from __future__ import annotations from functools import partial from typing import Dict, List from cvttpy_tools.settings.cvtt_types import JsonDictT from cvttpy_tools.tools.app import App from cvttpy_tools.tools.base import NamedObject from cvttpy_tools.tools.config import CvttAppConfig from cvttpy_tools.tools.logger import Log from pt_strategy.live.live_strategy import PtLiveStrategy from pt_strategy.live.pricer_md_client import PtMktDataClient from pt_strategy.live.ti_sender import TradingInstructionsSender # import sys # print("PYTHONPATH directories:") # for path in sys.path: # print(path) # from cvtt_client.mkt_data import (CvttPricerWebSockClient, # CvttPricesSubscription, MessageTypeT, # SubscriptionIdT) class PairTradingRunner(NamedObject): config_: CvttAppConfig instruments_: List[JsonDictT] live_strategy_: PtLiveStrategy pricer_client_: PtMktDataClient def __init__(self) -> None: self.instruments_ = [] App.instance().add_cmdline_arg( "--pair", type=str, required=True, help=( "Comma-separated pair of instrument symbols" " with exchange config name" " (e.g., PAIR-BTC-USD:BNBSPOT,PAIR-ETH-USD:BNBSPOT)" ), ) App.instance().add_call(App.Stage.Config, self._on_config()) App.instance().add_call(App.Stage.Run, self.run()) async def _on_config(self) -> None: self.config_ = CvttAppConfig.instance() # ------- PARSE INSTRUMENTS ------- instr_str = App.instance().get_argument("pair", "") if not instr_str: raise ValueError("Pair is required") instr_list = instr_str.split(",") for instr in instr_list: instr_parts = instr.split(":") if len(instr_parts) != 2: raise ValueError(f"Invalid pair format: {instr}") instrument_id = instr_parts[0] exchange_config_name = instr_parts[1] self.instruments_.append({ "exchange_config_name": exchange_config_name, "instrument_id": instrument_id }) assert len(self.instruments_) == 2, "Only two instruments are supported" Log.info(f"{self.fname()} Instruments: {self.instruments_}") # ------- CREATE TI (trading instructions) CLIENT ------- ti_config = self.config_.get_subconfig("ti_config", {}) self.ti_sender_ = TradingInstructionsSender(config=ti_config) Log.info(f"{self.fname()} TI client created: {self.ti_sender_}") # ------- CREATE STRATEGY ------- strategy_config = self.config_.get_value("strategy_config", {}) self.live_strategy_ = PtLiveStrategy( config=strategy_config, instruments=self.instruments_, ti_sender=self.ti_sender_ ) Log.info(f"{self.fname()} Strategy created: {self.live_strategy_}") # ------- CREATE PRICER CLIENT ------- pricer_config = self.config_.get_subconfig("pricer_config", {}) self.pricer_client_ = PtMktDataClient( live_strategy=self.live_strategy_, pricer_config=pricer_config ) Log.info(f"{self.fname()} CVTT Pricer client created: {self.pricer_client_}") async def run(self) -> None: Log.info(f"{self.fname()} ...") pass if __name__ == "__main__": App() CvttAppConfig() PairTradingRunner() App.instance().run()