| 55 | ) |
| 56 | |
| 57 | def run_backtest(data_dir: str = None, watermark_dir: str = None, venue: str = None, symbol: str = None,start: datetime = None,end: datetime = None,strategy_module: str = "strategy_template", signal_module: str = "signal_template",base_dir: str = None) -> Any: |
| 58 | svc = BinanceDatabase(data_root=data_dir,state_db=watermark_dir) |
| 59 | |
| 60 | start_ms = utc_ms(start) if start else utc_ms(datetime(2024, 1, 1)) |
| 61 | end_ms = utc_ms(end) if end else utc_ms(datetime(2025, 1, 1)) |
| 62 | |
| 63 | AgentStrategy = ClassLoader.load_class( |
| 64 | file_path=Path(base_dir) / "strategies" / f"{strategy_module}.py", |
| 65 | class_name=strategy_module, |
| 66 | ) |
| 67 | AgentSignal = ClassLoader.load_class( |
| 68 | file_path=Path(base_dir) / "signals" / f"{signal_module}.py", |
| 69 | class_name=signal_module, |
| 70 | ) |
| 71 | data = svc.query(venue=venue, symbol=symbol, start_ms=start_ms, end_ms=end_ms,as_="pandas",columns=["open_time","symbol","open","high","low","close","volume","quote_volume"],interval="1m") |
| 72 | data["trade_time"] = pd.to_datetime(data["open_time"], unit='ms', utc=True) |
| 73 | data.rename(columns={"symbol":"code","quote_volume":"amount"}, inplace=True) |
| 74 | data.drop(columns=["open_time"], inplace=True) |
| 75 | data.reset_index(drop=True, inplace=True) |
| 76 | |
| 77 | combo_data: pd.DataFrame = AgentSignal(data).fit() |
| 78 | combo_data.set_index("trade_time", inplace=True) |
| 79 | result = backtest_strategy( |
| 80 | data=combo_data, |
| 81 | code=symbol, |
| 82 | strategy=AgentStrategy, |
| 83 | strategy_kwargs=STRATEGY_PARAMS_ENV, |
| 84 | commission_kwargs=COMMISSION_ENV, |
| 85 | ) |
| 86 | |
| 87 | |
| 88 | ax = plot_cumulative_return(result,combo_data.query("code==@symbol")["close"], title=strategy_module + ' '+ signal_module) |
| 89 | save_path = Path(base_dir) / "cumulative_return.png" |
| 90 | plt.savefig(save_path) |
| 91 | plt.close(ax.figure) |
| 92 | return { |
| 93 | "sharpe_ratio": get_strategy_sharpe_ratio(result), |
| 94 | "cumulative_return (%)": get_strategy_cumulative_return(result).iloc[-1]*100, |
| 95 | "max_drawdown (%)": get_strategy_maxdrawdown(result)*100, |
| 96 | "win_rate (%)": get_strategy_win_rate(result).iloc[0]['win_rate']*100, |
| 97 | "total_commission (%)": get_strategy_total_commission(result)/COMMISSION_ENV["cash"] * 100, |
| 98 | "excess_return_ratio (%)": get_excess_return( |
| 99 | result, |
| 100 | combo_data.query("code==@symbol")["close"], |
| 101 | benchmark_is_return=False, |
| 102 | )*100, |
| 103 | # "cumulative_return_path": str(save_path) if base_dir else None |
| 104 | } |