From c1e9ffc1e3d0aae22136cb824c2bdd47c96f47ae Mon Sep 17 00:00:00 2001 From: Brenden Matthews Date: Tue, 12 Dec 2023 13:58:45 -0500 Subject: [PATCH] Include pending orders in cash balance Previously we ignored any pending orders, which could be credits or debits, when doing cash management. Now we'll include those values as well, which should result in a bit less churn. --- thetagang/portfolio_manager.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/thetagang/portfolio_manager.py b/thetagang/portfolio_manager.py index 23b567067..dfc3e0c7f 100644 --- a/thetagang/portfolio_manager.py +++ b/thetagang/portfolio_manager.py @@ -1755,6 +1755,21 @@ def vix_calls_should_be_closed() -> ( console.print(Panel(Group(*to_print), title="VIX call hedging")) + def calc_pending_cash_balance(self): + return sum( + [ + order.lmtPrice * order.totalQuantity * float(contract.multiplier) + for (contract, order) in self.orders + if order.action == "SELL" + ] + ) - sum( + [ + order.lmtPrice * order.totalQuantity * float(contract.multiplier) + for (contract, order) in self.orders + if order.action == "BUY" + ] + ) + def do_cashman(self, account_summary, portfolio_positions): to_print = [] @@ -1769,6 +1784,7 @@ def inner_handler(): buy_threshold = self.config["cash_management"]["buy_threshold"] sell_threshold = self.config["cash_management"]["sell_threshold"] cash_balance = math.floor(float(account_summary["TotalCashValue"].value)) + pending_balance = self.calc_pending_cash_balance() try: @@ -1791,14 +1807,16 @@ def make_order() -> tuple[Optional[Ticker], Optional[LimitOrder]]: else self.config["orders"]["algo"] ) - amount = cash_balance - target_cash_balance + amount = cash_balance - (target_cash_balance + pending_balance) price = ticker.ask if amount > 0 else ticker.bid qty = amount // price if qty > 0: to_print.append( - f"[green]cash_balance={cash_balance} which exceeds " - f"(target_cash_balance + buy_threshold)={(target_cash_balance + buy_threshold)}" + f"[green]cash_balance={dfmt(cash_balance)} which exceeds " + f"(target_cash_balance + pending_balance + buy_threshold)=" + f"{(dfmt(target_cash_balance + pending_balance + buy_threshold))} " + f"with pending_balance={dfmt(pending_balance)}" ) to_print.append( f"[green]Will buy {symbol} with qty={qty} shares at price={price}" @@ -1809,8 +1827,10 @@ def make_order() -> tuple[Optional[Ticker], Optional[LimitOrder]]: # subtract 1 to keep cash balance above target qty -= 1 to_print.append( - f"[green]cash_balance={cash_balance} which is less than " - f"(target_cash_balance - sell_threshold)={(target_cash_balance - sell_threshold)}" + f"[green]cash_balance={dfmt(cash_balance)} which is less than " + f"(target_cash_balance + pending_balance - sell_threshold)=" + f"{(dfmt(target_cash_balance + pending_balance - sell_threshold))} " + f"with pending_balance={dfmt(pending_balance)}" ) if symbol not in portfolio_positions: # we don't have any positions to sell