def test_too_expensive_buy(): assert db c = 1000.0 a = va.VirtualAccount(c, db.get_all_symbol_data()) assert a a.buy_at_market(0, 'SPY', 2000) assert len(a.get_all_positions()) == 0 assert a.get_cash() == c
def test_invalid_buy_qty(): assert db c = 1000.0 a = va.VirtualAccount(c, db.get_all_symbol_data()) assert a a.buy_at_market(0, 'SPY', 0) assert len(a.get_all_positions()) == 0 assert a.get_cash() == c a.buy_at_market(0, 'SPY', -10) assert len(a.get_all_positions()) == 0 assert a.get_cash() == c
def test_too_expensive_sell(): assert db c = 10000.0 a = va.VirtualAccount(c, db.get_all_symbol_data()) assert a a.buy_at_market(0, 'SPY', 1) assert len(a.get_open_positions()) == 1 assert a.get_cash() < c a.delta_cash(-a.get_cash() + 0.1) assert a.get_cash() > 0.0 c = a.get_cash() a.sell_at_market(a.get_open_positions()[0], 10) assert a.get_cash() == c assert len(a.get_open_positions()) == 1
def test_invalid_sell(): assert db c = 1000.0 a = va.VirtualAccount(c, db.get_all_symbol_data()) assert len(a.get_open_positions()) == 0 assert a a.buy_at_market(0, 'SPY', 1) assert len(a.get_open_positions()) == 1 p = a.get_open_positions()[0] a.sell_at_market(p, 1) # 1st sell, ok assert len(a.get_open_positions()) == 0 assert len(a.get_close_positions()) == 1 c = a.get_cash() a.sell_at_market(p, 2) # 2nd invalid sell same position assert a.get_cash() == c
def simulate2(): print("simulate2()") a = va.VirtualAccount(50000.00, dic) print("Initial cash", a.get_cash()) # Symbol loop symbol_list = list(dic.keys()) symbol_list.sort() for symbol in symbol_list: print("Simulating with", symbol) df = dic[symbol] # The various series (starting with s): s_close = fu.get_close(df) # Technical indicators s_close_sma = ti.sma(s_close, 200) # Bar loops (1 bar per day) # start index to include various moving average lag # end at -1 to include "tomorrow" (corresponds to last valid bar) # TBD to fix this with real signals for bar in range(200, len(df) - 1): # Positions loop open_positions = a.get_open_positions(symbol) for pos in open_positions: # TBD sell logic sell_signal = s_close[bar] > 1.15 * pos.get_entry_price() or \ s_close[bar] < 0.95 * pos.get_entry_price() if sell_signal: a.sell_at_market(pos, bar + 1) # bar + 1 = tomorrow if not open_positions: # TBD buy logic buy_signal = ti.cross_over(s_close, s_close_sma)[bar] if buy_signal: nb_share = int( 2500 / s_close[bar] ) # 2500$ => about 0.8% commission buy + sell a.buy_at_market(bar + 1, symbol, nb_share) # bar + 1 = tomorrow for p in a.get_all_positions(): print(p) print("Final cash", a.get_cash())
def simulate(): print("simulate()") initial_cash = 100000.0 a = va.VirtualAccount(initial_cash, dic) print("Initial cash", a.get_cash()) # Target allocation: ratio = { 'XBB.TO': 0.1, 'ZCN.TO': 0.3, 'VUN.TO': 0.3, 'XEF.TO': 0.2, 'XEC.TO': 0.1 } # Symbol loop symbol_list = list(dic.keys()) symbol_list.sort() df = pd.DataFrame(index=symbol_list, data=[ratio[s] for s in symbol_list], columns=['TgtAlloc']) df['NbShare'] = np.zeros(len(symbol_list)) df_prices = db.get_all_symbol_single_data_item('Close') for i in range(len(df_prices)): if i % 100 == 0: # Adjust rebalance frequency here print("Rebalance", i) # Roughly Matching StockPortfolio_RRSP column ordering df['Price'] = df_prices.iloc[i] df['MktValue'] = df['Price'] * df['NbShare'] total_value = sum(df['Price'] * df['NbShare']) + a.get_cash() df['CurrAlloc'] = df['MktValue'] / total_value df['DeltaAlloc'] = df['CurrAlloc'] - df['TgtAlloc'] df['TgtValue'] = df['TgtAlloc'] * total_value # +:Buy -:Sell df['DeltaShare'] = np.floor( (df['TgtValue']) / df['Price']) - df['NbShare'] c = [calc_commission_etf(n) for n in df['DeltaShare'].values] # TBD not sure about the commission formula for both buy & sell... for s in symbol_list: n = df.loc[s, 'DeltaShare'] if n > 0: print(" Buy {} of {}".format(n, s)) a.delta_cash(-n * df.loc[s, 'Price']) df.loc[s, 'NbShare'] += n #a.buy_at_market(i, s, n) elif n < 0: print(" Sell {} of {}".format(-n, s)) a.delta_cash(-n * df.loc[s, 'Price']) df.loc[s, 'NbShare'] += n #a.sell_at_market() # Do not tolerate after all transactions are done. if a.get_cash() < 0: print("Error: not enough money", a.get_cash()) else: #print("skip", i) pass print("Initial Cash =", initial_cash) # Update last price df['Price'] = [dic[s].iloc[-1]['Close'] for s in symbol_list] print("Final Cash = ", sum(df['Price'] * df['NbShare']) + a.get_cash())
def test_virtual_account(): assert db a = va.VirtualAccount(100000.0, db.get_all_symbol_data()) assert a assert a.get_cash() == 100000.0 a.delta_cash(200) assert a.get_cash() == 100200.0 a.delta_cash(-100) assert a.get_cash() == 100100.0 assert len(a.get_all_positions()) == 0 assert len(a.get_open_positions()) == 0 assert len(a.get_close_positions()) == 0 assert len(a.get_all_positions('SPY')) == 0 assert len(a.get_open_positions('SPY')) == 0 assert len(a.get_close_positions('SPY')) == 0 a.buy_at_market(0, 'SPY', 100) assert len(a.get_all_positions()) == 1 assert len(a.get_open_positions()) == 1 assert len(a.get_close_positions()) == 0 assert len(a.get_all_positions('SPY')) == 1 assert len(a.get_open_positions('SPY')) == 1 assert len(a.get_close_positions('SPY')) == 0 assert len(a.get_all_positions('IBM')) == 0 assert len(a.get_open_positions('IBM')) == 0 assert len(a.get_close_positions('IBM')) == 0 a.buy_at_market(1, 'IBM', 200) assert len(a.get_all_positions()) == 2 assert len(a.get_open_positions()) == 2 assert len(a.get_close_positions()) == 0 assert len(a.get_all_positions('SPY')) == 1 assert len(a.get_open_positions('SPY')) == 1 assert len(a.get_close_positions('SPY')) == 0 assert len(a.get_all_positions('IBM')) == 1 assert len(a.get_open_positions('IBM')) == 1 assert len(a.get_close_positions('IBM')) == 0 a.sell_at_market(a.get_open_positions()[0], 12) assert len(a.get_all_positions()) == 2 assert len(a.get_open_positions()) == 1 assert len(a.get_close_positions()) == 1 assert len(a.get_all_positions('SPY')) == 1 assert len(a.get_open_positions('SPY')) == 0 assert len(a.get_close_positions('SPY')) == 1 assert len(a.get_all_positions('IBM')) == 1 assert len(a.get_open_positions('IBM')) == 1 assert len(a.get_close_positions('IBM')) == 0 a.sell_at_market(a.get_open_positions()[0], 13) assert len(a.get_all_positions()) == 2 assert len(a.get_open_positions()) == 0 assert len(a.get_close_positions()) == 2 assert len(a.get_all_positions('SPY')) == 1 assert len(a.get_open_positions('SPY')) == 0 assert len(a.get_close_positions('SPY')) == 1 assert len(a.get_all_positions('IBM')) == 1 assert len(a.get_open_positions('IBM')) == 0 assert len(a.get_close_positions('IBM')) == 1