def calc_portfolio_returns(portfolio_id: str) -> pd.DataFrame: loop = asyncio.get_event_loop() _ = loop.run_until_complete(Portfolio.load_by_portfolio_id(portfolio_id)) account_id, initial_account_size = loop.run_until_complete( Portfolio.load_details(portfolio_id) ) data_loader = DataLoader() trades = load_trades_by_portfolio(portfolio_id) start_date = trades.client_time.min().date() end_date = trades.client_time.max().date() trader = trader_factory()() td = trader.get_trading_days(start_date=start_date, end_date=end_date) td["equity"] = 0.0 cash_df = get_cash(account_id, initial_account_size) symbols = trades.symbol.unique().tolist() for i in tqdm(range(len(symbols))): symbol = symbols[i] symbol_trades = trades[trades.symbol == symbol].sort_values( by="client_time" ) calc_symbol_trades_returns(symbol, symbol_trades, td, data_loader) td = td.join(cash_df) td = td.fillna(method="ffill") td["totals"] = td["equity"] + td["cash"] return pd.DataFrame(td, columns=["equity", "cash", "totals"])
def calc_batch_returns(batch_id: str) -> pd.DataFrame: loop = asyncio.get_event_loop() portfolio = loop.run_until_complete(Portfolio.load_by_batch_id(batch_id)) data_loader = DataLoader() trades = load_trades_by_batch_id(batch_id) start_date = trades.client_time.min().date() end_date = trades.client_time.max().date() trader = trader_factory()() td = trader.get_trading_days(start_date=start_date, end_date=end_date) td["equity"] = 0.0 td["cash"] = portfolio.portfolio_size num_symbols = len(trades.symbol.unique().tolist()) for c, symbol in enumerate(trades.symbol.unique().tolist(), start=1): print(f"{symbol} ({c}/{num_symbols})") symbol_trades = trades[trades.symbol == symbol].sort_values( by="client_time" ) calc_symbol_trades_returns(symbol, symbol_trades, td, data_loader) td["totals"] = td["equity"] + td["cash"] # td["date"] = pd.to_datetime(td.index) # td = td.set_index("date") return pd.DataFrame(td, columns=["equity", "cash", "totals"])
async def run(self) -> bool: trader = trader_factory() self.trend_logic = TrendLogic( symbols=await sp500_historical_constituents(datetime.today()), portfolio_size=self.portfolio_size, rank_days=self.rank_days, debug=self.debug, stock_count=self.stock_count, volatility_threshold=self.volatility_threshold, data_loader=DataLoader(), trader=trader, ) if self.debug: tlog(f"symbols: {self.trend_logic.symbols}") df = (await self.trend_logic.run_short( nyc.localize(datetime.utcnow()) + timedelta(days=1)) if self.short else await self.trend_logic.run( nyc.localize(datetime.utcnow()) + timedelta(days=1))) portfolio_id = await self.save_portfolio() await self.display_portfolio(df) # await self.execute_portfolio( # portfolio_id, df, nyc.localize(datetime.utcnow()) # ) print( "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" ) tlog(f"PORTFOLIO_ID:{portfolio_id}") print( "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" ) return True
async def consumer_async_main( queue: Queue, symbols: List[str], unique_id: str, strategies_conf: Dict, ): await create_db_connection(str(config.dsn)) data_loader = DataLoader() if symbols: try: trending_db = TrendingTickers(unique_id) await trending_db.save(symbols) except Exception as e: tlog( f"Exception in consumer_async_main() while storing symbols to DB:{type(e).__name__} with args {e.args}" ) exc_info = sys.exc_info() lines = traceback.format_exception(*exc_info) for line in lines: tlog(f"error: {line}") traceback.print_exception(*exc_info) del exc_info trader = trader_factory()() config.market_open, config.market_close = trader.get_market_schedule() tlog( f"market open:{config.market_open} market close:{config.market_close}") loaded = await create_strategies( batch_id=unique_id, symbols=symbols, trader=trader, data_loader=data_loader, strategies_conf=strategies_conf, ) if symbols and loaded != len(symbols): tlog( f"[ERROR] Consumer process loaded only {loaded} out of {len(symbols)} open positions. HINT: make sure that your tradeplan.toml file includes all strategies from previous trading session." ) queue_consumer_task = asyncio.create_task( queue_consumer(queue, data_loader, trader)) liquidate_task = asyncio.create_task(liquidator(trader)) periodic_runner_task = asyncio.create_task( periodic_runner(data_loader, trader)) tear_down = asyncio.create_task( teardown_task(trader, [queue_consumer_task, periodic_runner_task])) await asyncio.gather( tear_down, liquidate_task, queue_consumer_task, periodic_runner_task, return_exceptions=True, ) tlog("consumer_async_main() completed")
def compare_to_symbol_returns(batch_id: str, symbol: str) -> pd.DataFrame: data_loader = DataLoader() trades = load_trades_by_batch_id(batch_id) start_date = trades.client_time.min().date() end_date = trades.client_time.max().date() trader = trader_factory()() td = trader.get_trading_days(start_date=start_date, end_date=end_date) td[symbol] = td.apply( lambda row: data_loader[symbol].close[row.name.to_pydatetime().replace( tzinfo=est)], axis=1, ) return td[symbol]
async def execute_portfolio(self, portfolio_id: str, df: df, now: datetime) -> None: tlog("Executing portfolio buys") trader = trader_factory() algo_run = await trader.create_session(self.name) await DBPortfolio.associate_batch_id_to_profile( portfolio_id, algo_run.batch_id) orders = [ await trader.submit_order( symbol=row.symbol, qty=row.qty, side="buy", order_type="market", time_in_force="day", ) for _, row in df.iterrows() ] open_orders = [] while True: for order in orders: ( order_completed, executed_price, ) = await trader.is_order_completed(order) if order_completed: db_trade = NewTrade( algo_run_id=algo_run.run_id, symbol=order.symbol, qty=int(order.qty), operation="buy", price=executed_price, indicators={}, ) await db_trade.save( config.db_conn_pool, str(now), 0.0, 0.0, ) else: open_orders.append(order) if not len(open_orders): break await asyncio.sleep(5.0) orders = open_orders
def test_trader_calendar() -> bool: trader = trader_factory()() td = trader.get_trading_days(start_date=date(year=2021, month=1, day=1)) print(td) return True
async def consumer_async_main( queue: Queue, symbols: List[str], unique_id: str, strategies_conf: Dict, ): await create_db_connection(str(config.dsn)) data_loader = DataLoader() if symbols: try: trending_db = TrendingTickers(unique_id) await trending_db.save(symbols) except Exception as e: tlog( f"Exception in consumer_async_main() while storing symbols to DB:{type(e).__name__} with args {e.args}" ) exc_info = sys.exc_info() lines = traceback.format_exception(*exc_info) for line in lines: tlog(f"error: {line}") traceback.print_exception(*exc_info) del exc_info trader = trader_factory()() config.market_open, config.market_close = trader.get_market_schedule() tlog( f"market open:{config.market_open} market close:{config.market_close}") strategy_types = [] for strategy_name in strategies_conf: strategy_details = strategies_conf[strategy_name] tlog(f"strategy {strategy_name} selected") if strategy_details.get("off_hours", False): tlog(f"{strategy_name} if off-hours, skipping during market hours") try: spec = importlib.util.spec_from_file_location( "module.name", strategy_details["filename"]) custom_strategy_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(custom_strategy_module) # type: ignore class_name = strategy_name custom_strategy = getattr(custom_strategy_module, class_name) if not issubclass(custom_strategy, Strategy): tlog(f"strategy must inherit from class {Strategy.__name__}") exit(0) strategy_details.pop("filename", None) strategy_types += [(custom_strategy, strategy_details)] except FileNotFoundError as e: tlog(f"[Error] file not found `{strategy_details['filename']}`") exit(0) except Exception as e: tlog( f"[Error]exception of type {type(e).__name__} with args {e.args}" ) traceback.print_exc() exit(0) loaded = 0 for strategy_tuple in strategy_types: strategy_type = strategy_tuple[0] strategy_details = strategy_tuple[1] tlog(f"initializing {type(strategy_type).__name__}") s = strategy_type(batch_id=unique_id, data_loader=data_loader, **strategy_details) await s.create() trading_data.strategies.append(s) if symbols: loaded += await load_current_positions( trading_api=trader, symbols=symbols, strategy=s, ) if symbols and loaded != len(symbols): tlog( f"[ERROR] Consumer process loaded only {loaded} out of {len(symbols)} open positions. HINT: make sure that your tradeplan.toml file includes all strategues in previous trading session." ) queue_consumer_task = asyncio.create_task( queue_consumer(queue, data_loader, trader)) liquidate_task = asyncio.create_task(liquidator(trader)) tear_down = asyncio.create_task(teardown_task(trader, queue_consumer_task)) await asyncio.gather( tear_down, liquidate_task, queue_consumer_task, return_exceptions=True, ) tlog("consumer_async_main() completed")