102 lines
3.4 KiB
Python
102 lines
3.4 KiB
Python
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['tstmp'][:19]}] *** RLTM *** {message}")
|
|
elif message_type == "historical_md_aggregate":
|
|
for aggr in message.get("historical_data", []):
|
|
print(f"[{aggr['tstmp'][:19]}] *** HIST *** {aggr}")
|
|
else:
|
|
print(f"Unknown message type: {message_type}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|