def exit_by_max_holding_time( mkt: MarketData, sig: Optional[Signal], entries: Trades, max_holding_time: pd.Timedelta, exit_condition: Callable[[pd.DataFrame, pd.Series, pd.Timestamp], bool], ) -> Trades: """Exit trade at max holding time or satisfying condition. Args: mkt: Market data sig: Signal data entries: Tuple of entry trades. max_holding_time: maximum holding time exit_condition: The entry is closed most closest time which condition is `True`. Result: Trades """ df = _concat(mkt, sig) def _exit_by_max_holding_time( trades: Trades, df: pd.DataFrame, max_holding_time: pd.Timedelta, exit_condition: Callable[[pd.DataFrame, pd.Series, pd.Timestamp], bool], ) -> Trades: indices = [] # type: List[pd.Timestamp] exits = [] # type: List[Tuple[float, int]] for i in trades.ids: trade = trades.get_trade(i) if trade.sum() == 0: continue idx = trade.index[0] start = max(idx, df.index[0]) end = min(idx + max_holding_time, df.index[-1]) df_exit = df.loc[start:end] transaction = _exit_transaction(df_exit, trade, exit_condition) indices.append(transaction.timestamp) exits.append((transaction.amount, i)) df = pd.DataFrame(index=indices, data=exits, columns=["amount", "_id"]) return from_dataframe(df, symbol, currency_unit) symbol = entries.symbol currency_unit = entries.currency_unit exits = _exit_by_max_holding_time(entries, df, max_holding_time, exit_condition) return concat([entries, exits])
def exit( mkt: MarketData, sig: Optional[Signal], entries: Trades, exit_condition: Callable[[pd.DataFrame, pd.Series], pd.Series], ) -> Trades: """Exit trade when satisfying condition. Args: mkt: Market data sig: Signal data entries: Tuple of entry trades. max_holding_time: maximum holding time exit_condition: The entry is closed most closest time which condition is `True`. Result: Trades """ df = _concat(mkt, sig) def _exit( trades: Trades, df: pd.DataFrame, exit_condition: Callable[[pd.DataFrame, pd.Series], pd.Series], ) -> pd.Series: indices = [] # type: List[pd.Timestamp] exits = [] # type: List[Tuple[float, int]] for i in trades.ids: trade = trades.get_trade(i) if trade.sum() == 0: continue idx = trade.index[0] df_exit = df[idx <= df.index] transaction = _exit_transaction(df_exit, trade, exit_condition) indices.append(transaction.timestamp) exits.append((transaction.amount, i)) df = pd.DataFrame(index=indices, data=exits, columns=["amount", "_id"]) return from_dataframe(df, symbol) symbol = entries.symbol exits = _exit(entries, df, exit_condition) return concat([entries, exits])
def test_concat(trades, expected_ids, refresh_id): trades1 = trades.copy() trades2 = trades.copy() result = module.concat([trades1, trades2], refresh_id) # check symbol expected = trades1.symbol assert result.symbol == expected # check len expected = len(trades1) + len(trades2) assert len(result) == expected # check ids expected = expected_ids assert result.ids == expected # check amount data = trades.amount * 2.0 index = pd.date_range(start="2018-06-06", freq="1min", periods=len(data)) expected = pd.Series(data=data, index=index, name="amount") pd.testing.assert_series_equal(result.amount, expected)