def limit_max_amount(trades: Trades, max_amount: int) -> Trades: """Limit trade by max amount. Args: trades: Trades max_amount: Max amount in absolute value Result: Trades """ assert max_amount > 0.0 current_amount = 0.0 deleted_ids = [] # type: List[int] for index, row in trades.iterrows(): if row["_id"] in deleted_ids: continue next_amount = current_amount + row["amount"] if abs(next_amount) > max_amount: deleted_ids.append(row["_id"]) continue current_amount = next_amount return trades[~trades["_id"].isin(deleted_ids)]
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)
def count_trades(trades: Trades, mkt: MarketData) -> Tuple[int, int, int]: """Count winning, losing and total number of trades. Args: trades : Trades to evaluate. Each trade is evaluated only if it contains more than one transactions, because we can define pl in that case. mkt: Market data. The index should contains all trades' index. Returns: total count, win count, lose count """ pls = [ _calc_pl(trades.get_trade(i), mkt) for i in trades.ids if len(trades.get_trade(i).index) > 1 ] total = len(trades.ids) win = sum([pl > 0.0 for pl in pls]) lose = sum([pl < 0.0 for pl in pls]) return total, win, lose
def skip_entry_by_hours(trades: Trades, hours: List[int]) -> Trades: """Skip entry by hours. Args: trades: Trades hours: Hours which will be filtered out from entry. Result: Trades """ deleted_ids = [] for i in trades.ids: entry = trades.get_trade(i).index[0] if entry.hour in hours: deleted_ids.append(i) return trades[~trades["_id"].isin(deleted_ids)]
def filter_entry_by_time( trades: Trades, unit: str, container_set: tuple ) -> Type["Trades"]: """Filter trade which match conditions at least one element. -> e.g. for container_set = [1,2] and unit = 'hour' Trades of hour 1 or 2 will be return. Args: container_set: The results will only contain elements of time in this set unit: Can be 'hour', 'minute'... The results.time will be in the set Returns: Trades. """ sort = trades.sort_values("_id") df = pd.DataFrame( data=np.zeros((sort.shape[0], 3)), columns=["amount", "_id", "index"] ) j = 0 for i in range(0, sort.index.size, 2): entry_index = sort.index[i] exit_index = sort.index[i + 1] if ( getattr(entry_index, unit) in container_set or getattr(exit_index, unit) in container_set ): # This code is faster than an iloc. df.at[j, "amount"] = sort.iat[i, 0] df.at[j + 1, "amount"] = sort.iat[i + 1, 0] df.at[j, "_id"] = sort.iat[i, 1] df.at[j + 1, "_id"] = sort.iat[i + 1, 1] df.at[j, "index"] = entry_index df.at[j + 1, "index"] = exit_index j += 2 df = df.iloc[0:j, :].sort_values("index").set_index("index") df.index.name = None return from_dataframe(df, trades.symbol, trades.currency_unit)
def skip_entry_by_spread(trades: Trades, mkt: AskBidMarketData, max_spread: float) -> Trades: """Skip entry by spread. Args: trades: Trades mkt: Market data for ask/bid prices max_spread: More than the value, skip entry Result: Trades """ assert max_spread >= 0.0 assert trades.index.unique().isin(mkt.index).all() spread = mkt.spread deleted_ids = [] # type: List[int] for i in trades.ids: entry = trades.get_trade(i).index[0] if spread.at[entry] > max_spread: deleted_ids.append(i) return trades[~trades["_id"].isin(deleted_ids)]
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)