diff --git a/gogogo/data_fetcher.py b/gogogo/data_fetcher.py index 2e8419e..7d9e75d 100644 --- a/gogogo/data_fetcher.py +++ b/gogogo/data_fetcher.py @@ -54,7 +54,7 @@ def get_processed_data(): # 限制为最近一年数据 end_date = smic_data.index.max() - start_date = end_date - pd.Timedelta(days=360) + start_date = end_date - pd.Timedelta(days=360*3) print(f"\n限制回测时间范围: {start_date} 到 {end_date}") diff --git a/gogogo/result_visualizer.py b/gogogo/result_visualizer.py index 0efd595..d937ebc 100644 --- a/gogogo/result_visualizer.py +++ b/gogogo/result_visualizer.py @@ -2,14 +2,12 @@ import vectorbt as vbt import pandas as pd import matplotlib.pyplot as plt -from strategy_executor import execute_strategy -from strategy_executor import * +from strategy_executor import generate_strategy, create_portfolio, create_real_stock_portfolio # 设置中文显示 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False - def plot_results(strategy_data, portfolio): """绘制结果图表""" price_ratio = strategy_data['price_ratio'] @@ -177,10 +175,11 @@ def print_statistics(strategy_data, portfolio): print(f"做空信号次数: {short_count}") print(f"总信号次数: {total_signals}") + def main(): """主函数""" - # 执行策略 - strategy_data = execute_strategy() + # 生成策略 + strategy_data = generate_strategy() # 创建基于比率的投资组合(用于分析) ratio_portfolio = create_portfolio(strategy_data) @@ -188,45 +187,18 @@ def main(): # 创建基于真实股票的投资组合(用于真实收益计算) stock_portfolio = create_real_stock_portfolio(strategy_data) - # 绘制基于比率的结果 - plot_results(strategy_data, ratio_portfolio) - # 打印基于比率的统计 print_statistics(strategy_data, ratio_portfolio) # 打印真实股票组合的统计 - if stock_portfolio is not None: - print("\n" + "="*60) - print("=== 真实股票投资组合表现 ===") - print("="*60) - - try: - stats = stock_portfolio.stats() - print(f"总收益率: {stats.get('Total Return [%]', 'N/A')}%") - print(f"年化收益率: {stats.get('Annual Return [%]', 'N/A')}%") - print(f"夏普比率: {stats.get('Sharpe Ratio', 'N/A')}") - print(f"最大回撤: {stats.get('Max Drawdown [%]', 'N/A')}%") - print(f"最终组合价值: {stock_portfolio.value().iloc[-1]:.2f}") - print(f"总盈亏: {stock_portfolio.value().iloc[-1] - strategy_data['initial_cash']:.2f}") - - # 绘制真实股票组合的净值曲线 - plt.figure(figsize=(12, 6)) - plt.plot(stock_portfolio.value().index, stock_portfolio.value(), - label='真实股票组合净值', linewidth=2, color='darkgreen') - plt.axhline(y=strategy_data['initial_cash'], color='red', linestyle='--', - alpha=0.7, label=f'初始资金({strategy_data["initial_cash"]})') - plt.title('真实股票配对交易组合净值') - plt.ylabel('组合价值') - plt.xlabel('日期') - plt.legend() - plt.grid(True, alpha=0.3) - plt.tight_layout() - plt.show() - - except Exception as e: - print(f"分析真实股票组合时出错: {e}") + print(stock_portfolio['SMIC'].stats()) + print(stock_portfolio['HHIC'].stats()) + # 绘制基于比率的结果 + plot_results(strategy_data, ratio_portfolio) + print("程序执行完成!") if __name__ == "__main__": - main() \ No newline at end of file + main() + \ No newline at end of file diff --git a/gogogo/strategy_executor.py b/gogogo/strategy_executor.py index 11a4844..aa7e6fe 100644 --- a/gogogo/strategy_executor.py +++ b/gogogo/strategy_executor.py @@ -132,8 +132,8 @@ def generate_stock_sizes(signals, close_smic, close_hhic, initial_cash=100000, p return size_df -def execute_strategy(): - """执行配对交易策略""" +def generate_strategy(): + """生成配对交易策略""" # 获取数据 smic_data, hhic_data = get_processed_data() @@ -257,13 +257,80 @@ def create_real_stock_portfolio(strategy_data): traceback.print_exc() return None +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: 做空价差 + + for i in range(len(signals)): + if i < 20: # 跳过布林带计算期 + continue + + signal = signals.iloc[i] + 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: # 平仓 + # 平掉所有仓位 + 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 + + current_position = 0 + + # 创建size DataFrame + size_df = pd.DataFrame({ + 'SMIC': smic_size, + 'HHIC': hhic_size + }) + + return size_df + + if __name__ == "__main__": - strategy_data = execute_strategy() + strategy_data = generate_strategy() # 测试基于比率的投资组合 ratio_portfolio = create_portfolio(strategy_data) # 测试基于真实股票的投资组合 stock_portfolio = create_real_stock_portfolio(strategy_data) - - print("策略执行完成!") \ No newline at end of file + + print("策略生成完成!") \ No newline at end of file