86 lines
3.2 KiB
Python
86 lines
3.2 KiB
Python
from enum import Enum
|
|
from typing import Dict, Any, Tuple
|
|
import time
|
|
# import aiohttp
|
|
from cvttpy_base.tools.app import App
|
|
from cvttpy_base.tools.base import NamedObject
|
|
from cvttpy_base.tools.config import Config
|
|
from cvttpy_base.tools.logger import Log
|
|
from cvttpy_base.tools.web.rest_client import REST_RequestProcessor
|
|
from cvttpy_base.tools.timeutils import NanoPerSec
|
|
from cvttpy_base.tools.timer import Timer
|
|
|
|
|
|
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)
|
|
|
|
|