def create_register_from_warehouse(self, stocks: List[Stock], start_epoch_s: float, end_epoch_s: float) -> \ SymbolDayRegister: sdr = SymbolDayRegister() moments = self.warehouse_client.get_moments(stocks, start_epoch_s, end_epoch_s) sdr.add_moments(moments) return sdr
def execute(self, epoch_s: float, register: SymbolDayRegister) -> None: for _ in range(self.N_ACTIONS): action = random.randint(0, 1) # buy if action == 0: symbols = list(register.keys()) symbol = random.choice(symbols) price_per_share = register.get_close(symbol, epoch_s) if price_per_share is None: continue if self.cash >= self.TRADE_SIZE: shares = self.TRADE_SIZE / price_per_share self.buy(symbol, price_per_share, shares) # sell if action == 1: symbols = list(self.holdings.keys()) if len(symbols) == 0: continue symbol = random.choice(symbols) price_per_share = register.get_close(symbol, epoch_s) if price_per_share is None: continue shares = self.holdings[symbol] self.sell(symbol, price_per_share, shares)
class AddMomentToRegisterTestCase(unittest.TestCase): def setUp(self): self.symbol_day_register = SymbolDayRegister() def test_add_moment(self): moment = Moment.from_dict(STOCKS_DAILY['AAPL']['records'][0]) moment.symbol = 'AAPL' self.symbol_day_register.add_moment(moment) self.assertIn('AAPL', self.symbol_day_register.series.keys()) self.assertEqual(moment, self.symbol_day_register.series['AAPL'].get_moments()[0]) def test_add_multiple_moments(self): moments = list() for symbol in ('AAPL', 'BYND'): _chunk = [Moment.from_dict(x) for x in STOCKS_DAILY[symbol]['records']] for moment in _chunk: moment.symbol = symbol moments += _chunk moments_shuffled = moments.copy() random.shuffle(moments_shuffled) self.assertNotEqual(moments, moments_shuffled) self.symbol_day_register.add_moments(moments_shuffled) actual_moments = list() for symbol in ('AAPL', 'BYND'): actual_moments += self.symbol_day_register.series[symbol].get_moments() self.assertEqual(moments, actual_moments)
def execute(self, epoch_s: float, register: SymbolDayRegister) -> None: if self.cash <= 10: return available_symbols = register.symbols_available(epoch_s) allocated_per_trade = self.cash / len(available_symbols) for symbol in available_symbols: price_per_share = register.get_close(symbol, epoch_s) shares = allocated_per_trade / price_per_share shares = shares // 0.01 / 100 self.buy(symbol, price_per_share, shares)
def _determine_sell_signals(self, register: SymbolDayRegister, current_holdings: List[Stock]) -> List: holdings_dict = dict() for holding in current_holdings: holdings_dict[holding] = 1 sell_signals = list() register_holdings = register.subset(current_holdings) for trader in self.traders: trader.holdings = holdings_dict stocks_sell = trader.determine_sells(self.today_epoch_s, register_holdings) for stock in stocks_sell: recent_close = list() for i in range(10): recent_close.append( register_holdings.get_close(stock, self.today_epoch_s, -i)) sell_signal = { 'trader': trader.name, 'date': self.today_day_str, 'exchange': stock.exchange, 'symbol': stock.symbol, 'signal': 'SELL', 'recent_close': recent_close } print(yaml.dump(sell_signal)) sell_signals.append(sell_signal) return sell_signals
def determine_buys(self, epoch_s: float, register: SymbolDayRegister) -> List[str]: """ Apply rules that trigger buy order """ stocks = list(register.keys()) random.shuffle(stocks) to_buy = list() for stock in stocks: buy_flag = True prices = [None] * (self.n_crash + 1) for i in range(self.n_crash): close_today = register.get_close(stock, epoch_s, -i) if close_today is None: buy_flag = False break close_yesterday = register.get_close(stock, epoch_s, -i - 1) if close_yesterday is None: buy_flag = False break gain = 100 * (close_today / close_yesterday - 1) if gain > self.gain_crash: buy_flag = False break prices[i] = close_today prices[i + 1] = close_yesterday if buy_flag: to_buy.append(stock) date = IntuitiveDateConverter.to_day_str(epoch_s) print( f'Identified BUY flag: {date} : {stock.to_str()} : {prices}' ) if self.logger is not None: message = f'Identified BUY flag: {date} : {stock.to_str()} : {prices}' self.logger.log_message(message) if len(to_buy) >= self.n_buy_per_day: break return to_buy
def _populate_today_register(self, stocks: List[Stock]): register = SymbolDayRegister() moments = list() for stock in stocks: prices = self.data_ingest_manager.market_client.get_real_time_price( [stock]) for price in prices: moment_data = { 'epoch_s': self.today_epoch_s, 'exchange': price['exchange'], 'symbol': price['symbol'], 'close': float(price['price']) } moment = Moment(**moment_data) moments.append(moment) register.add_moments(moments) return register
def execute(self, epoch_s: float, register: SymbolDayRegister) -> None: to_sell = self.determine_sells(epoch_s, register) for stock in to_sell: price_per_share = register.get_close(stock, epoch_s) shares = self.holdings[stock] self.sell(stock, price_per_share, shares) to_buy = self.determine_buys(epoch_s, register) for stock in to_buy: if stock in self.holdings: continue price_per_share = register.get_close(stock, epoch_s) if self.cash >= self.trade_size: shares = self.trade_size / price_per_share shares = shares // 0.01 / 100 self.buy(stock, price_per_share, shares)
class GetFromRegisterTestCase(unittest.TestCase): def setUp(self): self.symbol_day_register = SymbolDayRegister() def test_get(self): moments = list() for symbol in ('AAPL', 'BYND'): _chunk = [Moment.from_dict(x) for x in STOCKS_DAILY[symbol]['records']] for moment in _chunk: moment.symbol = symbol moments += _chunk self.symbol_day_register.add_moments(moments) for symbol in ('AAPL', 'BYND'): for _ in range(3): i = random.randint(0, len(STOCKS_DAILY[symbol]['records']) - 1) moment = Moment.from_dict(STOCKS_DAILY[symbol]['records'][i]) moment.symbol = symbol self.assertEqual(moment, self.symbol_day_register.get(symbol, moment.epoch_s))
def get_net_worth(self, epoch_s: float, register: SymbolDayRegister) -> float: """ Provide instantaneous net worth of trader. The net worth is the sum of cash held as well as the value of all shares held at the close price of the moment. """ net_worth = self.cash for stock, n_shares in self.holdings.items(): moment = register.get(stock, epoch_s) if moment is not None: net_worth += moment.close * n_shares return net_worth
def determine_sells(self, epoch_s: float, register: SymbolDayRegister) -> List[str]: """ Apply rules that trigger sell order """ stocks = self.holdings.keys() to_sell = list() for stock in stocks: sell_flag = True prices = [None] * (self.n_down + 1) for i in range(self.n_down): close_today = register.get_close(stock, epoch_s, -i) if close_today is None: sell_flag = False break close_yesterday = register.get_close(stock, epoch_s, -i - 1) if close_yesterday is None: sell_flag = False break gain = 100 * (close_today / close_yesterday - 1) if gain > self.gain_down: sell_flag = False break prices[i] = close_today prices[i + 1] = close_yesterday if sell_flag: to_sell.append(stock) date = IntuitiveDateConverter.to_day_str(epoch_s) if self.logger is not None: message = f'Identified SELL flag: {date} : {stock.to_str()} : {prices}' self.logger.log_message(message) return to_sell
def _determine_buy_signals(self, register: SymbolDayRegister, candidates: List[Stock]) -> List: buy_signals = list() register_candidates = register.subset(candidates) for trader in self.traders: stocks_buy = trader.determine_buys(self.today_epoch_s, register_candidates) recent_close = list() for stock in stocks_buy: for i in range(10): recent_close.append( register_candidates.get_close(stock, self.today_epoch_s, -i)) buy_signal = { 'trader': trader.name, 'date': self.today_day_str, 'exchange': stock.exchange, 'symbol': stock.symbol, 'signal': 'BUY', 'recent_close': recent_close } buy_signals.append(buy_signal) return buy_signals
def setUp(self): self.symbol_day_register = SymbolDayRegister()