progress
This commit is contained in:
@@ -10,19 +10,23 @@ 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_tools.settings.cvtt_types import BookIdT, IntervalSecT
|
||||
from cvttpy_tools.timeutils import SecPerHour, current_nanoseconds
|
||||
from cvttpy_tools.logger import Log
|
||||
|
||||
# ---
|
||||
from cvttpy_trading.trading.instrument import ExchangeInstrument
|
||||
from cvttpy_trading.trading.mkt_data.md_summary import MdTradesAggregate
|
||||
from cvttpy_trading.trading.trading_instructions import TradingInstructions
|
||||
from cvttpy_trading.trading.accounting.cvtt_book import CvttBook
|
||||
from cvttpy_trading.trading.trading_instructions import TargetPositionSignal
|
||||
|
||||
# ---
|
||||
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.lib.pt_strategy.trading_pair import LiveTradingPair
|
||||
from pairs_trading.apps.pairs_trader import PairsTrader
|
||||
from pairs_trading.lib.pt_strategy.pt_market_data import LiveMarketData
|
||||
|
||||
|
||||
"""
|
||||
@@ -51,7 +55,7 @@ class PtLiveStrategy(NamedObject):
|
||||
open_threshold_: float
|
||||
close_threshold_: float
|
||||
|
||||
trading_pair_: TradingPair
|
||||
trading_pair_: LiveTradingPair
|
||||
model_data_policy_: ModelDataPolicy
|
||||
pairs_trader_: PairsTrader
|
||||
|
||||
@@ -60,28 +64,29 @@ class PtLiveStrategy(NamedObject):
|
||||
# for presentation: history of prediction values and trading signals
|
||||
predictions_df_: pd.DataFrame
|
||||
trading_signals_df_: pd.DataFrame
|
||||
# book_: CvttBook
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config: Config,
|
||||
instruments: List[ExchangeInstrument],
|
||||
pairs_trader: PairsTrader,
|
||||
):
|
||||
|
||||
self.trading_pair_ = TradingPair(
|
||||
config=cast(Dict[str, Any], config.data()),
|
||||
instruments=[{"instrument_id": ei.instrument_id()} for ei in instruments],
|
||||
self.pairs_trader_ = pairs_trader
|
||||
self.trading_pair_ = LiveTradingPair(
|
||||
config=config,
|
||||
instruments=self.pairs_trader_.instruments_,
|
||||
)
|
||||
self.predictions_df_ = pd.DataFrame()
|
||||
self.trading_signals_df_ = pd.DataFrame()
|
||||
self.pairs_trader_ = pairs_trader
|
||||
# self.book_ = book
|
||||
|
||||
import copy
|
||||
|
||||
# modified config must be passed to PtMarketData
|
||||
self.config_ = Config(json_src=copy.deepcopy(config.data()))
|
||||
|
||||
self.instruments_ = instruments
|
||||
self.instruments_ = self.pairs_trader_.instruments_
|
||||
|
||||
App.instance().add_call(
|
||||
stage=App.Stage.Config, func=self._on_config(), can_run_now=True
|
||||
@@ -95,9 +100,6 @@ class PtLiveStrategy(NamedObject):
|
||||
|
||||
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_value(
|
||||
"dis-equilibrium_open_trshld", 0.0
|
||||
)
|
||||
@@ -121,13 +123,22 @@ class PtLiveStrategy(NamedObject):
|
||||
if not self._is_md_actual(hist_aggr=hist_aggr):
|
||||
return
|
||||
|
||||
market_data_df: Optional[pd.DataFrame] = self._create_md_pdf(hist_aggr=hist_aggr)
|
||||
if market_data_df is None:
|
||||
market_data_df: pd.DataFrame = self._create_md_df(hist_aggr=hist_aggr)
|
||||
if len(market_data_df) == 0:
|
||||
Log.warning(f"{self.fname()} Unable to create market data df")
|
||||
return
|
||||
|
||||
self.trading_pair_.market_data_ = market_data_df
|
||||
self.model_data_policy_.advance()
|
||||
self.model_data_policy_ = ModelDataPolicy.create(
|
||||
self.config_,
|
||||
is_real_time=True,
|
||||
pair=self.trading_pair_,
|
||||
mkt_data=market_data_df,
|
||||
)
|
||||
assert (
|
||||
self.model_data_policy_ is not None
|
||||
), f"{self.fname()}: Unable to create ModelDataPolicy"
|
||||
|
||||
prediction = self.trading_pair_.run(
|
||||
market_data_df, self.model_data_policy_.advance()
|
||||
)
|
||||
@@ -135,7 +146,7 @@ class PtLiveStrategy(NamedObject):
|
||||
[self.predictions_df_, prediction.to_df()], ignore_index=True
|
||||
)
|
||||
|
||||
trading_instructions: Optional[TradingInstructions] = (
|
||||
trading_instructions: List[TradingInstructions] = (
|
||||
self._create_trading_instructions(
|
||||
prediction=prediction, last_row=market_data_df.iloc[-1]
|
||||
)
|
||||
@@ -144,10 +155,74 @@ class PtLiveStrategy(NamedObject):
|
||||
await self._send_trading_instructions(trading_instructions)
|
||||
|
||||
def _is_md_actual(self, hist_aggr: List[MdTradesAggregate]) -> bool:
|
||||
return False # URGENT _is_md_actual
|
||||
return False # URGENT _is_md_actual
|
||||
|
||||
def _create_md_pdf(self, hist_aggr: List[MdTradesAggregate]) -> Optional[pd.DataFrame]:
|
||||
return None # URGENT _create_md_pdf
|
||||
def _create_md_df(self, hist_aggr: List[MdTradesAggregate]) -> pd.DataFrame:
|
||||
"""
|
||||
tstamp time_ns symbol open high low close volume num_trades vwap
|
||||
0 2025-09-10 11:30:00 1757503800000000000 ADA-USDT 0.8750 0.8750 0.8743 0.8743 50710.500 0 0.874489
|
||||
1 2025-09-10 11:30:00 1757503800000000000 SOL-USDT 219.9700 219.9800 219.6600 219.7000 2648.582 0 219.787847
|
||||
2 2025-09-10 11:31:00 1757503860000000000 SOL-USDT 219.7000 219.7300 219.6200 219.6200 1134.886 0 219.663460
|
||||
3 2025-09-10 11:31:00 1757503860000000000 ADA-USDT 0.8743 0.8745 0.8741 0.8741 10696.400 0 0.874234
|
||||
4 2025-09-10 11:32:00 1757503920000000000 ADA-USDT 0.8742 0.8742 0.8739 0.8740 18546.900 0 0.874037
|
||||
"""
|
||||
|
||||
rows: List[Dict[str, Any]] = []
|
||||
|
||||
for aggr in hist_aggr:
|
||||
exch_inst = aggr.exch_inst_
|
||||
|
||||
rows.append(
|
||||
{
|
||||
# convert nanoseconds → tz-aware pandas timestamp
|
||||
"tstamp": pd.to_datetime(aggr.time_ns_, unit="ns", utc=True),
|
||||
"time_ns": aggr.time_ns_,
|
||||
"symbol": exch_inst.instrument_id().split("-", 1)[1],
|
||||
"exchange_id": exch_inst.exchange_id_,
|
||||
"instrument_id": exch_inst.instrument_id(),
|
||||
"open": exch_inst.get_price(aggr.open_),
|
||||
"high": exch_inst.get_price(aggr.high_),
|
||||
"low": exch_inst.get_price(aggr.low_),
|
||||
"close": exch_inst.get_price(aggr.close_),
|
||||
"volume": exch_inst.get_quantity(aggr.volume_),
|
||||
"num_trades": aggr.num_trades_,
|
||||
"vwap": exch_inst.get_price(aggr.vwap_),
|
||||
}
|
||||
)
|
||||
|
||||
source_md_df = pd.DataFrame(
|
||||
rows,
|
||||
columns=[
|
||||
"tstamp",
|
||||
"time_ns",
|
||||
"symbol",
|
||||
"exchange_id",
|
||||
"instrument_id",
|
||||
"open",
|
||||
"high",
|
||||
"low",
|
||||
"close",
|
||||
"volume",
|
||||
"num_trades",
|
||||
"vwap",
|
||||
],
|
||||
)
|
||||
|
||||
# automatic sorting
|
||||
source_md_df.sort_values(
|
||||
by=["time_ns", "symbol"],
|
||||
ascending=True,
|
||||
inplace=True,
|
||||
kind="mergesort", # stable sort
|
||||
)
|
||||
|
||||
source_md_df.reset_index(drop=True, inplace=True)
|
||||
|
||||
pt_mkt_data = LiveMarketData(config=self.config_, instruments=self.instruments_)
|
||||
pt_mkt_data.origin_mkt_data_df_ = source_md_df
|
||||
pt_mkt_data.set_market_data()
|
||||
|
||||
return pt_mkt_data.market_data_df_
|
||||
|
||||
def interval_sec(self) -> IntervalSecT:
|
||||
return self.interval_sec_
|
||||
@@ -156,271 +231,110 @@ class PtLiveStrategy(NamedObject):
|
||||
return self.history_depth_sec_
|
||||
|
||||
async def _send_trading_instructions(
|
||||
self, trading_instructions: TradingInstructions
|
||||
self, trading_instructions: List[TradingInstructions]
|
||||
) -> None:
|
||||
await self.pairs_trader_.ti_sender_.send_trading_instructions(trading_instructions)
|
||||
pass # URGENT _send_trading_instructions
|
||||
for ti in trading_instructions:
|
||||
Log.info(f"{self.fname()} Sending trading instructions {ti}")
|
||||
await self.pairs_trader_.ti_sender_.send_trading_instructions(ti)
|
||||
|
||||
def _create_trading_instructions(
|
||||
self, prediction: Prediction, last_row: pd.Series
|
||||
) -> Optional[TradingInstructions]:
|
||||
) -> List[TradingInstructions]:
|
||||
trd_instructions: List[TradingInstructions] = []
|
||||
pair = self.trading_pair_
|
||||
res: Optional[TradingInstructions]
|
||||
|
||||
scaled_disequilibrium = prediction.scaled_disequilibrium_
|
||||
abs_scaled_disequilibrium = abs(scaled_disequilibrium)
|
||||
|
||||
if pair.is_closed():
|
||||
if abs_scaled_disequilibrium >= self.open_threshold_:
|
||||
trd_instructions = self._create_open_trade_instructions(
|
||||
pair, row=last_row, prediction=prediction
|
||||
)
|
||||
elif pair.is_open():
|
||||
if abs_scaled_disequilibrium <= self.close_threshold_:
|
||||
trd_instructions = self._create_close_trade_instructions(
|
||||
pair, row=last_row # , prediction=prediction
|
||||
)
|
||||
elif pair.to_stop_close_conditions(predicted_row=last_row):
|
||||
trd_instructions = self._create_close_trade_instructions(
|
||||
pair, row=last_row
|
||||
)
|
||||
if abs_scaled_disequilibrium >= self.open_threshold_:
|
||||
trd_instructions = self._create_open_trade_instructions(
|
||||
pair, row=last_row, prediction=prediction
|
||||
)
|
||||
|
||||
elif abs_scaled_disequilibrium <= self.close_threshold_ or pair.to_stop_close_conditions(predicted_row=last_row):
|
||||
trd_instructions = self._create_close_trade_instructions(
|
||||
pair, row=last_row # , prediction=prediction
|
||||
)
|
||||
|
||||
|
||||
return trd_instructions
|
||||
|
||||
def _strength(self, scaled_disequilibrium) -> float:
|
||||
# URGENT PtLiveStrategy._strength()
|
||||
return 1.0
|
||||
|
||||
def _create_open_trade_instructions(
|
||||
self, pair: TradingPair, row: pd.Series, prediction: Prediction
|
||||
) -> Optional[TradingInstructions]:
|
||||
ti: Optional[TradingInstructions] = None
|
||||
scaled_disequilibrium = prediction.scaled_disequilibrium_
|
||||
# URGENT _create_open_trade_instructions
|
||||
|
||||
# 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},
|
||||
# )
|
||||
# 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
|
||||
# pair.user_data_["open_px_a"] = px_a
|
||||
# pair.user_data_["open_px_b"] = px_b
|
||||
# pair.user_data_["open_tstamp"] = tstamp
|
||||
|
||||
# pair.user_data_["close_side_a"] = side_b # used for closing trades
|
||||
# pair.user_data_["close_side_b"] = side_a
|
||||
|
||||
# # create opening trades
|
||||
# df.loc[len(df)] = {
|
||||
# "time": tstamp,
|
||||
# "symbol": pair.symbol_a_,
|
||||
# "side": side_a,
|
||||
# "action": "OPEN",
|
||||
# "price": px_a,
|
||||
# "disequilibrium": diseqlbrm,
|
||||
# "signed_scaled_disequilibrium": scaled_disequilibrium,
|
||||
# "scaled_disequilibrium": abs(scaled_disequilibrium),
|
||||
# # "pair": pair,
|
||||
# }
|
||||
# df.loc[len(df)] = {
|
||||
# "time": tstamp,
|
||||
# "symbol": pair.symbol_b_,
|
||||
# "side": side_b,
|
||||
# "action": "OPEN",
|
||||
# "price": px_b,
|
||||
# "disequilibrium": diseqlbrm,
|
||||
# "scaled_disequilibrium": abs(scaled_disequilibrium),
|
||||
# "signed_scaled_disequilibrium": scaled_disequilibrium,
|
||||
# # "pair": pair,
|
||||
# }
|
||||
# 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
|
||||
) -> Optional[TradingInstructions]:
|
||||
ti: Optional[TradingInstructions] = None
|
||||
# URGENT _create_close_trade_instructions
|
||||
return ti
|
||||
|
||||
def _handle_outstanding_positions(self) -> Optional[pd.DataFrame]:
|
||||
trades = None
|
||||
pair = self.trading_pair_
|
||||
|
||||
# Outstanding positions
|
||||
if pair.user_data_["state"] == PairState.OPEN:
|
||||
print(f"{pair}: *** Position is NOT CLOSED. ***")
|
||||
# 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
|
||||
# close_position_row["signed_scaled_disequilibrium"] = 0.0
|
||||
|
||||
trades = self._create_close_trades(
|
||||
pair=pair, row=close_position_row, prediction=None
|
||||
)
|
||||
if trades is not None:
|
||||
trades["status"] = PairState.CLOSE_POSITION.name
|
||||
print(f"CLOSE_POSITION TRADES:\n{trades}")
|
||||
pair.user_data_["state"] = PairState.CLOSE_POSITION
|
||||
pair.on_close_trades(trades)
|
||||
else:
|
||||
pair.add_outstanding_position(
|
||||
symbol=pair.symbol_a_,
|
||||
open_side=pair.user_data_["open_side_a"],
|
||||
open_px=pair.user_data_["open_px_a"],
|
||||
open_tstamp=pair.user_data_["open_tstamp"],
|
||||
last_mkt_data_row=pair.market_data_.iloc[-1],
|
||||
)
|
||||
pair.add_outstanding_position(
|
||||
symbol=pair.symbol_b_,
|
||||
open_side=pair.user_data_["open_side_b"],
|
||||
open_px=pair.user_data_["open_px_b"],
|
||||
open_tstamp=pair.user_data_["open_tstamp"],
|
||||
last_mkt_data_row=pair.market_data_.iloc[-1],
|
||||
)
|
||||
return trades
|
||||
|
||||
def _trades_df(self) -> pd.DataFrame:
|
||||
types = {
|
||||
"time": "datetime64[ns]",
|
||||
"action": "string",
|
||||
"symbol": "string",
|
||||
"side": "string",
|
||||
"price": "float64",
|
||||
"disequilibrium": "float64",
|
||||
"scaled_disequilibrium": "float64",
|
||||
"signed_scaled_disequilibrium": "float64",
|
||||
# "pair": "object",
|
||||
}
|
||||
columns = list(types.keys())
|
||||
return pd.DataFrame(columns=columns).astype(types)
|
||||
|
||||
def _create_open_trades(
|
||||
self, pair: TradingPair, row: pd.Series, prediction: Prediction
|
||||
) -> Optional[pd.DataFrame]:
|
||||
colname_a, colname_b = pair.exec_prices_colnames()
|
||||
|
||||
tstamp = row["tstamp"]
|
||||
self, pair: LiveTradingPair, row: pd.Series, prediction: Prediction
|
||||
) -> List[TradingInstructions]:
|
||||
diseqlbrm = prediction.disequilibrium_
|
||||
scaled_disequilibrium = prediction.scaled_disequilibrium_
|
||||
px_a = row[f"{colname_a}"]
|
||||
px_b = row[f"{colname_b}"]
|
||||
|
||||
# creating the trades
|
||||
df = self._trades_df()
|
||||
|
||||
print(f"OPEN_TRADES: {row["tstamp"]} {scaled_disequilibrium=}")
|
||||
if diseqlbrm > 0:
|
||||
side_a = "SELL"
|
||||
side_b = "BUY"
|
||||
side_a = -1
|
||||
side_b = 1
|
||||
else:
|
||||
side_a = "BUY"
|
||||
side_b = "SELL"
|
||||
side_a = 1
|
||||
side_b = -1
|
||||
|
||||
# save closing sides
|
||||
pair.user_data_["open_side_a"] = side_a # used in oustanding positions
|
||||
pair.user_data_["open_side_b"] = side_b
|
||||
pair.user_data_["open_px_a"] = px_a
|
||||
pair.user_data_["open_px_b"] = px_b
|
||||
pair.user_data_["open_tstamp"] = tstamp
|
||||
ti_a: Optional[TradingInstructions] = TradingInstructions(
|
||||
book=self.pairs_trader_.book_id_,
|
||||
strategy_id=self.__class__.__name__,
|
||||
ti_type=TradingInstructions.Type.TARGET_POSITION,
|
||||
issued_ts_ns=current_nanoseconds(),
|
||||
data=TargetPositionSignal(
|
||||
strength=side_a * self._strength(scaled_disequilibrium),
|
||||
base_asset=pair.get_instrument_a().base_asset_id_,
|
||||
quote_asset=pair.get_instrument_a().quote_asset_id_,
|
||||
user_data={}
|
||||
),
|
||||
)
|
||||
if not ti_a:
|
||||
return []
|
||||
ti_b: Optional[TradingInstructions] = TradingInstructions(
|
||||
book=self.pairs_trader_.book_id_,
|
||||
strategy_id=self.__class__.__name__,
|
||||
ti_type=TradingInstructions.Type.TARGET_POSITION,
|
||||
issued_ts_ns=current_nanoseconds(),
|
||||
data=TargetPositionSignal(
|
||||
strength=side_b * self._strength(scaled_disequilibrium),
|
||||
base_asset=pair.get_instrument_b().base_asset_id_,
|
||||
quote_asset=pair.get_instrument_b().quote_asset_id_,
|
||||
user_data={}
|
||||
),
|
||||
)
|
||||
if not ti_b:
|
||||
return []
|
||||
return [ti_a, ti_b]
|
||||
|
||||
pair.user_data_["close_side_a"] = side_b # used for closing trades
|
||||
pair.user_data_["close_side_b"] = side_a
|
||||
|
||||
# create opening trades
|
||||
df.loc[len(df)] = {
|
||||
"time": tstamp,
|
||||
"symbol": pair.symbol_a_,
|
||||
"side": side_a,
|
||||
"action": "OPEN",
|
||||
"price": px_a,
|
||||
"disequilibrium": diseqlbrm,
|
||||
"signed_scaled_disequilibrium": scaled_disequilibrium,
|
||||
"scaled_disequilibrium": abs(scaled_disequilibrium),
|
||||
# "pair": pair,
|
||||
}
|
||||
df.loc[len(df)] = {
|
||||
"time": tstamp,
|
||||
"symbol": pair.symbol_b_,
|
||||
"side": side_b,
|
||||
"action": "OPEN",
|
||||
"price": px_b,
|
||||
"disequilibrium": diseqlbrm,
|
||||
"scaled_disequilibrium": abs(scaled_disequilibrium),
|
||||
"signed_scaled_disequilibrium": scaled_disequilibrium,
|
||||
# "pair": pair,
|
||||
}
|
||||
return df
|
||||
|
||||
def _create_close_trades(
|
||||
self, pair: TradingPair, row: pd.Series, prediction: Optional[Prediction] = None
|
||||
) -> Optional[pd.DataFrame]:
|
||||
colname_a, colname_b = pair.exec_prices_colnames()
|
||||
|
||||
tstamp = row["tstamp"]
|
||||
if prediction is not None:
|
||||
diseqlbrm = prediction.disequilibrium_
|
||||
signed_scaled_disequilibrium = prediction.scaled_disequilibrium_
|
||||
scaled_disequilibrium = abs(prediction.scaled_disequilibrium_)
|
||||
else:
|
||||
diseqlbrm = 0.0
|
||||
signed_scaled_disequilibrium = 0.0
|
||||
scaled_disequilibrium = 0.0
|
||||
px_a = row[f"{colname_a}"]
|
||||
px_b = row[f"{colname_b}"]
|
||||
|
||||
# creating the trades
|
||||
df = self._trades_df()
|
||||
|
||||
# create opening trades
|
||||
df.loc[len(df)] = {
|
||||
"time": tstamp,
|
||||
"symbol": pair.symbol_a_,
|
||||
"side": pair.user_data_["close_side_a"],
|
||||
"action": "CLOSE",
|
||||
"price": px_a,
|
||||
"disequilibrium": diseqlbrm,
|
||||
"scaled_disequilibrium": scaled_disequilibrium,
|
||||
"signed_scaled_disequilibrium": signed_scaled_disequilibrium,
|
||||
# "pair": pair,
|
||||
}
|
||||
df.loc[len(df)] = {
|
||||
"time": tstamp,
|
||||
"symbol": pair.symbol_b_,
|
||||
"side": pair.user_data_["close_side_b"],
|
||||
"action": "CLOSE",
|
||||
"price": px_b,
|
||||
"disequilibrium": diseqlbrm,
|
||||
"scaled_disequilibrium": scaled_disequilibrium,
|
||||
"signed_scaled_disequilibrium": signed_scaled_disequilibrium,
|
||||
# "pair": pair,
|
||||
}
|
||||
del pair.user_data_["close_side_a"]
|
||||
del pair.user_data_["close_side_b"]
|
||||
|
||||
del pair.user_data_["open_tstamp"]
|
||||
del pair.user_data_["open_px_a"]
|
||||
del pair.user_data_["open_px_b"]
|
||||
del pair.user_data_["open_side_a"]
|
||||
del pair.user_data_["open_side_b"]
|
||||
return df
|
||||
def _create_close_trade_instructions(
|
||||
self, pair: LiveTradingPair, row: pd.Series
|
||||
) -> List[TradingInstructions]:
|
||||
ti_a: Optional[TradingInstructions] = TradingInstructions(
|
||||
book=self.pairs_trader_.book_id_,
|
||||
strategy_id=self.__class__.__name__,
|
||||
ti_type=TradingInstructions.Type.TARGET_POSITION,
|
||||
issued_ts_ns=current_nanoseconds(),
|
||||
data=TargetPositionSignal(
|
||||
strength=0,
|
||||
base_asset=pair.get_instrument_a().base_asset_id_,
|
||||
quote_asset=pair.get_instrument_a().quote_asset_id_,
|
||||
user_data={}
|
||||
),
|
||||
)
|
||||
if not ti_a:
|
||||
return []
|
||||
ti_b: Optional[TradingInstructions] = TradingInstructions(
|
||||
book=self.pairs_trader_.book_id_,
|
||||
strategy_id=self.__class__.__name__,
|
||||
ti_type=TradingInstructions.Type.TARGET_POSITION,
|
||||
issued_ts_ns=current_nanoseconds(),
|
||||
data=TargetPositionSignal(
|
||||
strength=0,
|
||||
base_asset=pair.get_instrument_b().base_asset_id_,
|
||||
quote_asset=pair.get_instrument_b().quote_asset_id_,
|
||||
user_data={}
|
||||
),
|
||||
)
|
||||
if not ti_b:
|
||||
return []
|
||||
return [ti_a, ti_b]
|
||||
|
||||
Reference in New Issue
Block a user