import time from enum import Enum from typing import Tuple # import aiohttp from cvttpy_tools.tools.app import App from cvttpy_tools.tools.base import NamedObject from cvttpy_tools.tools.config import Config from cvttpy_tools.tools.logger import Log from cvttpy_tools.tools.timer import Timer from cvttpy_tools.tools.timeutils import NanoPerSec from cvttpy_tools.tools.web.rest_client import REST_RequestProcessor class TradingInstructionsSender(NamedObject): class TradingInstType(str, Enum): TARGET_POSITION = "TARGET_POSITION" DIRECT_ORDER = "DIRECT_ORDER" MARKET_MAKING = "MARKET_MAKING" NONE = "NONE" config_: Config ti_method_: str ti_url_: str health_check_method_: str health_check_url_: str def __init__(self, config: Config): self.config_ = config base_url = config.get_value("url", "ws://localhost:12346/ws") self.book_id_ = config.get_value("book_id", "") assert self.book_id_, "book_id is required" self.strategy_id_ = config.get_value("strategy_id", "") assert self.strategy_id_, "strategy_id is required" endpoint_uri = config.get_value("ti_endpoint/url", "/trading_instructions") endpoint_method = config.get_value("ti_endpoint/method", "POST") health_check_uri = config.get_value("health_check_endpoint/url", "/ping") health_check_method = config.get_value("health_check_endpoint/method", "GET") self.ti_method_ = endpoint_method self.ti_url_ = f"{base_url}{endpoint_uri}" self.health_check_method_ = health_check_method self.health_check_url_ = f"{base_url}{health_check_uri}" App.instance().add_call(App.Stage.Start, self._set_health_check_timer(), can_run_now=True) async def _set_health_check_timer(self) -> None: # TODO: configurable interval self.health_check_timer_ = Timer(is_periodic=True, period_interval=15, start_in_sec=0, func=self._health_check) Log.info(f"{self.fname()} Health check timer set to 15 seconds") async def _health_check(self) -> None: rqst = REST_RequestProcessor(method=self.health_check_method_, url=self.health_check_url_) async with rqst as (status, msg, headers): if status != 200: Log.error(f"{self.fname()} CVTT Service is not responding") async def send_tgt_positions(self, strength: float, base_asset: str, quote_asset: str) -> Tuple[int, str]: instr = { "type": self.TradingInstType.TARGET_POSITION.value, "book_id": self.book_id_, "strategy_id": self.strategy_id_, "issued_ts_ns": int(time.time() * NanoPerSec), "data": { "strength": strength, "base_asset": base_asset, "quote_asset": quote_asset, "user_data": {}, }, } rqst = REST_RequestProcessor(method=self.ti_method_, url=self.ti_url_, params=instr) async with rqst as (status, msg, headers): if status != 200: raise ConnectionError(f"Failed to send trading instructions: {msg}") return (status, msg)