import argparse import asyncio import glob import importlib import os from datetime import date, datetime from typing import Any, Dict, List, Optional import hjson import pandas as pd from tools.data_loader import get_available_instruments_from_db, load_market_data from pt_trading.results import ( BacktestResult, create_result_database, store_config_in_database, store_results_in_database, ) from pt_trading.fit_methods import PairsTradingFitMethod from pt_trading.trading_pair import TradingPair def run_strategy( config: Dict, datafile: str, fit_method: PairsTradingFitMethod, instruments: List[str], ) -> BacktestResult: """ Run backtest for all pairs using the specified instruments. """ bt_result: BacktestResult = BacktestResult(config=config) def _create_pairs(config: Dict, instruments: List[str]) -> List[TradingPair]: nonlocal datafile all_indexes = range(len(instruments)) unique_index_pairs = [(i, j) for i in all_indexes for j in all_indexes if i < j] pairs = [] # Update config to use the specified instruments config_copy = config.copy() config_copy["instruments"] = instruments market_data_df = load_market_data( datafile=datafile, exchange_id=config_copy["exchange_id"], instruments=config_copy["instruments"], instrument_id_pfx=config_copy["instrument_id_pfx"], db_table_name=config_copy["db_table_name"], trading_hours=config_copy["trading_hours"], ) for a_index, b_index in unique_index_pairs: pair = fit_method.create_trading_pair( market_data=market_data_df, symbol_a=instruments[a_index], symbol_b=instruments[b_index], ) pairs.append(pair) return pairs pairs_trades = [] for pair in _create_pairs(config, instruments): single_pair_trades = fit_method.run_pair( pair=pair, config=config, bt_result=bt_result ) if single_pair_trades is not None and len(single_pair_trades) > 0: pairs_trades.append(single_pair_trades) # Check if result_list has any data before concatenating if len(pairs_trades) == 0: print("No trading signals found for any pairs") return bt_result result = pd.concat(pairs_trades, ignore_index=True) result["time"] = pd.to_datetime(result["time"]) result = result.set_index("time").sort_index() bt_result.collect_single_day_results(result) return bt_result def main() -> None: # Load config # Subscribe to CVTT market data # On snapshot (with historical data) - create trading strategy with market data dateframe async def on_message(message_type: MessageTypeT, subscr_id: SubscriptionIdT, message: Dict, instrument_id: str) -> None: print(f"{message_type=} {subscr_id=} {instrument_id}") if message_type == "md_aggregate": aggr = message.get("md_aggregate", []) print(f"[{aggr['tstamp'][:19]}] *** RLTM *** {message}") elif message_type == "historical_md_aggregate": for aggr in message.get("historical_data", []): print(f"[{aggr['tstamp'][:19]}] *** HIST *** {aggr}") else: print(f"Unknown message type: {message_type}") if __name__ == "__main__": asyncio.run(main())