def test_orders_columns(): account = TradingAccount() account.buy('BTC', 'GBP', 1000, 30000) actual = account.getOrders().columns.to_list() expected = ['market', 'action', 'type', 'size', 'value', 'status', 'price'] assert len(actual) == len(expected) assert all([a == b for a, b in zip(actual, expected)])
def test_orders_filtering(): account = TradingAccount() account.buy('BTC', 'GBP', 250, 30000) assert len(account.getOrders()) == 1 account.sell('BTC', 'GBP', 0.0082, 35000) assert len(account.getOrders()) == 2 account.buy('ETH', 'GBP', 250, 30000) assert len(account.getOrders()) == 3 account.sell('ETH', 'GBP', 0.0082, 35000) assert len(account.getOrders()) == 4 assert len(account.getOrders('BTC-GBP')) == 2
def test_binance_market_buy_insufficient_funds(): try: with open('config-binance.json') as config_file: config = json.load(config_file) account = TradingAccount(config) with pytest.raises(Exception) as execinfo: account.buy('DOGE', 'BTC', 1000000, 0.000025) assert str( execinfo.value ) == 'APIError(code=-2010): Account has insufficient balance for requested action.' except IOError: pytest.skip('config-binance.json does not exist to perform test')
def test_dummy_orders(): account = TradingAccount() account.buy('BTC', 'GBP', 1000, 30000) actual = account.getOrders().columns.to_list() if len(actual) == 0: pytest.skip('No orders to perform test') expected = [ 'created_at', 'market', 'action', 'type', 'size', 'value', 'status', 'price' ] assert len(actual) == len(expected) assert all([a == b for a, b in zip(actual, expected)]) assert account.getExchange() == 'coinbasepro' assert account.getMode() == 'test'
def test_coinbasepro_market_buy_insufficient_funds(): with open('config-coinbasepro.json') as config_file: config = json.load(config_file) account = TradingAccount(config) resp = account.buy('BTC', 'GBP', 20000) assert str(resp) == 'None'
def test_successful_buy_and_sell(): account = TradingAccount() account.buy('BTC', 'GBP', 1000, 30000) account.sell('BTC', 'GBP', 0.0331, 35000) assert type(account.getBalance('GBP')) is float assert account.getBalance('GBP') == 1152.7
def test_sell_insufficient_funds(): account = TradingAccount() account.buy('BTC', 'GBP', 1000, 30000) with pytest.raises(Exception) as execinfo: account.sell('BTC', 'GBP', 1, 35000) assert str(execinfo.value) == 'Insufficient funds.'
def test_buy_sufficient_funds(): account = TradingAccount() account.buy('BTC', 'GBP', 1000, 30000) assert type(account.getBalance('GBP')) is float assert account.getBalance('GBP') == 0
-1 ]]['action'].values[0] == 'buy' and row['close'] > df_orders.iloc[[ -1 ]]['price'].values[0]: action = 'sell' if action != '' and action != last_action and not (last_action == '' and action == 'sell'): if last_action != '': if action == 'sell': diff = row['close'] - last_close else: diff = 0.00 if action == 'buy': account.buy(cryptoMarket, fiatMarket, amountPerTrade, row['close']) elif action == 'sell': account.sell(cryptoMarket, fiatMarket, df_orders.iloc[[-1]]['size'].values[0], row['close']) data_dict = { 'market': market, 'granularity': granularity, 'start': startDate, 'end': endDate, 'action': action, 'index': str(index), 'close': row['close'], 'sma200': row['sma200'], 'ema12': row['ema12'], 'ema26': row['ema26'],
"""Trading Account object model examples""" import json from models.TradingAccount import TradingAccount with open('config.json') as config_file: config = json.load(config_file) # live trading account - your account data! ''' account = TradingAccount(config) print (account.getBalance('GBP')) print (account.getOrders('BTC-GBP')) ''' # test trading account - dummy data account = TradingAccount() print(account.getBalance('GBP')) print(account.getBalance('BTC')) account = TradingAccount() account.buy('BTC', 'GBP', 250, 30000) print(account.getBalance()) account.sell('BTC', 'GBP', 0.0082, 35000) print(account.getBalance()) account.buy('ETH', 'GBP', 250, 30000) print(account.getBalance()) account.sell('ETH', 'GBP', 0.0082, 35000) print(account.getOrders()) print(account.getOrders('BTC-GBP')) print(account.getOrders('ETH-GBP'))
def runExperiment(id, market='BTC-GBP', granularity=3600, mostRecent=True): """Run an experiment Parameters ---------- market : str A valid market/product from the Coinbase Pro exchange. (Default: 'BTC-GBP') granularity : int A valid market interval {60, 300, 900, 3600, 21600, 86400} (Default: 86400 - 1 day) """ if not isinstance(id, int): raise TypeError('ID not numeric.') if id < 0: raise TypeError('ID is invalid.') p = re.compile(r"^[A-Z]{3,4}\-[A-Z]{3,4}$") if not p.match(market): raise TypeError('Coinbase Pro market required.') cryptoMarket, fiatMarket = market.split('-', 2) if not isinstance(granularity, int): raise TypeError('Granularity integer required.') if not granularity in [60, 300, 900, 3600, 21600, 86400]: raise TypeError( 'Granularity options: 60, 300, 900, 3600, 21600, 86400.') if not isinstance(mostRecent, bool): raise TypeError('Most recent is a boolean.') print('Experiment #' + str(id) + "\n") endDate = datetime.now() - timedelta(hours=random.randint( 0, 8760 * 3)) # 3 years in hours startDate = endDate - timedelta(hours=300) if mostRecent == True: startDate = '' endDate = '' print('Start date:', (datetime.now() - timedelta(hours=300)).isoformat()) print(' End date:', datetime.now().isoformat()) print('') else: startDate = str(startDate.isoformat()) endDate = str(endDate.isoformat()) print('Start date:', startDate) print(' End date:', endDate) print('') # instantiate a non-live trade account account = TradingAccount() # instantiate a CoinbassePro object with desired criteria coinbasepro = CoinbasePro(market, granularity, startDate, endDate) # adds buy and sell signals to Pandas DataFrame coinbasepro.addEMABuySignals() coinbasepro.addMACDBuySignals() # stores the Pandas Dataframe in df df = coinbasepro.getDataFrame() # defines the buy and sell signals and consolidates into df_signals buysignals = ((df.ema12gtema26co == True) & (df.macdgtsignal == True) & (df.obv_pc > 0)) | ((df.ema12gtema26 == True) & (df.ema12gtema26 == True) & (df.macdgtsignal == True) & (df.obv_pc >= 2)) sellsignals = (((df.ema12ltema26co == True) & (df.macdltsignal == True)) | ((df.ema12gtema26 == True) & ((df.macdltsignal == True) & (df.obv_pc < 0)))) df_signals = df[(buysignals) | (sellsignals)] diff = 0 action = '' last_action = '' last_close = 0 total_diff = 0 events = [] # iterate through the DataFrame buy and sell signals for index, row in df_signals.iterrows(): df_orders = account.getOrders() # determine if the df_signal is a buy or sell, just a high level check if row['ema12gtema26'] == True and row['macdgtsignal'] == True: action = 'buy' elif row['ema12ltema26co'] == True and row['macdltsignal'] == True: # ignore sell if close is lower than previous buy if len(df_orders) > 0 and df_orders.iloc[[ -1 ]]['action'].values[0] == 'buy' and row['close'] > df_orders.iloc[[ -1 ]]['price'].values[0]: action = 'sell' if action != '' and action != last_action and not ( last_action == '' and action == 'sell'): if last_action != '': if action == 'sell': diff = row['close'] - last_close else: diff = 0.00 if action == 'buy': account.buy(cryptoMarket, fiatMarket, 100, row['close']) elif action == 'sell': account.sell(cryptoMarket, fiatMarket, df_orders.iloc[[-1]]['size'].values[0], row['close']) data_dict = { 'market': market, 'granularity': granularity, 'start': startDate, 'end': endDate, 'action': action, 'index': str(index), 'close': row['close'], 'sma200': row['sma200'], 'ema12': row['ema12'], 'ema26': row['ema26'], 'macd': row['macd'], 'signal': row['signal'], 'ema12gtema26co': row['ema12gtema26co'], 'macdgtsignal': row['macdgtsignal'], 'ema12ltema26co': row['ema12ltema26co'], 'macdltsignal': row['macdltsignal'], 'obv_pc': row['obv_pc'], 'diff': diff } events.append(data_dict) last_action = action last_close = row['close'] total_diff = total_diff + diff # displays the events from the simulation events_df = pd.DataFrame(events) print(events_df) # if the last transation was a buy retrieve open amount addBalance = 0 df_orders = account.getOrders() if len(df_orders) > 0 and df_orders.iloc[[-1 ]]['action'].values[0] == 'buy': # last trade is still open, add to closing balance addBalance = df_orders.iloc[[-1]]['value'].values[0] # displays the orders from the simulation print('') print(df_orders) def truncate(f, n): return math.floor(f * 10**n) / 10**n # if the last transaction was a buy add the open amount to the closing balance result = truncate( round((account.getBalance(fiatMarket) + addBalance) - 1000, 2), 2) print('') print("Opening balance:", 1000) print("Closing balance:", truncate(round(account.getBalance(fiatMarket) + addBalance, 2), 2)) print(" Result:", result) print('') # saves the rendered diagram for the DataFrame (without displaying) tradinggraphs = TradingGraphs(coinbasepro) tradinggraphs.renderBuySellSignalEMA1226MACD( 'experiments/experiment' + str(id) + '_' + str(result) + '.png', True) result_dict = { 'market': market, 'granularity': granularity, 'start': startDate, 'end': endDate, 'open': 1000, 'close': '{:.2f}'.format(round(account.getBalance(fiatMarket) + addBalance, 2)), 'result': result } return result_dict