解决仓位不匹配,用到杠杆的问题
This commit is contained in:
@ -223,21 +223,9 @@ def print_trade_orders(strategy_data, stock_portfolio):
|
||||
print(f" 总订单数: {len(column_orders)}")
|
||||
print(f" 买入订单: {len(buy_orders)}")
|
||||
print(f" 卖出订单: {len(sell_orders)}")
|
||||
print(f" 总交易金额: {column_orders['Size'].abs().sum():.2f} 股")
|
||||
print(f" 总交易股数: {column_orders['Size'].abs().sum():.2f} 股")
|
||||
print(f" 总手续费: {column_orders['Fees'].sum():.2f}")
|
||||
|
||||
# 按日期分组统计
|
||||
if time_column:
|
||||
print(f"\n【按日期统计】")
|
||||
daily_orders = orders_sorted.groupby(time_column).agg({
|
||||
'Column': 'count',
|
||||
'Size': 'sum',
|
||||
'Fees': 'sum'
|
||||
}).rename(columns={'Column': '订单数'})
|
||||
|
||||
print(daily_orders.to_string())
|
||||
else:
|
||||
print(f"\n【按日期统计】- 未找到时间列")
|
||||
|
||||
|
||||
# 重置pandas显示选项
|
||||
pd.reset_option('display.max_rows')
|
||||
|
||||
@ -7,6 +7,7 @@ from data_fetcher import get_processed_data
|
||||
def calculate_ratio_signals(ratio_series, window=20, num_std=2):
|
||||
"""
|
||||
基于价格比率计算配对交易信号
|
||||
优化信号逻辑,避免过于频繁的交易
|
||||
"""
|
||||
# 计算布林带
|
||||
ratio_ma = ratio_series.rolling(window=window).mean()
|
||||
@ -16,25 +17,36 @@ def calculate_ratio_signals(ratio_series, window=20, num_std=2):
|
||||
lower_band = ratio_ma - num_std * ratio_std
|
||||
|
||||
# 生成交易信号
|
||||
# 1: 做多价差 (买中芯/卖华虹) -> 买入比率
|
||||
# -1: 做空价差 (卖中芯/买华虹) -> 卖空比率
|
||||
# 0: 平仓
|
||||
signals = pd.Series(0, index=ratio_series.index, name='signal')
|
||||
current_signal = 0
|
||||
|
||||
# 当比率突破下轨时做多价差 -> 买入比率
|
||||
long_condition = (ratio_series < lower_band) & (ratio_ma.notna())
|
||||
signals[long_condition] = 1
|
||||
|
||||
# 当比率突破上轨时做空价差 -> 卖空比率
|
||||
short_condition = (ratio_series > upper_band) & (ratio_ma.notna())
|
||||
signals[short_condition] = -1
|
||||
|
||||
# 当比率回归均值时平仓
|
||||
close_condition = (ratio_series.between(lower_band, upper_band)) & (signals.shift(1) != 0)
|
||||
signals[close_condition] = 0
|
||||
for i in range(len(ratio_series)):
|
||||
if i < window: # 跳过布林带计算期
|
||||
continue
|
||||
|
||||
ratio_val = ratio_series.iloc[i]
|
||||
ma_val = ratio_ma.iloc[i]
|
||||
|
||||
# 当前无仓位时的开仓条件
|
||||
if current_signal == 0:
|
||||
if ratio_val < lower_band.iloc[i]: # 比率突破下轨,做多价差
|
||||
signals.iloc[i] = 1
|
||||
current_signal = 1
|
||||
elif ratio_val > upper_band.iloc[i]: # 比率突破上轨,做空价差
|
||||
signals.iloc[i] = -1
|
||||
current_signal = -1
|
||||
|
||||
# 当前有仓位时的平仓条件
|
||||
elif current_signal != 0:
|
||||
# 当比率回归均值时平仓
|
||||
if (current_signal == 1 and ratio_val >= ma_val) or \
|
||||
(current_signal == -1 and ratio_val <= ma_val):
|
||||
signals.iloc[i] = 0
|
||||
current_signal = 0
|
||||
|
||||
return signals, ratio_ma, upper_band, lower_band
|
||||
|
||||
|
||||
def generate_ratio_size(signals, price_ratio, position_size=0.5):
|
||||
"""
|
||||
生成比率交易的size数据
|
||||
@ -69,13 +81,15 @@ def generate_ratio_size(signals, price_ratio, position_size=0.5):
|
||||
def generate_stock_sizes(signals, close_smic, close_hhic, initial_cash=100000, position_ratio=0.5):
|
||||
"""
|
||||
生成真实股票交易的size数据
|
||||
返回两个DataFrame:smic_size和hhic_size
|
||||
确保每次配对交易都是等市值对冲,避免使用杠杆
|
||||
"""
|
||||
# 创建空的size Series
|
||||
smic_size = pd.Series(0.0, index=signals.index, name='SMIC')
|
||||
hhic_size = pd.Series(0.0, index=signals.index, name='HHIC')
|
||||
|
||||
current_position = 0 # 0: 无仓位, 1: 做多价差, -1: 做空价差
|
||||
smic_position = 0.0 # 当前中芯持仓数量
|
||||
hhic_position = 0.0 # 当前华虹持仓数量
|
||||
|
||||
for i in range(len(signals)):
|
||||
if i < 20: # 跳过布林带计算期
|
||||
@ -85,44 +99,63 @@ def generate_stock_sizes(signals, close_smic, close_hhic, initial_cash=100000, p
|
||||
smic_price = close_smic.iloc[i]
|
||||
hhic_price = close_hhic.iloc[i]
|
||||
|
||||
if signal == 1 and current_position != 1: # 做多价差:买入中芯,卖空华虹
|
||||
# 计算每只股票的仓位价值
|
||||
position_value = initial_cash * position_ratio
|
||||
|
||||
# 做多中芯国际
|
||||
smic_shares = position_value / smic_price
|
||||
smic_size.iloc[i] = smic_shares
|
||||
|
||||
# 做空华虹半导体
|
||||
hhic_shares = -position_value / hhic_price
|
||||
hhic_size.iloc[i] = hhic_shares
|
||||
|
||||
current_position = 1
|
||||
|
||||
elif signal == -1 and current_position != -1: # 做空价差:卖空中芯,买入华虹
|
||||
# 计算每只股票的仓位价值
|
||||
position_value = initial_cash * position_ratio
|
||||
|
||||
# 做空中芯国际
|
||||
smic_shares = -position_value / smic_price
|
||||
smic_size.iloc[i] = smic_shares
|
||||
|
||||
# 做多华虹半导体
|
||||
hhic_shares = position_value / hhic_price
|
||||
hhic_size.iloc[i] = hhic_shares
|
||||
|
||||
current_position = -1
|
||||
|
||||
elif signal == 0 and current_position != 0: # 平仓
|
||||
# 平仓条件:信号为0且当前有仓位
|
||||
if signal == 0 and current_position != 0:
|
||||
# 平掉所有仓位
|
||||
if current_position == 1: # 平掉做多价差仓位
|
||||
smic_size.iloc[i] = -smic_size.shift(1).iloc[i] if i > 0 else 0
|
||||
hhic_size.iloc[i] = -hhic_size.shift(1).iloc[i] if i > 0 else 0
|
||||
elif current_position == -1: # 平掉做空价差仓位
|
||||
smic_size.iloc[i] = -smic_size.shift(1).iloc[i] if i > 0 else 0
|
||||
hhic_size.iloc[i] = -hhic_size.shift(1).iloc[i] if i > 0 else 0
|
||||
if smic_position != 0:
|
||||
smic_size.iloc[i] = -smic_position
|
||||
smic_position = 0.0
|
||||
if hhic_position != 0:
|
||||
hhic_size.iloc[i] = -hhic_position
|
||||
hhic_position = 0.0
|
||||
|
||||
current_position = 0
|
||||
continue
|
||||
|
||||
# 开仓条件:只有当前无仓位时才开新仓
|
||||
if current_position == 0:
|
||||
if signal == 1: # 做多价差:买入中芯,卖空华虹
|
||||
# 计算每只股票的仓位价值(等市值对冲)
|
||||
position_value = initial_cash * position_ratio
|
||||
|
||||
# 做多中芯国际
|
||||
smic_shares = position_value / smic_price
|
||||
smic_size.iloc[i] = smic_shares
|
||||
smic_position = smic_shares
|
||||
|
||||
# 做空华虹半导体
|
||||
hhic_shares = -position_value / hhic_price
|
||||
hhic_size.iloc[i] = hhic_shares
|
||||
hhic_position = hhic_shares
|
||||
|
||||
current_position = 1
|
||||
print(f"开仓做多价差: {signals.index[i]} - 买入SMIC {smic_shares:.2f}股 @{smic_price:.2f}, 卖空HHIC {abs(hhic_shares):.2f}股 @{hhic_price:.2f}")
|
||||
|
||||
elif signal == -1: # 做空价差:卖空中芯,买入华虹
|
||||
# 计算每只股票的仓位价值(等市值对冲)
|
||||
position_value = initial_cash * position_ratio
|
||||
|
||||
# 做空中芯国际
|
||||
smic_shares = -position_value / smic_price
|
||||
smic_size.iloc[i] = smic_shares
|
||||
smic_position = smic_shares
|
||||
|
||||
# 做多华虹半导体
|
||||
hhic_shares = position_value / hhic_price
|
||||
hhic_size.iloc[i] = hhic_shares
|
||||
hhic_position = hhic_shares
|
||||
|
||||
current_position = -1
|
||||
print(f"开仓做空价差: {signals.index[i]} - 卖空SMIC {abs(smic_shares):.2f}股 @{smic_price:.2f}, 买入HHIC {hhic_shares:.2f}股 @{hhic_price:.2f}")
|
||||
|
||||
# 最后检查是否有未平仓的仓位,如果有则在最后一天平仓
|
||||
if current_position != 0:
|
||||
last_index = len(signals) - 1
|
||||
if smic_position != 0:
|
||||
smic_size.iloc[last_index] = -smic_position
|
||||
if hhic_position != 0:
|
||||
hhic_size.iloc[last_index] = -hhic_position
|
||||
print(f"最终平仓: {signals.index[last_index]} - 平掉所有剩余仓位")
|
||||
|
||||
# 创建size DataFrame
|
||||
size_df = pd.DataFrame({
|
||||
|
||||
Reference in New Issue
Block a user