dev progress

This commit is contained in:
Oleg Sheynin
2025-12-28 19:30:00 +00:00
parent ba2a6cd2eb
commit 2e32b26fad
11 changed files with 122 additions and 173 deletions
+41 -19
View File
@@ -7,17 +7,18 @@ from enum import Enum
import pandas as pd
# ---
from cvttpy_tools.base import NamedObject
from cvttpy_tools.app import App
from cvttpy_tools.logger import Log
from cvttpy_tools.settings.cvtt_types import JsonDictT
# ---
from cvttpy_trading.trading.instrument import ExchangeInstrument
from cvttpy_trading.trading.mkt_data.md_summary import MdTradesAggregate
# ---
from pairs_trading.lib.pt_strategy.live.ti_sender import TradingInstructionsSender
from pairs_trading.lib.pt_strategy.model_data_policy import ModelDataPolicy
from pairs_trading.lib.pt_strategy.pt_market_data import RealTimeMarketData
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
from pairs_trading.lib.pt_strategy.pt_market_data import RealTimeMarketData
"""
--config=pair.cfg
--pair=PAIR-BTC-USDT:COINBASE_AT,PAIR-ETH-USDT:COINBASE_AT
@@ -38,8 +39,10 @@ class PtLiveStrategy(NamedObject):
config_: Dict[str, Any]
trading_pair_: TradingPair
model_data_policy_: ModelDataPolicy
pairs_trader_: PairsTrader
pt_mkt_data_: RealTimeMarketData
ti_sender_: TradingInstructionsSender
# ti_sender_: TradingInstructionsSender
# for presentation: history of prediction values and trading signals
predictions_: pd.DataFrame
@@ -49,23 +52,29 @@ class PtLiveStrategy(NamedObject):
self,
config: Dict[str, Any],
instruments: List[Dict[str, str]],
ti_sender: TradingInstructionsSender,
pairs_trader: PairsTrader,
):
self.config_ = config
self.trading_pair_ = TradingPair(config=config, instruments=instruments)
self.predictions_ = pd.DataFrame()
self.trading_signals_ = pd.DataFrame()
self.ti_sender_ = ti_sender
self.pairs_trader_ = pairs_trader
import copy
# modified config must be passed to PtMarketData
config_copy = copy.deepcopy(config)
config_copy["instruments"] = instruments
self.pt_mkt_data_ = RealTimeMarketData(config=config_copy)
self.config_ = config_copy
App.instance().add_call(stage=App.Stage.Config, func=self._on_config(), can_run_now=True)
async def _on_config(self) -> None:
await self.pairs_trader_.subscribe_md()
self.model_data_policy_ = ModelDataPolicy.create(
config, is_real_time=True, pair=self.trading_pair_
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"
@@ -75,12 +84,12 @@ class PtLiveStrategy(NamedObject):
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, aggr: JsonDictT) -> None:
Log.info(f"on_mkt_data_hist_snapshot: {aggr}")
await self.pt_mkt_data_.on_mkt_data_hist_snapshot(snapshot=aggr)
pass
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()
async def on_mkt_data_update(self, aggr: JsonDictT) -> None:
async def on_mkt_data_update(self, aggr: MdTradesAggregate) -> None:
market_data_df = await self.pt_mkt_data_.on_mkt_data_update(update=aggr)
if market_data_df is not None:
self.trading_pair_.market_data_ = market_data_df
@@ -100,7 +109,6 @@ 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])
# URGENT implement this
pass
async def _send_trading_instructions(
@@ -125,7 +133,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(
@@ -142,15 +150,25 @@ class PtLiveStrategy(NamedObject):
if scaled_disequilibrium > 0:
side_a = "SELL"
trd_inst_a = TradingInstruction(
type=TradingInstructionType.TARGET_POSITION,
exch_instr=pair.get_instrument_a(),
specifics={"side": "SELL", "strength": -1},
type_=TradingInstructionType.TARGET_POSITION,
exch_instr_=pair.get_instrument_a(),
specifics_={"side": "SELL", "strength": -1},
)
side_b = "BUY"
else:
side_a = "BUY"
side_b = "SELL"
colname_a, colname_b = pair.exec_prices_colnames()
px_a = row[f"{colname_a}"]
px_b = row[f"{colname_b}"]
tstamp = row["tstamp"]
diseqlbrm = prediction.disequilibrium_
scaled_disequilibrium = prediction.scaled_disequilibrium_
df = self._trades_df()
# save closing sides
pair.user_data_["open_side_a"] = side_a # used in oustanding positions
pair.user_data_["open_side_b"] = side_b
@@ -184,7 +202,11 @@ class PtLiveStrategy(NamedObject):
"signed_scaled_disequilibrium": scaled_disequilibrium,
# "pair": pair,
}
return df
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
+6 -2
View File
@@ -3,8 +3,12 @@ from __future__ import annotations
from typing import Any, Dict, List, Optional
import pandas as pd
# ---
from cvttpy_tools.settings.cvtt_types import JsonDictT
from tools.data_loader import load_market_data
# ---
from cvttpy_trading.trading.mkt_data.md_summary import MdTradesAggregate
# ---
from pairs_trading.lib.tools.data_loader import load_market_data
class PtMarketData():
@@ -199,7 +203,7 @@ class RealTimeMarketData(PtMarketData):
pass
async def on_mkt_data_update(self, update: JsonDictT) -> Optional[pd.DataFrame]:
async def on_mkt_data_update(self, update: MdTradesAggregate) -> Optional[pd.DataFrame]:
# URGENT
# make sure update has both instruments
# create DataFrame tmp1 from update
+2 -2
View File
@@ -3,8 +3,8 @@ from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Any, Dict, cast
from pt_strategy.prediction import Prediction
from pairs_trading.lib.pt_strategy.prediction import Prediction
from pairs_trading.lib.pt_strategy.trading_pair import TradingPair
class PairsTradingModel(ABC):
+14 -3
View File
@@ -6,8 +6,12 @@ from typing import Any, Dict, List
import pandas as pd
from pt_strategy.model_data_policy import DataWindowParams
from pt_strategy.prediction import Prediction
# ---
from cvttpy_trading.trading.instrument import ExchangeInstrument
# ---
from pairs_trading.lib.pt_strategy.model_data_policy import DataWindowParams
from pairs_trading.lib.pt_strategy.prediction import Prediction
from pairs_trading.lib.pt_strategy.models import PairsTradingModel
class PairState(Enum):
@@ -44,6 +48,9 @@ class TradingPair:
user_data_: Dict[str, Any]
exch_inst_a_: ExchangeInstrument
exch_inst_b_: ExchangeInstrument
def __init__(
self,
config: Dict[str, Any],
@@ -190,7 +197,11 @@ class TradingPair:
"last_value": last_px * shares,
})
def get_instrument_a(self) -> ExchangeInstrument:
return self.exch_inst_a_
def get_instrument_b(self) -> ExchangeInstrument:
return self.exch_inst_b_
def run(self, market_data: pd.DataFrame, data_params: DataWindowParams) -> Prediction: # type: ignore[assignment]
self.market_data_ = market_data[data_params.training_start_index:data_params.training_start_index + data_params.training_size]
return self.model_.predict(pair=self)