dev progress

This commit is contained in:
2025-12-31 08:03:26 +00:00
parent 121c85def0
commit 69a0b19e9f
5 changed files with 117 additions and 75 deletions
+70 -37
View File
@@ -1,22 +1,28 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import Any, Dict, List, Optional
from typing import Any, Dict, List, Optional, cast
from enum import Enum
import pandas as pd
# ---
from cvttpy_tools.base import NamedObject
from cvttpy_tools.app import App
from cvttpy_tools.config import Config
from cvttpy_tools.settings.cvtt_types import IntervalSecT
from cvttpy_tools.timeutils import SecPerHour
# ---
from cvttpy_trading.trading.instrument import ExchangeInstrument
from cvttpy_trading.trading.mkt_data.md_summary import MdTradesAggregate
# ---
from pairs_trading.lib.pt_strategy.model_data_policy import ModelDataPolicy
from pairs_trading.lib.pt_strategy.pt_model import Prediction
from pairs_trading.lib.pt_strategy.trading_pair import PairState, TradingPair
from pairs_trading.apps.pairs_trader import PairsTrader
"""
--config=pair.cfg
--pair=PAIR-BTC-USDT:COINBASE_AT,PAIR-ETH-USDT:COINBASE_AT
@@ -26,6 +32,7 @@ from pairs_trading.apps.pairs_trader import PairsTrader
class TradingInstructionType(Enum):
TARGET_POSITION = "TARGET_POSITION"
@dataclass
class TradingInstruction(NamedObject):
type_: TradingInstructionType
@@ -34,57 +41,84 @@ class TradingInstruction(NamedObject):
class PtLiveStrategy(NamedObject):
config_: Dict[str, Any]
config_: Config
instruments_: List[ExchangeInstrument]
interval_sec_: IntervalSecT
history_depth_sec_: IntervalSecT
open_threshold_: float
close_threshold_: float
trading_pair_: TradingPair
model_data_policy_: ModelDataPolicy
pairs_trader_: PairsTrader
# ti_sender_: TradingInstructionsSender
# for presentation: history of prediction values and trading signals
predictions_: pd.DataFrame
trading_signals_: pd.DataFrame
predictions_df_: pd.DataFrame
trading_signals_df_: pd.DataFrame
def __init__(
self,
config: Dict[str, Any],
instruments: List[Dict[str, str]],
config: Config,
instruments: List[ExchangeInstrument],
pairs_trader: PairsTrader,
):
self.config_ = config
self.trading_pair_ = TradingPair(config=config, instruments=instruments)
self.predictions_ = pd.DataFrame()
self.trading_signals_ = pd.DataFrame()
self.trading_pair_ = TradingPair(
config=cast(Dict[str, Any], config.data()),
instruments=[{"instrument_id": ei.instrument_id()} for ei in instruments],
)
self.predictions_df_ = pd.DataFrame()
self.trading_signals_df_ = pd.DataFrame()
self.pairs_trader_ = pairs_trader
import copy
# modified config must be passed to PtMarketData
config_copy = copy.deepcopy(config)
config_copy["instruments"] = instruments
self.config_ = config_copy
App.instance().add_call(stage=App.Stage.Config, func=self._on_config(), can_run_now=True)
self.config_ = Config(json_src=copy.deepcopy(config.data()))
self.instruments_ = instruments
App.instance().add_call(
stage=App.Stage.Config, func=self._on_config(), can_run_now=True
)
async def _on_config(self) -> None:
self.interval_sec_ = self.config_.get_value("interval_sec", 0)
self.history_depth_sec_ = (
self.config_.get_value("history_depth_hours", 0) * SecPerHour
)
await self.pairs_trader_.subscribe_md()
self.model_data_policy_ = ModelDataPolicy.create(
self.config_, is_real_time=True, pair=self.trading_pair_
)
self.open_threshold_ = self.config_.get("dis-equilibrium_open_trshld", 0.0)
assert self.open_threshold_ > 0, "open_threshold must be greater than 0"
self.close_threshold_ = self.config_.get("dis-equilibrium_close_trshld", 0.0)
assert self.close_threshold_ > 0, "close_threshold must be greater than 0"
self.open_threshold_ = self.config_.get_value(
"dis-equilibrium_open_trshld", 0.0
)
self.close_threshold_ = self.config_.get_value(
"dis-equilibrium_close_trshld", 0.0
)
assert (
self.open_threshold_ > 0
), "dis-equilibrium_open_trshld must be greater than 0"
assert (
self.close_threshold_ > 0
), "dis-equilibrium_close_trshld must be greater than 0"
def __repr__(self) -> str:
return f"{self.classname()}: trading_pair={self.trading_pair_}, mdp={self.model_data_policy_.__class__.__name__}, "
async def on_mkt_data_hist_snapshot(self, hist_aggr: List[MdTradesAggregate]) -> None:
async def on_mkt_data_hist_snapshot(
self, hist_aggr: List[MdTradesAggregate]
) -> None:
# Log.info(f"on_mkt_data_hist_snapshot: {aggr}")
# await self.pt_mkt_data_.on_mkt_data_hist_snapshot(snapshot=aggr)
pass # URGENT PtiveStrategy.on_mkt_data_hist_snapshot()
pass # URGENT PtiveStrategy.on_mkt_data_hist_snapshot()
async def on_mkt_data_update(self, aggr: MdTradesAggregate) -> None:
# if market_data_df is not None:
@@ -105,18 +139,18 @@ class PtLiveStrategy(NamedObject):
# if len(trading_instructions) > 0:
# await self._send_trading_instructions(trading_instructions)
# # trades = self._create_trades(prediction=prediction, last_row=market_data_df.iloc[-1])
pass # URGENT
pass # URGENT
def interval_sec(self) -> IntervalSecT:
return 60 # URGENT use config
return self.interval_sec_
def history_depth_sec(self) -> IntervalSecT:
return 3600 * 60 * 2 # URGENT use config
return self.history_depth_sec_
async def _send_trading_instructions(
self, trading_instructions: List[TradingInstruction]
) -> None:
pass # URGENT implement _send_trading_instructions
pass # URGENT implement _send_trading_instructions
def _create_trading_instructions(
self, prediction: Prediction, last_row: pd.Series
@@ -135,7 +169,7 @@ class PtLiveStrategy(NamedObject):
elif pair.is_open():
if abs_scaled_disequilibrium <= self.close_threshold_:
trd_instructions = self._create_close_trade_instructions(
pair, row=last_row #, prediction=prediction
pair, row=last_row # , prediction=prediction
)
elif pair.to_stop_close_conditions(predicted_row=last_row):
trd_instructions = self._create_close_trade_instructions(
@@ -204,16 +238,15 @@ class PtLiveStrategy(NamedObject):
"signed_scaled_disequilibrium": scaled_disequilibrium,
# "pair": pair,
}
ti: List[TradingInstruction] =self._create_trading_instructions(
prediction=prediction, last_row=row
ti: List[TradingInstruction] = self._create_trading_instructions(
prediction=prediction, last_row=row
)
return ti
def _create_close_trade_instructions(
self, pair: TradingPair, row: pd.Series #, prediction: Prediction
self, pair: TradingPair, row: pd.Series # , prediction: Prediction
) -> List[TradingInstruction]:
return [] # URGENT implement _create_close_trade_instructions
return [] # URGENT implement _create_close_trade_instructions
def _handle_outstanding_positions(self) -> Optional[pd.DataFrame]:
trades = None
@@ -223,7 +256,7 @@ class PtLiveStrategy(NamedObject):
if pair.user_data_["state"] == PairState.OPEN:
print(f"{pair}: *** Position is NOT CLOSED. ***")
# outstanding positions
if self.config_["close_outstanding_positions"]:
if self.config_.key_exists("close_outstanding_positions"):
close_position_row = pd.Series(pair.market_data_.iloc[-2])
# close_position_row["disequilibrium"] = 0.0
# close_position_row["scaled_disequilibrium"] = 0.0