class Polo: def __init__(self): self.public = Poloniex() self.private = Poloniex(API_Key, API_Secret) self.watch() def watch(self): res = self.private.returnBalances() self.btc = float(res['BTC']) self.usd = float(res['USDT']) self.xrp = float(res['XRP']) self.xem = float(res['XEM']) self.ltc = float(res['LTC']) self.eth = float(res['ETH']) res = self.public.returnOrderBook(Currency_Pair) self.ask = [float(res['asks'][0][0]), float(res['asks'][0][1])] self.bid = [float(res['bids'][0][0]), float(res['bids'][0][1])] def sell(self, am): self.private.sell('USDT_BTC', self.bid[0], am) self.watch() def buy(self, am): self.private.buy('USDT_BTC', self.ask[0], am) self.watch()
class PoloniexApiClient(BaseApiClient): PAIR_NAME_TEMPLATE = '{quote}_{base}' def __init__(self): super(PoloniexApiClient, self).__init__() self.api = self.get_api() def get_api(self): if not self.api: self.api = Poloniex(settings.API4_KEY, settings.API4_SECRET) return self.api def get_balance(self, currency): return Decimal(str(self.api.returnBalances().get(currency.code))) def get_ticker(self, pair): market = self.PAIR_NAME_TEMPLATE.format( base=pair.base.code, quote=pair.quote.code, ) return self.api.returnTicker().get(market) def get_rate(self, pair, **kwargs): ticker = self.get_ticker(pair) rate = ticker.get('last') return Decimal(str(rate)) def buy_limit(self, pair, amount, rate=None): market = self.PAIR_NAME_TEMPLATE.format( base=pair.base.code, quote=pair.quote.code, ) if not rate: rate = float(self.get_rate(pair)) return self.api.buy(market, rate, amount) def sell_limit(self, pair, amount, rate=None): market = self.PAIR_NAME_TEMPLATE.format( base=pair.base.code, quote=pair.quote.code, ) if not rate: rate = float(self.get_rate(pair)) return self.api.sell(market, rate, amount) def release_coins(self, currency, address, amount): tx_id = None if isinstance(currency, Currency): currency = currency.code if isinstance(address, Address): address = address.address res = self.api.withdraw(currency, amount, address) self.logger.info('Response from Poloniex withdraw: {}'.format(res)) success = 'Withdrew' in res.get('response', '') if success: tx_id = res.get('response') return tx_id, success
def buy_asset(pair, amount, store = True): '''Given a pair and an amount in $, buy the amount at the lowest possible price''' api_key = getkeys()[0] api_secret = getkeys()[1] polo = Poloniex(api_key, api_secret) total_bought = 0 total_to_buy = amount res = [] total = 0 # I - Sell while total_bought < 0.95*amount: # Let's say 95% is acceptable : in the vast majority of cases we will achieve 100% with the first trade, though... # Order to buy the missing amount we want to sell, then update the total amount bought rate = polo.returnTicker()[pair]["lowestAsk"] amount_pair = total_to_buy/rate res2 = polo.buy(currencyPair=pair, rate= rate, amount = amount_pair, immediateOrCancel = 1) trade = res2['resultingTrades'] total = [trade[k]['total'] for k in range(len(trade))] total_bought = total_bought + np.sum(total) total_to_buy = total_to_buy - np.sum(total) # Update the recapitulative of trades passed res = res + [res2] # II - Create a recapitulative table trades = [res[k]['resultingTrades'] for k in range(len(res))] dates = [trades[i][0]['date'] for i in range(len(trades))] amounts = [trades[i][0]['takerAdjustment'] for i in range(len(trades))] # amount bought expressed in the pair totals = [trades[i][0]['total'] for i in range(len(trades))] #amounts expressed in dollar rates = [trades[i][0]['rate'] for i in range(len(trades))] #rate of the pair for each trade fees = res[0]['fee'] recap= pd.DataFrame({'Date' : dates, 'AmountInCurrency' : amounts, 'Total$' : totals, 'Rate' : rates}) recap['FeesPaid$'] = recap['Total$']*fees recap['Pair'] = pair recap['Type'] = 'Buy' # III - If selected, store the trades in a csv if store: if not os.path.exists('./Trades'): os.makedirs('./Trades') recap.to_csv('./Trades/Buy_{}_{}_{}.csv'.format(pair, amount, res[0]['orderNumber']), index = False, sep = ';') print('We bought {} $ of {}. '.format(total_bought, pair)) return(recap)
def configure_poloniex(): api_key = config.API_KEY api_secret = config.API_SECRET polo = Poloniex(api_key, api_secret) _timing = time.time() def _arc(f): def decorator(*args, **kwargs): logging.info(('request', f.__name__, str(args), str(kwargs))) while time.time() - _timing < 0.5: time.sleep(0.01) return f(*args, **kwargs) return decorator polo.buy = _arc(polo.buy) polo.sell = _arc(polo.sell) polo.returnCompleteBalances = _arc(polo.returnCompleteBalances) polo.returnOpenOrders = _arc(polo.returnOpenOrders) polo.cancelOrder = _arc(polo.cancelOrder) polo.moveOrder = _arc(polo.moveOrder) polo.returnTradeHistory = _arc(polo.returnTradeHistory) return polo
order_book = bot.returnOrderBook(currency_pair) asks = order_book["asks"] btc_ask_volume = 0.0 for i, val in enumerate(asks): btc_ask_volume += (float(val[0]) * val[1]) if btc_ask_volume >= btc_volume_each_trade: return float(val[0]) # buy loop while True: startTime = time.time() buy_price = get_buy_price() amount_traded_in_btc += btc_volume_each_trade xmr_amount_to_buy = btc_volume_each_trade/buy_price amount_xmr_bought += xmr_amount_to_buy # TODO: Use the trade result print "---BUYING--- Buy price: ", buy_price, " Total XMR bought: ", amount_xmr_bought, "Total BTC spent: ", amount_traded_in_btc print bot.buy(currency_pair, buy_price, xmr_amount_to_buy, 1) if amount_traded_in_btc >= total_amount_to_spend: print "Buying completed. Bought ", amount_xmr_bought, " XMR, spent ", amount_traded_in_btc, " BTC" break endTime = time.time() elapsedTime = endTime - startTime sleepTime = frequency - elapsedTime if sleepTime < 0.0: sleepTime = 0.0 time.sleep(sleepTime)
class LiveTrader: params = { "initial_depth": 3, "max_depth": 4, "variance_threshold": 0.00013, "band_threshold": 0.00013, "iteration_level": 3, "division_threshold": 0.00013, "max_weight": 8.0, "activation": "tanh" } # Config for CPPN. config = neat.config.Config(neat.genome.DefaultGenome, neat.reproduction.DefaultReproduction, neat.species.DefaultSpeciesSet, neat.stagnation.DefaultStagnation, 'config_trader') def __init__(self, ticker_len, target_percent, hd, base_sym="BTC"): self.base_sym = base_sym self.load_polo_client() self.hd = hd self.target_percent = target_percent self.ticker_len = ticker_len self.end_ts = datetime.now() + timedelta(seconds=(ticker_len * 55)) self.hs = HistWorker() self.refresh_data() self.tickers = self.polo.returnTicker() self.refresh_balances() self.sellCoins() self.set_target() self.inputs = self.hs.hist_shaped.shape[0] * ( self.hs.hist_shaped[0].shape[1]) self.outputs = self.hs.hist_shaped.shape[0] self.end_idx = len(self.hs.hist_shaped[0]) - 1 self.make_shapes() self.load_net() self.poloTrader() def load_polo_client(self): keys = self.get_keys() self.polo = Poloniex(keys[0], keys[1]) def purge_polo_client(self): self.polo = None def load_net(self): champ_file = open("./champ_data/latest_greatest.pkl", 'rb') g = pickle.load(champ_file) #file.close() the_cppn = neat.nn.FeedForwardNetwork.create(g, self.config) self.cppn = the_cppn def refresh_data(self): try: self.hs.pull_polo_usd_live(21) self.hs.combine_live_usd_frames() except Exception as e: print(e) time.sleep(360) self.refresh_data() def refresh_balances(self): try: self.bal = self.polo.returnCompleteBalances() except Exception as e: print(e) time.sleep(360) self.refresh_balances() def get_one_bar_input_2d(self): master_active = [] try: for x in range(0, self.hd): active = [] #print(self.outputs) for y in range(0, self.outputs): sym_data = self.hs.hist_shaped[y][self.end_idx - x] #print(len(sym_data)) active += sym_data.tolist() master_active.append(active) except: print("error getting look back data") self.refresh_data() self.get_one_bar_input_2d() #print(active) return master_active def closeOrders(self): try: orders = self.polo.returnOpenOrders() except Exception as e: print(e) print('error getting open orers') time.sleep(360) self.closeOrders() for o in orders: if orders[o] != []: try: ordnum = orders[o][0]['orderNumber'] self.polo.cancelOrder(ordnum) except Exception as e: print(e) print('error closing') def sellCoins(self): for b in self.tickers: if (b.split("_")[0] == self.base_sym): price = self.get_price(b) price = price - (price * .005) self.sell_coin(b, price) def buy_coin(self, coin, price): amt = self.target / price if (self.bal[self.base_sym]["available"] > self.target): try: self.polo.buy(coin, price, amt) print("buying: ", coin) except Exception as e: print("error buying ", coin) print(e) return def sell_coin(self, coin, price): if (self.base_sym != "BTC"): amt = self.bal[coin.split("_")[1]]["available"] else: amt = self.bal[coin.split("_")[1]]["btcValue"] if (amt * price > .0001): try: self.polo.sell(coin, price, amt) print("selling this shit: ", coin) except Exception as e: print("error selling ", coin) print(e) return def reset_tickers(self): try: self.tickers = self.polo.returnTicker() self.bal = self.polo.returnCompleteBalances() except Exception as e: print(e) time.sleep(360) self.reset_tickers() return def get_keys(self): with open("./godsplan.txt") as f: content = f.readlines() content[0] = content[0][:-1] if (content[1][-1:] == "\n"): content[1] = content[1][:-1] return content def make_shapes(self): sign = 1 self.out_shapes = [] self.in_shapes = [] for ix in range(1, self.outputs + 1): sign = sign * -1 self.out_shapes.append((0.0 - (sign * .005 * ix), 0.0, -1.0)) for ix2 in range(1, (self.inputs // self.outputs) + 1): self.in_shapes.append( (0.0 + (sign * .01 * ix2), 0.0 - (sign * .01 * ix2), 0.0)) self.subStrate = Substrate(self.in_shapes, self.out_shapes) def get_price(self, coin): return self.tickers[coin]['last'] def set_target(self): total = 0 full_bal = self.polo.returnCompleteBalances() for x in full_bal: total += full_bal[x]["btcValue"] if (self.base_sym != "BTC"): total = total * self.get_price(self.base_sym + "_" + "BTC") * self.target_percent print(total) self.target = total def poloTrader(self): self.refresh_balances() end_prices = {} active = self.get_one_bar_input_2d() self.load_net() network = ESNetwork(self.subStrate, self.cppn, self.params, self.hd) net = network.create_phenotype_network_nd('paper_net.png') net.reset() sell_syms = [] buy_syms = [] buy_signals = [] sell_signals = [] self.closeOrders() for n in range(1, self.hd): net.activate(active[self.hd - n]) out = net.activate(active[0]) for x in range(len(out)): sym = self.hs.coin_dict[x] end_prices[sym] = self.get_price(self.base_sym + "_" + sym) if (out[x] > .5): buy_signals.append(out[x]) buy_syms.append(sym) if (out[x] < -.5): sell_signals.append(out[x]) sell_syms.append(sym) #rng = iter(shuffle(rng)) sorted_buys = np.argsort(buy_signals)[::-1] sorted_sells = np.argsort(sell_signals) self.reset_tickers() for x in sorted_sells: sym = sell_syms[x] p = self.get_price(self.base_sym + "_" + sym) price = p - (p * .005) self.sell_coin(self.base_sym + "_" + sym, price) for x in sorted_buys: sym = buy_syms[x] self.target_percent = .1 + out[x] - .45 p = self.get_price(self.base_sym + "_" + sym) price = p * 1.005 self.buy_coin(self.base_sym + "_" + sym, price) if datetime.now() >= self.end_ts: return else: self.purge_polo_client() time.sleep(self.ticker_len) self.load_polo_client() self.refresh_data() self.make_shapes() #self.closeOrders() self.poloTrader()
print("---!SELL Complete!--- fitted in Third Bid") break else: # Sell to the highest 2 bids (BuyOrders 0&1) sell = polo.sell(pair, OrderBidsPrice1, AltSell) # Make the SellOrder print("---!SELL Complete!--- fitted in Second Bid") break break # End SELL part (if float(AltWorth) >= float(budget):) else: # BUY!!! Compare BuyOrder with Available Asks (same Logic as SELL part where sell=buy & bid=ask) #print("**BUY** AltWorth LOWER budget") OrderAsksPrice0 = polo.returnOrderBook()[pair]['asks'][0][0] OrderAsksAmount0 = polo.returnOrderBook()[pair]['asks'][0][1] OrderAsksSum0 = float(OrderAsksAmount0) * float(OrderAsksPrice0) if float(AltBuyWorth) <= float(OrderAsksSum0): #Order the OrderBook0 buy = polo.buy(pair, Ask, AltBuy) print("---!Buy Complete!--- fitted in first Ask") break else: #OrderBook0 to small Calculate for Order 0&1 print("Order is Bigger than AsksSum0") OrderAsksPrice1 = polo.returnOrderBook()[pair]['asks'][1][0] OrderAsksAmount1 = polo.returnOrderBook()[pair]['asks'][1][1] OrderAsksSum1 = float(OrderAsksAmount1) * float(OrderAsksPrice1) OrderAsksSum01 = float(OrderAsksSum0) + float(OrderAsksSum1) if float(AltBuyWorth) >= float(OrderAsksSum01): #Orderbook 0&1 to small. Order 0,1&2 print("Order is Bigger than AsksSum01") OrderAsksPrice2 = polo.returnOrderBook()[pair]['asks'][2][0] OrderAsksAmount2 = polo.returnOrderBook()[pair]['asks'][2][1] OrderAsksSum2 = float(OrderAsksAmount2) * float(OrderAsksPrice2) OrderAsksSum012 = float(OrderAsksSum01) + float(OrderAsksSum2)
class Polo(Base): """ Poloniex interface """ def __init__(self, config, verbosity=2): super(Polo, self).__init__() api_key = config['api_key'] secret = config['secret'] self.transaction_fee = float(config['transaction_fee']) self.polo = Poloniex(api_key, secret) self.buy_order_type = config['buy_order_type'] self.sell_order_type = config['sell_order_type'] self.verbosity = verbosity self.pair_delimiter = '_' def get_balances(self): """ Return available account balances (function returns ONLY currencies > 0) """ try: balances = self.polo.returnBalances() only_non_zeros = { k: float(v) for k, v in balances.items() if float(v) > 0.0 } except PoloniexError as e: print( colored('!!! Got exception (polo.get_balances): ' + str(e), 'red')) only_non_zeros = dict() return only_non_zeros def get_symbol_ticker(self, symbol, candle_size=5): """ Returns real-time ticker Data-Frame """ ticker = self.polo.returnTicker()[symbol] df = pd.DataFrame.from_dict(ticker, orient="index") df = df.T # We will use 'last' price as closing one df = df.rename(columns={'last': 'close', 'baseVolume': 'volume'}) df['close'] = df['close'].astype(float) df['volume'] = df['volume'].astype(float) df['pair'] = symbol df['date'] = int(datetime.datetime.utcnow().timestamp()) return df def return_ticker(self): """ Returns ticker for all currencies """ return self.polo.returnTicker() def cancel_order(self, order_number): """ Cancels order for given order number """ return self.polo.cancelOrder(order_number) def return_open_orders(self, currency_pair='all'): """ Returns your open orders """ return self.polo.returnOpenOrders(currency_pair) def get_pairs(self): """ Returns ticker pairs for all currencies """ ticker = self.polo.returnTicker() return list(ticker) def return_candles(self, currency_pair, epoch_start, epoch_end, period=False): """ Returns candlestick chart data """ data = [] try: data = self.polo.returnChartData(currency_pair, period, epoch_start, epoch_end) except (PoloniexError, JSONDecodeError) as e: print() print( colored( '!!! Got exception while retrieving polo data:' + str(e) + ', pair: ' + currency_pair, 'red')) return data def trade(self, actions, wallet, trade_mode): if trade_mode == TradeMode.backtest: return Base.trade(actions, wallet, trade_mode) else: actions = self.life_trade(actions) return actions def life_trade(self, actions): """ Places orders and returns order number !!! For now we are NOT handling postOnly type of orders !!! """ for action in actions: if action.action == TradeState.none: actions.remove(action) continue # Handle buy_sell_all cases wallet = self.get_balances() if action.buy_sell_all: action.amount = self.get_buy_sell_all_amount(wallet, action) if self.verbosity > 0: print( 'Processing live-action: ' + str(action.action) + ', amount:', str(action.amount) + ', pair:', action.pair + ', rate:', str(action.rate) + ', buy_sell_all:', action.buy_sell_all) # If we don't have enough assets, just skip/remove the action if action.amount == 0.0: print( colored( 'No assets to buy/sell, ...skipping: ' + str(action.amount) + ' ' + action.pair, 'green')) actions.remove(action) continue # ** Buy Action ** if action.action == TradeState.buy: try: print( colored( 'Setting buy order: ' + str(action.amount) + '' + action.pair, 'green')) action.order_number = self.polo.buy( action.pair, action.rate, action.amount, self.buy_order_type) except PoloniexError as e: print( colored( 'Got exception: ' + str(e) + ' Txn: buy-' + action.pair, 'red')) continue amount_unfilled = action.order_number.get('amountUnfilled') if float(amount_unfilled) == 0.0: actions.remove(action) print( colored( 'Bought: ' + str(action.amount) + '' + action.pair, 'green')) else: action.amount = amount_unfilled print( colored( 'Not filled 100% buy txn. Unfilled amount: ' + str(amount_unfilled) + '' + action.pair, 'red')) # ** Sell Action ** elif action.action == TradeState.sell: try: print( colored( 'Setting sell order: ' + str(action.amount) + '' + action.pair, 'yellow')) action.order_number = self.polo.sell( action.pair, action.rate, action.amount, self.buy_order_type) except PoloniexError as e: print( colored( 'Got exception: ' + str(e) + ' Txn: sell-' + action.pair, 'red')) continue amount_unfilled = action.order_number.get('amountUnfilled') if float(amount_unfilled) == 0.0: actions.remove(action) print( colored( 'Sold: ' + str(action.amount) + '' + action.pair, 'yellow')) else: action.amount = amount_unfilled print( colored( 'Not filled 100% sell txn. Unfilled amount: ' + str(amount_unfilled) + '' + action.pair, 'red')) return actions
i = i + 1 except: print btrxavantaj, "\tBITTREX ALIS\t", bs, "\n\t\tPOLO SATIS\t", pa, "\tEmir verilemedi" print datetime.now().strftime('%Y-%m-%d %H:%M:%S') continue if poloavantaj > zorluk and polo_wallet > islem_ucreti and btrx_wallet_c * ba > islem_ucreti: try: ps = ps * (1 + (kayip + (poloavantaj - zorluk)) / 1000) ba = ba * (1 - (kayip + (poloavantaj - zorluk)) / 1000) order_s = my_bittrex.sell_limit( bittrex_currency, amount_satis, ba) polo.buy(poloniex_currency, ps, amount_alis) print poloavantaj, "\tPOLO ALIS\t", ps, "\n\t\tBITTREXSATIS\t", ba print datetime.now().strftime('%Y-%m-%d %H:%M:%S') # emir kontrolu. islem sonra devam edecek (bittrex) while True: try: kontrol = my_bittrex.get_order( order_s['result']['uuid']) if kontrol['result']['IsOpen'] == False: print "bittrex satim emri gerceklesti" break except: print "bittrex satim emi kontrol hatasi"
class LiveTrader: params = {"initial_depth": 4, "max_depth": 4, "variance_threshold": 0.00013, "band_threshold": 0.00013, "iteration_level": 3, "division_threshold": 0.00013, "max_weight": 8.0, "activation": "tanh"} # Config for CPPN. config = neat.config.Config(neat.genome.DefaultGenome, neat.reproduction.DefaultReproduction, neat.species.DefaultSpeciesSet, neat.stagnation.DefaultStagnation, 'config_trader') def __init__(self, ticker_len, target_percent, hd): self.polo = Poloniex(key, secret) self.hist_depth = hd self.target_percent = target_percent self.ticker_len = ticker_len self.end_ts = datetime.now()+timedelta(seconds=(ticker_len*55)) self.hs = HistWorker() self.refresh_data() self.tickers = self.polo.returnTicker() self.bal = self.polo.returnBalances() self.sellCoins() self.set_target() self.inputs = self.hs.hist_shaped.shape[0]*(self.hs.hist_shaped[0].shape[1]) self.outputs = self.hs.hist_shaped.shape[0] self.make_shapes() self.leaf_names = [] self.db = tinydb.database("live_hist/memories.json") for l in range(len(self.in_shapes[0])): self.leaf_names.append('leaf_one_'+str(l)) self.leaf_names.append('leaf_two_'+str(l)) #self.load_net() self.poloTrader() def load_net(self): #file = open("./champ_gens/thot-checkpoint-13",'rb') g = neat.Checkpointer.restore_checkpoint("./champ_gens/thot-checkpoint-25") best_fit = 0.0 for gx in g.population: if g.population[gx].fitness != None: if g.population[gx].fitness > best_fit: bestg = g.population[gx] g = bestg #file.close() [the_cppn] = create_cppn(g, self.config, self.leaf_names, ['cppn_out']) self.cppn = the_cppn def refresh_data(self): self.hs.pull_polo_live(20) self.hs.combine_live_frames(self.hist_depth) def make_shapes(self): self.in_shapes = [] self.out_shapes = [] sign = 1 for ix in range(1,self.outputs+1): sign = sign *-1 self.out_shapes.append((0.0-(sign*.005*ix), -1.0, -1.0)) for ix2 in range(1,(self.inputs//self.outputs)+1): self.in_shapes.append((0.0+(sign*.01*ix2), 0.0-(sign*.01*ix2), 1.0)) def get_one_bar_input_2d(self,end_idx=10): master_active = [] for x in range(0, self.hist_depth): active = [] #print(self.outputs) for y in range(0, self.outputs): sym_data = self.hs.hist_shaped[y][self.hist_depth-x] #print(len(sym_data)) active += sym_data.tolist() master_active.append(active) #print(active) return master_active def closeOrders(self): try: orders = self.polo.returnOpenOrders() except: print('error getting open orers') time.sleep(360) self.closeOrder() for o in orders: if orders[o] != []: try: ordnum = orders[o][0]['orderNumber'] self.polo.cancelOrder(ordnum) except: print('error closing') def sellCoins(self): for b in self.tickers: if(b[:3] == "BTC"): price = self.get_price(b) price = price - (price * .005) self.sell_coin(b, price) def buy_coin(self, coin, price): amt = self.target / price if(self.bal['BTC'] > self.target): self.polo.buy(coin, price, amt, fillOrKill=1) print("buying: ", coin) return def sell_coin(self, coin, price): amt = self.bal[coin[4:]] if (amt*price > .0001): try: self.polo.sell(coin, price, amt,fillOrKill=1) print("selling this shit: ", coin) except: print('error selling', coin) return def reset_tickers(self): try: self.tickers = self.polo.returnTicker() self.bal = self.polo.returnBalances() except: time.sleep(360) self.reset_tickers() return def get_price(self, coin): return self.tickers[coin]['last'] def set_target(self): total = 0 full_bal = self.polo.returnCompleteBalances() for x in full_bal: total += full_bal[x]["btcValue"] self.target = total*self.target_percent def poloTrader(self): end_prices = {} active = self.get_one_bar_input_2d() self.load_net() sub = Substrate(self.in_shapes, self.out_shapes) network = ESNetwork(sub, self.cppn, self.params) net = network.create_phenotype_network_nd('paper_net.png') net.reset() for n in range(1, self.hist_depth+1): out = net.activate(active[self.hist_depth-n]) #print(len(out)) rng = len(out) #rng = iter(shuffle(rng)) self.reset_tickers() for x in np.random.permutation(rng): sym = self.hs.coin_dict[x] #print(out[x]) try: if(out[x] < -.5): print("selling: ", sym) p = self.get_price('BTC_'+sym) price = p -(p*.01) self.sell_coin('BTC_'+sym, price) elif(out[x] > .5): print("buying: ", sym) self.target_percent = .1 + out[x] - .45 p = self.get_price('BTC_'+sym) price = p*1.01 self.buy_coin('BTC_'+sym, price) except: print('error', sym) #skip the hold case because we just dont buy or sell hehe if datetime.now() >= self.end_ts: return else: time.sleep(self.ticker_len) self.refresh_data() #self.closeOrders() self.poloTrader()
class LiveTrader: params = { "initial_depth": 0, "max_depth": 4, "variance_threshold": 0.03, "band_threshold": 0.3, "iteration_level": 1, "division_threshold": 0.3, "max_weight": 5.0, "activation": "tanh" } # Config for CPPN. config = neat.config.Config(neat.genome.DefaultGenome, neat.reproduction.DefaultReproduction, neat.species.DefaultSpeciesSet, neat.stagnation.DefaultStagnation, 'config_trader') def __init__(self, ticker_len, target_percent): self.polo = Poloniex(key, secret) self.currentHists = {} self.hist_shaped = {} self.coin_dict = {} self.ticker_len = ticker_len self.end_ts = datetime.now() + timedelta(seconds=(ticker_len * 55)) file = open("es_trade_god_cppn.pkl", 'rb') self.cppn = pickle.load(file) file.close() self.tickers = self.polo.returnTicker() self.bal = self.polo.returnBalances() self.target = self.bal['BTC'] * target_percent self.pull_polo() self.inputs = self.hist_shaped.shape[0] * ( self.hist_shaped[0].shape[1] - 1) self.outputs = self.hist_shaped.shape[0] self.multiplier = self.inputs / self.outputs def make_shapes(self): self.in_shapes = [] self.out_shapes = [] sign = 1 for ix in range(self.outputs): sign = sign * -1 self.out_shapes.append((sign * ix, 1)) for ix2 in range(len(self.hist_shaped[0][0]) - 1): self.in_shapes.append((sign * ix, (1 + ix2) * .1)) def pull_polo(self): tickLen = '7200' start = datetime.today() - timedelta(1) start = str(int(start.timestamp())) ix = 0 for coin in self.tickers: if coin[:3] == 'BTC': hist = requests.get( 'https://poloniex.com/public?command=returnChartData¤cyPair=' + coin + '&start=' + start + '&end=9999999999&period=' + tickLen) try: df = pd.DataFrame(hist.json()) #df.rename(columns = lambda x: col_prefix+'_'+x, inplace=True) as_array = np.array(df) #print(len(as_array)) self.currentHists[coin] = df self.hist_shaped[ix] = as_array self.coin_dict[ix] = coin ix += 1 except: print("error reading json") self.hist_shaped = pd.Series(self.hist_shaped) self.end_idx = len(self.hist_shaped[0]) - 1 def get_one_bar_input_2d(self): active = [] misses = 0 for x in range(0, self.outputs): try: sym_data = self.hist_shaped[x][self.end_idx] for i in range(len(sym_data)): if (i != 1): active.append(sym_data[i].tolist()) except: self.outputs -= 1 self.inputs -= self.multiplier print('error') #print(active) self.make_shapes() return active def closeOrders(self): orders = self.polo.returnOpenOrders() for o in orders: if orders[o] != []: try: ordnum = orders[o][0]['orderNumber'] self.polo.cancelOrder(ordnum) except: print('error closing') def sellCoins(self, coinlist, currency): balances = self.polo.returnBalances() for b in balances: bal = balances[b] * .99 def buy_coin(self, coin, price): amt = self.target if (self.bal['BTC'] > self.target): try: self.polo.buy(coin, price, amt, fillOrKill=1) print("buying: ", coin) except: print('error buying', coin) return def sell_coin(self, coin, price): amt = self.bal[coin[4:]] try: self.polo.sell(coin, price, amt, fillOrKill=1) except: print('error selling: ', coin) return def reset_tickers(self): self.tickers = self.polo.returnTicker() return def get_price(self, coin): return self.tickers[coin]['last'] def poloTrader(self): end_prices = {} active = self.get_one_bar_input_2d() sub = Substrate(self.in_shapes, self.out_shapes) network = ESNetwork(sub, self.cppn, self.params) net = network.create_phenotype_network() net.reset() for n in range(network.activations): out = net.activate(active) #print(len(out)) rng = len(out) #rng = iter(shuffle(rng)) for x in np.random.permutation(rng): sym = self.coin_dict[x] #print(out[x]) try: if (out[x] < -.5): print("selling: ", sym) self.sell_coin( sym, self.get_price(sym), ) elif (out[x] > .5): print("buying: ", sym) self.buy_coin(sym, self.get_price(sym)) except: print('error', sym) #skip the hold case because we just dont buy or sell hehe end_prices[sym] = self.get_price(sym) if datetime.now() >= self.end_ts: return else: time.sleep(self.ticker_len) self.reset_tickers self.pull_polo() self.poloTrader()
class Trader(object): def __init__(self, api_key, api_secret, coin, currency, dust_total=10, dust_amount=100.0, min_spread=0.0001, max_trading_amount=1): # set currency pair self.coin = coin self.currency = currency self.my_pair = '%s_%s' % (currency, coin) # we'll need this while finding buy/sell prices self.dust_total = self.make_satoshi(dust_total) self.dust_amount = self.make_satoshi(dust_amount) self.min_spread = self.make_satoshi(min_spread) self.max_trading_amount = self.make_satoshi(max_trading_amount) # initialize the poloniex api self.api_key = api_key self.api_secret = api_secret self.polo = Poloniex(api_key, api_secret) # initialize other variables self.coin_balance = self.make_satoshi('0.0') self.currency_balance = self.make_satoshi('0.0') self.total_coin_balance = self.make_satoshi('0.0') self.total_currency_balance = self.make_satoshi('0.0') self.open_orders_raw = [] self.open_orders = [] self.open_orders_sell = [] self.open_orders_buy = [] self.order_book_raw = [] self.order_book = {} self.order_book["buy"] = [] self.order_book["sell"] = [] self.sell_price = self.make_satoshi('0.0') self.buy_price = self.make_satoshi('0.0') self.price_spread = self.make_satoshi('0.0') self.sell_amount = self.make_satoshi('0.0') self.buy_amount = self.make_satoshi('0.0') self.trade = False # those are hardcoded. may be added to settings later. self.min_currency_balance = self.make_satoshi('0.00100000') # seconds to wait for exchange rate limits. self.exchange_wait_time = 0.8 def make_satoshi(self, num): return decimal.Decimal(num).quantize(decimal.Decimal('1.00000000')) def load_open_orders(self): # loads open orders. Resets the balances so load_balances method should be called after. self.total_coin_balance = self.make_satoshi('0.0') self.total_currency_balance = self.make_satoshi('0.0') self.open_orders_raw = self.polo.returnOpenOrders( currencyPair=self.my_pair) self.open_orders = [] self.open_orders_sell = [] self.open_orders_buy = [] for item in self.open_orders_raw: order = {} order['type'] = item['type'] order["order_number"] = item['orderNumber'] order["price"] = self.make_satoshi(item['rate']) order["amount"] = self.make_satoshi(item['amount']) order["total"] = self.make_satoshi(order['price'] * order['amount']) order["starting_amount"] = self.make_satoshi( item['startingAmount']) self.open_orders.append(order) if order['type'] == 'sell': self.open_orders_sell.append(order) self.total_coin_balance = self.total_coin_balance + order[ "amount"] else: self.open_orders_buy.append(order) self.total_currency_balance = self.total_currency_balance + order[ "total"] return self.open_orders def load_balances(self): # first load the open orders to get the balances in open orders. self.load_open_orders() # request from exchange self.balances = self.polo.returnBalances() # set the coin balance self.coin_balance = self.make_satoshi(self.balances[self.coin]) self.total_coin_balance = self.total_coin_balance + self.coin_balance # '0.00000001' makes things complicated. get rid of it. if self.coin_balance <= self.make_satoshi('0.00000001'): self.coin_balance = self.make_satoshi('0.0') if self.total_coin_balance <= self.make_satoshi('0.00000001'): self.total_coin_balance = self.make_satoshi('0.0') # set the main currency balance self.currency_balance = self.make_satoshi(self.balances[self.currency]) self.total_currency_balance = self.total_currency_balance + self.currency_balance # '0.00000001' makes things complicated. get rid of it. if self.currency_balance <= self.make_satoshi('0.00000001'): self.currency_balance = self.make_satoshi('0.0') if self.total_currency_balance <= self.make_satoshi('0.00000001'): self.total_currency_balance = self.make_satoshi('0.0') # added for debugging. make the BTC amount > 0 so we can test buying. # self.total_currency_balance = self.make_satoshi('0.10000000') def load_order_book(self): self.order_book_raw = self.polo.returnOrderBook( currencyPair=self.my_pair, depth='200') self.order_book["buy"] = [] self.order_book["sell"] = [] self.process_order_book('buy', self.order_book_raw["bids"]) self.process_order_book('sell', self.order_book_raw["asks"]) return self.order_book def process_order_book(self, order_type, order_book_raw): self.order_book[order_type] = [] total = self.make_satoshi("0.0") for item in order_book_raw: order = {} order['type'] = order_type order["price"] = self.make_satoshi(item[0]) order["amount"] = self.make_satoshi(item[1]) order["cur"] = self.make_satoshi(order["price"] * order["amount"]) total = self.make_satoshi(total + order["cur"]) order["total"] = total # mark the order if its my order. put order number from open_orders order['order_number'] = None for open_order in self.open_orders: if (open_order['type'] == order['type']) and (open_order["price"] == order["price"]): order["order_number"] = open_order['order_number'] print "order:", order self.order_book[order_type].append(order) return self.order_book[order_type] def find_sell_price(self): total = self.make_satoshi("0.0") for order in self.order_book['sell']: if order['order_number'] is None: total = self.make_satoshi(total + order["cur"]) if (order["amount"] >= dust_amount) or (total >= dust_total): return self.make_satoshi(order["price"] - self.make_satoshi("0.00000003")) return False def find_buy_price(self): total = self.make_satoshi("0.0") for order in self.order_book['buy']: if order['order_number'] is None: total = self.make_satoshi(total + order["cur"]) if (order["amount"] >= dust_amount) or (total >= dust_total): return self.make_satoshi(order["price"] + self.make_satoshi("0.00000003")) return False def decide_to_trade(self): self.sell_price = self.find_sell_price() self.buy_price = self.find_buy_price() self.price_spread = self.sell_price - self.buy_price print "Sell Price:", self.sell_price print "Buy Price:", self.buy_price print "Price Spread:", self.price_spread if (not self.sell_price) or (not self.buy_price): print "Something is wrong with sell and buy prices. Will not trade!" self.trade = False return False if self.total_currency_balance > self.min_currency_balance: print 'I have %s %s, will try to buy %s.' % ( self.total_currency_balance, self.currency, self.coin) self.trade = 'buy' return True else: if self.price_spread >= self.min_spread: print 'Spread is good. Will trade' # sell or buy? if self.total_coin_balance > 0: print 'I have %s %s, will try to sell %s for %s.' % ( self.total_coin_balance, self.coin, self.coin, self.currency) self.trade = 'sell' return True else: print 'I have nothing to trade.' self.trade = False else: print 'Price Spread is not good. Stop trading.' self.trade = False return False def cancel_open_orders(self, buy_sell): for order in self.open_orders: if order['type'] == buy_sell: print "canceling order:", order try: retval = self.polo.cancelOrder(order["order_number"]) except: retval = False print 'ERROR canceling order.' print "cancel order retval:", retval self.open_orders.remove(order) if buy_sell == 'sell': self.open_orders_sell.remove(order) else: self.open_orders_buy.remove(order) def cancel_open_order(self, order): print "canceling order:", order try: retval = self.polo.cancelOrder(order["order_number"]) except: retval = False print 'ERROR canceling order.' time.sleep(0.2) print "cancel order retval:", retval self.open_orders.remove(order) if order['type'] == 'sell': self.open_orders_sell.remove(order) else: self.open_orders_buy.remove(order) def add_sell_order(self): # compute the amount if self.total_coin_balance > self.max_trading_amount: self.sell_amount = self.max_trading_amount else: self.sell_amount = self.total_coin_balance print "self.sell_amount:", self.sell_amount # send order to exchange try: retval = self.polo.sell(currencyPair=self.my_pair, rate=self.sell_price, amount=self.sell_amount) except: print 'ERROR adding SELL order.' retval = False print retval return retval def sell(self): # cancel all buy orders first. self.cancel_open_orders('buy') # check open sell orders if the sell price is ok. for order in self.open_orders_sell: if order['price'] == self.sell_price: print "order is ok:", order else: # cancel the order. retval = self.cancel_open_order(order) print 'self.open_orders_sell:', len(self.open_orders_sell) if len(self.open_orders_sell) == 0: print 'adding a new sell order' retval = self.add_sell_order() def add_buy_order(self): # compute the amount if self.total_currency_balance > self.make_satoshi('0.00001000'): self.buy_amount = self.make_satoshi( self.total_currency_balance / self.buy_price) - self.make_satoshi('0.00000001') print "Buying amount:", self.buy_amount else: print "Buying amount is low. not buying:" return False # send order to exchange try: retval = self.polo.buy(currencyPair=self.my_pair, rate=self.buy_price, amount=self.buy_amount) except: print 'ERROR adding BUY order.' retval = False print retval return retval def buy(self): # cancel all buy orders first. self.cancel_open_orders('sell') # check open sell orders if the sell price is ok. for order in self.open_orders_buy: if order['price'] == self.buy_price: print "order is ok:", order else: # cancel the order. retval = self.cancel_open_order(order) print 'self.open_orders_buy:', len(self.open_orders_buy) if len(self.open_orders_buy) == 0: print 'adding a new buy order' retval = self.add_buy_order() def run_scalping(self): while True: now = datetime.datetime.now() print str(now) self.load_balances() self.load_order_book() print '%s Balance: %s' % (self.currency, self.total_currency_balance) print '%s Balance: %s' % (self.coin, self.total_coin_balance) # trade or not trade? trade = self.decide_to_trade() print "Trade?", trade if self.trade == 'sell': self.sell() elif self.trade == 'buy': self.buy() else: #Will not trade. Cancel all orders. self.cancel_open_orders('buy') self.cancel_open_orders('sell') print "." print "open orders:", self.open_orders print "." now = datetime.datetime.now() print str(now) print "Will wait a little bit for not to flood the exchange..." time.sleep(self.exchange_wait_time) def add_sell_all_order(self): # compute the amount self.sell_amount = self.total_coin_balance print "self.sell_amount:", self.sell_amount if self.sell_amount: # send order to exchange try: retval = self.polo.sell(currencyPair=self.my_pair, rate=self.sell_price, amount=self.sell_amount) except: print 'ERROR adding SELL ALL order.' retval = False print retval return retval else: return False def sell_all(self): # cancel all buy orders first. self.cancel_open_orders('buy') # check open sell orders if the sell price is ok. for order in self.open_orders_sell: if order['price'] == self.sell_price: print "order is ok:", order else: # cancel the order. retval = self.cancel_open_order(order) print 'self.open_orders_sell:', len(self.open_orders_sell) if len(self.open_orders_sell) == 0: print 'adding a new sell all order' retval = self.add_sell_all_order() def run_sell_all(self): self.trade = 'sell' while self.trade == 'sell': now = datetime.datetime.now() print str(now) self.load_balances() self.load_order_book() print '%s Balance: %s' % (self.currency, self.total_currency_balance) print '%s Balance: %s' % (self.coin, self.total_coin_balance) self.sell_price = self.find_sell_price() print "Sell Price:", self.sell_price if self.total_coin_balance > 0.0: print 'I have %s %s, will try to sell %s for %s.' % ( self.total_coin_balance, self.coin, self.coin, self.currency) self.trade = 'sell' else: print 'I have nothing to trade.' self.trade = False if self.trade == 'sell': self.sell_all() else: #Will not trade. Cancel all orders. self.cancel_open_orders('buy') self.cancel_open_orders('sell') print "." print "open orders:", self.open_orders print "." now = datetime.datetime.now() print str(now) print "Will wait a little bit for not to flood the exchange..." time.sleep(self.exchange_wait_time) def add_buy_all_order(self): # compute the amount if self.total_currency_balance > self.make_satoshi('0.00001000'): self.buy_amount = self.make_satoshi( self.total_currency_balance / self.buy_price) - self.make_satoshi('0.00000001') print "Buying amount:", self.buy_amount else: print "Buying amount is low. not buying:" return False # send order to exchange try: retval = self.polo.buy(currencyPair=self.my_pair, rate=self.buy_price, amount=self.buy_amount) except: print 'ERROR adding BUY ALL order.' retval = False print retval return retval def buy_all(self): # cancel all buy orders first. self.cancel_open_orders('sell') # check open sell orders if the sell price is ok. for order in self.open_orders_buy: if order['price'] == self.buy_price: print "order is ok:", order else: # cancel the order. retval = self.cancel_open_order(order) print 'self.open_orders_buy:', len(self.open_orders_buy) if len(self.open_orders_buy) == 0: print 'adding a new buy all order' retval = self.add_buy_all_order() def run_buy_all(self): self.trade = 'buy' while self.trade == 'buy': now = datetime.datetime.now() print str(now) self.load_balances() self.load_order_book() print '%s Balance: %s' % (self.currency, self.total_currency_balance) print '%s Balance: %s' % (self.coin, self.total_coin_balance) self.buy_price = self.find_buy_price() print "Buy Price:", self.buy_price if self.total_currency_balance > self.min_currency_balance: print 'I have %s %s, will try to buy %s.' % ( self.total_currency_balance, self.currency, self.coin) self.trade = 'buy' else: print 'I have nothing to trade.' self.trade = False if self.trade == 'buy': self.buy_all() else: #Will not trade. Cancel all orders. self.cancel_open_orders('buy') self.cancel_open_orders('sell') print "." print "open orders:", self.open_orders print "." now = datetime.datetime.now() print str(now) print "Will wait a little bit for not to flood the exchange..." time.sleep(self.exchange_wait_time)
class poloniex_functions(object): def __init__(self): self.output = BotLog() self.conn = Poloniex('secret', 'key') def getBalance(self): while True: try: balData = { k: v for k, v in self.conn.returnBalances().items() if float(v) != 0 } break except Exception as e: self.output.log("Error: " + str(e)) time.sleep(20) continue return balData def getCurrencies(self): while True: try: tickData = [k for k, v in self.conn.returnTicker().items()] break except Exception as e: self.output.log("Error: " + str(e)) time.sleep(20) continue return tickData def getNextTick(self, pair): while True: try: tickData = self.conn.returnTicker()[pair] break except Exception as e: self.output.log("Error: " + str(e)) time.sleep(20) continue return tickData def getHistoricTicks(self, pair, startTime, endTime, period): while True: try: result = self.conn.returnChartData(currencyPair=pair, start=startTime, end=endTime, period=period) break except Exception as e: self.output.log("Error: " + str(e)) time.sleep(20) continue return result def sell(self, pair, rate, amount): try: result = self.conn.sell(currencyPair=pair, rate=rate, amount=amount) except Exception as e: self.output.log("Error: " + str(e)) time.sleep(20) return result def buy(self, pair, rate, amount): try: result = self.conn.buy(currencyPair=pair, rate=rate, amount=amount) except Exception as e: self.output.log("Error: " + str(e)) time.sleep(20) return result def returnOrderTrades(self, orderId): while True: try: result = self.conn.returnOrderTrades(orderId) break except Exception as e: self.output.log("Error: " + str(e)) time.sleep(20) continue return result #============================================================================== # Returns your open orders for a given market, specified by the "currencyPair" POST parameter, # e.g. "BTC_XCP". Set "currencyPair" to "all" to return open orders for all markets. Sample output for single market: #============================================================================== def returnOpenOrders(self, currencyPair='All'): while True: try: result = self.conn.returnOpenOrders(currencyPair) break except Exception as e: self.output.log("Error: " + str(e)) time.sleep(20) continue return result #============================================================================== # Cancels an order you have placed in a given market. Required POST parameter is "orderNumber". If successful, the method will return: #============================================================================== def cancelOrder(self, orderNumber): while True: try: result = self.conn.cancelOrder(orderNumber) break except Exception as e: self.output.log("Error: " + str(e)) time.sleep(20) continue return result #============================================================================== # Cancels an order and places a new one of the same type in a single atomic transaction, meaning either both operations will succeed or both will fail. # Required POST parameters are "orderNumber" and "rate"; you may optionally specify "amount" if you wish to change # the amount of the new order. "postOnly" or "immediateOrCancel" may be specified for exchange orders, but will have no effect on margin orders. #============================================================================== def moveOrder(self, orderNumber, rate, amount): while True: try: result = self.conn.moveOrder(orderNumber, rate, amount) break except Exception as e: self.output.log("Error: " + str(e)) time.sleep(20) continue return result
class Checker: def __init__(self, ex_ev): self.ex_ev = ex_ev self.log = None self.loop = asyncio.new_event_loop() self.polo = Poloniex(POLONIEX_API_KEY, POLONIEX_API_SECRET) async def eternity(self, timeout): while not self.ex_ev.is_set(): await asyncio.sleep(timeout) async def get_balance(self, balances, user_exchange): total_btc = float(0) for coin, balance in balances.items(): total_balance = float(balance['available']) + \ float(balance['onOrders']) total_btc += float(balance['btcValue']) try: coin_balance = await get_first_by_filter(session=session, model=UserBalance, ue=user_exchange, coin=coin.lower()) except Exception as e: self.log.error(f'Error getting coin balance: {e}') send_telegram(title='ERROR', text=f'Error getting coin balance: {e}') coin_balance = None if coin_balance: data = { 'total': total_balance, 'btc_value': balance['btcValue'], 'conversions': '', 'used': balance['onOrders'], 'free': balance['available'], 'last_update': datetime.now(timezone.utc) } await update_model(session=session, model=UserBalance, pk=coin_balance.id, data=data) else: data = { 'ue_id': user_exchange.id, 'coin': coin, 'total': total_balance, 'btc_value': balance['btcValue'], 'conversions': '', 'used': balance['onOrders'], 'free': balance['available'], 'last_update': datetime.now(timezone.utc) } await create(session=session, model=UserBalance, **data) # ================================================= data = { 'total_btc': total_btc, 'total_usd': get_usd_value('btc', total_btc), 'error': '', } await update_model(session=session, model=UserExchange, pk=user_exchange.id, data=data) async def pull_exchanges_balances(self, ue_pk=None): while not self.ex_ev.is_set(): # print("=========CHECKER PULL EXCHANGE BALANCE========") try: if ue_pk is None: user_exchanges = await get_by_filter(session=session, model=UserExchange) else: user_exchanges = await get_by_filter(session=session, model=UserExchange, id=ue_pk) except Exception as e: self.log.error(f'Get Exchange Error: {e}') return if not user_exchanges: self.log.error('No Active Exchanges!') for user_exchange in user_exchanges: try: balances = self.polo.returnCompleteBalances() try: await self.get_balance(balances, user_exchange) except Exception as e: self.log.error(f'Get Balance Error: {e}') send_telegram(title='ERROR', text=f'Get Balance Error: {e}') data = {'error': '', 'is_correct': True, 'is_active': True} await update_model(session=session, model=UserExchange, pk=user_exchange.id, data=data) except Exception as e: self.log.error(f'Get Balance From Poloniex Error: {e}') send_telegram(title='ERROR', text='Incorrect apikey or secret') data = { 'error': 'Incorrect apikey or secret', 'is_correct': False, 'is_active': False } await update_model(session=session, model=UserExchange, pk=user_exchange.id, data=data) if self.ex_ev.is_set(): break try: await asyncio.wait_for(self.eternity(10), timeout=60.0) except asyncio.TimeoutError: ... if ue_pk: break if self.ex_ev.is_set(): self.log.info('=========EXIT EVENT PULL EXCHANGE BALANCE========') async def check_open(self, uo, orders_to_close): if uo in orders_to_close: self.log.info(f'Time to close for order # ' f'{uo.order_number} {uo.pair}') canceled = {} i = 3 if uo.is_fake: canceled['success'] = 1 else: while not self.ex_ev.is_set(): try: self.log.info(f'Trying to cancel order ' f'{uo.order_number} {uo.pair}') canceled = self.polo.cancelOrder(str(uo.order_number)) except Exception as e: self.log.error(f'Cancel order error: {e}') await asyncio.sleep(.5) self.polo = Poloniex(POLONIEX_API_KEY, POLONIEX_API_SECRET) if 'success' in e: canceled['success'] = 1 if canceled or i == 0: break i -= 1 if canceled['success'] == 1: data = { 'date_cancel': datetime.now(timezone.utc), 'date_updated': datetime.now(timezone.utc), 'cancel_desc': 'TTL' } try: await update_model(session=session, model=UserOrder, pk=uo.id, data=data) self.log.info(f'Order # {uo.order_number}({uo.pair}) ' f'was canceled') send_telegram(title='Order was canceled', text=f'Order # {uo.order_number}({uo.pair}) ' f'was canceled') except Exception as e: self.log.error( f'Order # {uo.order_number} update error {e}') send_telegram( title='ERROR', text=f'Order # {uo.order_number} update error {e}') else: balance_main_coin = await get_first_by_filter( session=session, model=UserBalance, ue=uo.ue, coin=uo.pair.main_coin.symbol.lower()) if balance_main_coin: try: data = { 'interim_main_coin': balance_main_coin.total, 'date_updated': datetime.now(timezone.utc), } await update_model(session=session, model=UserOrder, pk=uo.id, data=data) except Exception as e: self.log.error( f'Order # {uo.order_number} update error {e}') send_telegram( title='ERROR', text=f'Order # {uo.order_number} update error {e}') async def check_close(self, uo): current_balance_main_coin = await get_first_by_filter( session=session, model=UserBalance, ue=uo.ue, coin=uo.pair.main_coin.symbol.lower()) fact_total = 0 data = {} if current_balance_main_coin: data['main_coin_after_total'] = current_balance_main_coin.total data['main_coin_after_free'] = current_balance_main_coin.free data['main_coin_after_used'] = current_balance_main_coin.used else: data['main_coin_after_total'] = '-1' data['main_coin_after_free'] = '-1' data['main_coin_after_used'] = '-1' current_balance_second_coin = await get_first_by_filter( session=session, model=UserBalance, ue=uo.ue, coin=uo.pair.second_coin.symbol.lower()) if current_balance_second_coin: data['second_coin_after_total'] = current_balance_second_coin.total data['second_coin_after_used'] = current_balance_second_coin.free data['second_coin_after_free'] = current_balance_second_coin.used else: data['second_coin_after_total'] = '-1' data['second_coin_after_used'] = '-1' data['second_coin_after_free'] = '-1' if uo.order_type == 'buy': fact_total = float(uo.interim_main_coin) - float( current_balance_main_coin.total) if uo.order_type == 'sell': fact_total = float(current_balance_main_coin.total) - float( uo.interim_main_coin) data['fact_total'] = fact_total if fact_total != 0: fact_fee = 100.0 * float(uo.total) / float(fact_total) - 100.0 data['fact_fee'] = fact_fee if fact_fee > 0.2: data['is_ok'] = False try: data['to_close'] = False data['cancel_desc'] = 'Worked' data['date_updated'] = datetime.now(timezone.utc) data['date_cancel'] = datetime.now(timezone.utc) await update_model(session=session, model=UserOrder, pk=uo.id, data=data) self.log.warning(f'[!!!!!] Order # {uo.order_number}, ' f'Pair {uo.pair} saved [!!!!!]') send_telegram(title='!!! Order saved', text=f'Order # {uo.order_number}, ' f'Pair {uo.pair} saved') except Exception as e: self.log.error(f'Save Order Error: {e}') send_telegram(title='ERROR', text=f'Save Order Error: {e}') async def group_check_orders(self, uo, orders_to_close): try: order_status = self.polo.returnOrderStatus(uo.order_number) if order_status.get('success') == 1: await self.check_open(uo, orders_to_close) if order_status.get('success') == 0: await self.check_close(uo) except Exception as e: self.log.error(f'Error getting orders for {uo.order_number}: {e}') send_telegram( title='ERROR', text=f'Error getting orders for {uo.order_number}: {e}') async def check_orders(self): while not self.ex_ev.is_set(): # print('===========CHECKER CHECK ORDERS================') user_orders = None try: user_orders = await get_by_filter(session=session, model=UserOrder, cancel_desc='') except Exception as e: self.log.error(f'Error getting user orders to close: {e}') if user_orders: try: orders_to_close = session.query(UserOrder).filter( UserOrder.date_created <= datetime.now(timezone.utc) - timedelta(minutes=ORDER_TTL), UserOrder.cancel_desc == '', UserOrder.to_close.is_(False)).all() [ asyncio.ensure_future(self.group_check_orders( uo, orders_to_close), loop=self.loop) for uo in user_orders ] except Exception as e: self.log.error(f'Check orders error: {e}') send_telegram(title='ERROR', text=f'Check orders error: {e}') await asyncio.sleep(1) if self.ex_ev.is_set(): self.log.info('==========CHECKER EXIT EVENT check_orders=======') async def open_real_order(self, to_trade): pair = f'{to_trade.user_pair.main_coin}_' \ f'{to_trade.user_pair.second_coin}' order_id = None try: if to_trade.type == 'buy': order = self.polo.buy(currencyPair=pair, rate=to_trade.price, amount=to_trade.amount, postOnly=1) self.log.warning(f'Answer (buy): {order}') order_id = order.get('orderNumber') send_telegram(title=f'Order open: {pair}, ' f'price: {to_trade.price: .8f}, ' f'amount: {to_trade.amount}', text=f'Answer (buy): {order}') elif to_trade.type == 'sell': order = self.polo.sell(currencyPair=pair, rate=to_trade.price, amount=to_trade.amount, postOnly=1) self.log.warning(f'Answer (sell): {order}') order_id = order.get('orderNumber') send_telegram(title=f'Order open: {pair}, ' f'price: {to_trade.price: .8f}, ' f'amount: {to_trade.amount}', text=f'Answer (sell): {order}') except Exception as e: self.log.error(f'Open order {pair}, {to_trade.amount}, ' f'{to_trade.price}. Error: {e}') send_telegram( title='ERROR', text=f'Open order for: {pair}, amount: {to_trade.amount}, ' f'price: {to_trade.price: .8f}. Error: {e}') await asyncio.sleep(1) return order_id async def check_to_trade(self): while not self.ex_ev.is_set(): # print('================CHECK TO TRADE===================') try: to_trade = session.query(ToTrade).filter( ToTrade.date_updated >= datetime.now(timezone.utc) - timedelta(minutes=5)).order_by( ToTrade.date_updated).first() if not to_trade: await asyncio.sleep(5) continue self.log.info(f'Found order to trade: {to_trade}') already_in_orders = await get_by_filter( session=session, model=UserOrder, pair_id=to_trade.user_pair.pair.id, date_cancel=None) self.log.info(f'Already in orders: {already_in_orders}') if len(already_in_orders) > 0: to_delete = session.query(ToTrade).filter( ToTrade.id == to_trade.id) _ = to_delete.delete() session.commit() else: self.log.info('Trying to open order...') order_id = await self.open_real_order(to_trade) if not order_id: await asyncio.sleep(5) continue await self.pull_exchanges_balances( to_trade.user_pair.user_exchange.id) self.log.info('Balance Checked') main_coin_balance = await get_first_by_filter( session=session, model=UserBalance, ue=to_trade.user_pair.user_exchange, coin=to_trade.user_pair.pair.main_coin.symbol) second_coin_balance = await get_first_by_filter( session=session, model=UserBalance, ue=to_trade.user_pair.user_exchange, coin=to_trade.user_pair.pair.second_coin.symbol) self.log.info(f'Main coin: {main_coin_balance}, ' f'Second coin: {second_coin_balance}') data = { 'ue_id': to_trade.user_pair.user_exchange.id, 'pair_id': to_trade.user_pair.pair.id, 'order_type': to_trade.type, 'order_number': order_id, 'interim_main_coin': main_coin_balance.total, 'main_coin_before_total': main_coin_balance.total, 'main_coin_before_free': main_coin_balance.free, 'main_coin_before_used': main_coin_balance.used, 'second_coin_before_total': second_coin_balance.total, 'second_coin_before_free': second_coin_balance.free, 'second_coin_before_used': second_coin_balance.used, 'price': to_trade.price, 'amount': to_trade.amount, 'total': to_trade.price * to_trade.amount, 'date_created': datetime.now(timezone.utc), 'date_updated': datetime.now(timezone.utc), 'fee': FEE, } self.log.info('Create order') try: await create(session=session, model=UserOrder, **data) self.log.warning(f"Order {order_id} added. " f"Type {to_trade.type}, " f"Pair {to_trade.user_pair.pair}, " f"Price {to_trade.price: .8f}") to_delete = session.query(ToTrade).filter( ToTrade.id == to_trade.id) _ = to_delete.delete() session.commit() except Exception as e: self.log.exception(f'Create Order Error: {e}') send_telegram(title='ERROR', text=f'Error write order to DB: {e}') except Exception as e: self.log.error(f'check_to_trade error: {e}') await asyncio.sleep(5) if self.ex_ev.is_set(): self.log.info('============CHECK TO TRADE EXIT EVENT===========') def run(self): self.log = get_logger('checker') self.log.info('Start Checker') asyncio.set_event_loop(self.loop) tasks = [ self.pull_exchanges_balances(), self.check_orders(), self.check_to_trade() ] group = asyncio.gather(*tasks) self.loop.run_until_complete(group) if self.ex_ev.is_set(): self.log.info('=======CHECKER RUN EXIT EVENT=================') self.loop.stop() self.loop.close()
class PoloData: def __init__(self, *args, **kwargs): self._polo = Poloniex(*args, **kwargs) self.ticker_update_freq = 1 self.ticker_updated = datetime(1970, 1, 1) self._ticker = {} self.ticker = None self.ticker_active = False self._ticker_thread = None self.charts_update_freq = 60 self.charts_updated = datetime(1970, 1, 1) self.charts = {} self.charts_active = False self._charts_thread = None self.chart_path = None self._new_chart = False self.balances_update_freq = 1 self.balances_updated = datetime(1970, 1, 1) self.balances = None self.balances_active = False self._balances_thread = None self.markets = self._get_markets() def start_ticker(self, update_freq): self.ticker_update_freq = update_freq self._ticker_thread = threading.Thread(target=self._get_ticker) self._ticker_thread.setDaemon(True) self.ticker_active = True self._ticker_thread.start() def _get_ticker(self): while self.ticker_active: # print(datetime.now(), "Ticker Update") self._ticker = self._polo.returnTicker() self._populate_ticker() self.ticker_updated = datetime.now() time.sleep(self.ticker_update_freq) print("Ticker thread stopped.") def stop_ticker(self): self.ticker_active = False def _get_markets(self): ticker = self._polo.returnTicker() markets = {} for k in ticker.keys(): pc, sc = k.split("_") if pc not in markets: markets[pc] = pd.DataFrame(columns=[ 'last', 'highestBid', 'baseVolume', 'lowestAsk', 'quoteVolume', 'low24hr', 'high24hr', 'percentChange', 'isFrozen', 'id', 'favourite' ], dtype=float) if sc not in markets[pc]: markets[pc].ix[sc, "favourite"] = 0 return markets def _populate_ticker(self): self.ticker = pd.DataFrame.from_dict(self._ticker, orient='index', dtype=float).fillna(0) def start_charts(self, update_freq, chart_path): self.charts_update_freq = update_freq self.chart_path = chart_path self._charts_thread = threading.Thread(target=self._get_charts) self._charts_thread.setDaemon(True) self.charts_active = True self._charts_thread.start() def _get_charts(self): while self.charts_active: # print(datetime.now(), "Charts Update") update_time = datetime.now() + timedelta( seconds=self.charts_update_freq) for chart in self.charts: market, currency = chart.split("_") if self.charts[chart] is None: self.charts[chart] = self._load_chart( market, currency, datetime.now() - timedelta(days=90), datetime.now()) self._new_chart = False else: self.charts[chart] = self._update_chart( market, currency, self.charts[chart]) self.charts_updated = datetime.now() while datetime.now() < update_time and not self._new_chart: time.sleep(1) print("Charts thread stopped.") def stop_charts(self): self.charts_active = False def add_chart(self, market): if market not in self.charts: self.charts[market] = None self._new_chart = True def remove_chart(self, market): if market is not None: del self.charts[market] def start_balances(self, update_freq): self.balances_update_freq = update_freq self._balances_thread = threading.Thread(target=self._get_balances) self._balances_thread.setDaemon(True) self.balances_active = True self._balances_thread.start() def _get_balances(self): while self.balances_active: # print(datetime.now(), "Balances Update") self.balances = self._polo.returnCompleteBalances() self.balances_updated = datetime.now() time.sleep(self.balances_update_freq) print("Balances thread stopped.") def stop_balances(self): self.balances_active = False def _retrieve_chart_data(self, market, currency, start_date, end_date, freq=300): start_date = start_date.timestamp() end_date = end_date.timestamp() raw_chart_data = self._polo.returnChartData(market + "_" + currency, freq, start_date, end_date) chart_data = pd.DataFrame(raw_chart_data, dtype=float) chart_data["Date"] = [ datetime.fromtimestamp(d) for d in chart_data["date"] ] chart_data.set_index(["Date"], inplace=True) chart_data.drop("date", axis=1, inplace=True) chart_data = chart_data.drop_duplicates() freq_str = str(int(freq / 60)) + "Min" chart_data = chart_data.asfreq(freq_str, method='pad') return chart_data def _load_chart(self, market, currency, start_date, end_date, freq=300, force_reload=False): path = self.chart_path + market + "_" + currency + ".csv" if isfile(path) and not force_reload: # print("Loading:", market + "_" + currency, end='', flush=True) chart_data = pd.read_csv(path, parse_dates=True, index_col="Date") # print(" OK.") else: # print("Downloading:", market + "_" + currency) chart_data = self._retrieve_chart_data(market, currency, start_date, end_date, freq) chart_data.to_csv(path) return chart_data def _update_chart(self, market, currency, chart_data, freq=300): path = self.chart_path + market + "_" + currency + ".csv" next_entry = chart_data.ix[-1].name.to_pydatetime() + timedelta( minutes=int(freq / 60)) update = self._retrieve_chart_data(market, currency, next_entry, datetime.now(), freq) # print("Updating:", market + "_" + currency) if update.shape[0] > 1: chart_data = pd.concat([chart_data, update]) chart_data = chart_data.drop_duplicates() freq_str = str(int(freq / 60)) + "Min" chart_data = chart_data.asfreq(freq_str, method='pad') chart_data.to_csv(path) return chart_data def calculate_macd(self, closes, ema_fast, ema_slow, ema_signal): ema_fast = closes.ewm(ema_fast).mean() ema_slow = closes.ewm(ema_slow).mean() macd_line = ema_fast - ema_slow signal_line = macd_line.ewm(ema_signal).mean() histogram = macd_line - signal_line return macd_line, signal_line, histogram def calculate_rsi(self, closes, periods): delta = closes.diff() up_periods, down_periods = delta.copy(), delta.copy() up_periods[up_periods <= 0] = 0 down_periods[down_periods > 0] = 0 up_ema = up_periods.ewm(periods).mean() down_ema = down_periods.ewm(periods).mean().abs() rs = up_ema / down_ema rsi = 100 - (100 / (1 + rs)) return rsi def buy(self, market, price, amount): current_price = float(self.ticker.ix[market, 'lowestAsk']) orderType = 'postOnly' if float( price) < current_price else 'immediateOrCancel' result = self._polo.buy(market, price, amount, orderType=orderType) return result def sell(self, market, price, amount): current_price = float(self.ticker.ix[market, 'highestBid']) orderType = 'postOnly' if float( price) > current_price else 'immediateOrCancel' result = self._polo.sell(market, price, amount, orderType=orderType) return result
# ----- # THIS IS THE BUY BLOCK # ----- # BUY BUY # elif last_sell_min * lower['buy'] > current[ 'lowestAsk'] and k not in holdList: trade_ix += 1 if trade_ix == 1: sys.stdout.write('\n') rate = current['lowestAsk_orig'] amount_to_trade = amount['buy'] / int(rate.lstrip("0.")) try: res = p.buy(currencyPair=exchange, rate=rate, amount=amount_to_trade, orderType="fillOrKill") lib.showTrade(res, exchange, trade_type='buy', rate=rate, source='bot2', amount=amount_to_trade) print("Spread: {:.8f}".format(current['highestBid'] / current['lowestAsk'])) except Exception as ex: print(" BUY {:9} {} {}".format(exchange, rate, ex)) if trade_ix > 0: sys.stdout.write(time.strftime("%Y-%m-%d %H:%M:%S"))
class Polo(Exchange): trade = False polon = 0 def __init__(self): self.polon = Poloniex() self.polon.key = config['polo']['key'] self.polon.secret = config['polo']['secret'] def get_exchange_name(self): return "Poloniex" def short_crypto(self, _crypto, _quantity, _price): symbol = "USDT_" + _crypto if trade: order = self.polon.sell(symbol, _price, _quantity) logger.info("Poloniex short " + _crypto + ". Quantity: " + Util.float_to_str(_quantity) + ", Price: " + str(_price)) def long_crypto(self, _crypto, _quantity, _price): symbol = "USDT_" + _crypto if trade: order = self.polon.buy(symbol, _price, _quantity) logger.info("Poloniex short " + _crypto + ". Quantity: " + Util.float_to_str(_quantity) + ", Price: " + str(_price)) def get_balances(self): balances = self.polon.returnBalances() non_zero_balances = {} for key, value in balances.items(): if float(value) > 0: non_zero_balances[key] = float(value) return non_zero_balances def get_balance_usd(self): balance = float(self.polon.returnTicker()['USDT_ETH']['last']) * float( self.polon.returnBalances()['ETH']) balance = balance + float(self.polon.returnTicker( )['USDT_DASH']['last']) * float(self.polon.returnBalances()['DASH']) balance = balance + float(self.polon.returnTicker()['USDT_ZEC']['last'] ) * float(self.polon.returnBalances()['ZEC']) balance = balance + float(self.polon.returnTicker()['USDT_BCH']['last'] ) * float(self.polon.returnBalances()['BCH']) balance = balance + float(self.polon.returnTicker()['USDT_BTC']['last'] ) * float(self.polon.returnBalances()['BTC']) balance = balance + float(self.polon.returnBalances()['USDT']) return balance def get_lowest_ask(self, _crypto): asks = self.polon.returnOrderBook()['USDT_' + _crypto]['asks'] lowestAsk = 10000000 for ask in asks: ask_price = float(ask[0]) if ask_price < lowestAsk: lowestAsk = ask_price return lowestAsk def get_highest_bid(self, _crypto): bids = self.polon.returnOrderBook()['USDT_' + _crypto]['bids'] highest_bid = 0 for bid in bids: bid_price = float(bid[0]) if bid_price > highest_bid: highest_bid = bid_price return highest_bid def get_make_fee(self): return 0.0015 def get_take_fee(self): return 0.0025
class Polo(Base): """ Poloniex interface """ arg_parser = configargparse.get_argument_parser() arg_parser.add('--polo_api_key', help='polo_api_key') arg_parser.add("--polo_secret", help='polo_secret') arg_parser.add("--polo_txn_fee", help='Poloniex txn. fee') arg_parser.add("--polo_buy_order", help='Poloniex buy order type') arg_parser.add("--polo_sell_order", help='Poloniex sell order type') valid_candle_intervals = [300, 900, 1800, 7200, 14400, 86400] def __init__(self): args = self.arg_parser.parse_known_args()[0] super(Polo, self).__init__() api_key = args.polo_api_key secret = args.polo_secret self.transaction_fee = float(args.polo_txn_fee) self.polo = Poloniex(api_key, secret) self.buy_order_type = args.polo_buy_order self.sell_order_type = args.polo_sell_order self.verbosity = args.verbosity self.pair_delimiter = '_' self.tickers_cache_refresh_interval = 50 # If the ticker request is within the interval, get data from cache self.last_tickers_fetch_epoch = 0 # self.last_tickers_cache = None # Cache for storing immediate tickers def get_balances(self): """ Return available account balances (function returns ONLY currencies > 0) """ try: balances = self.polo.returnBalances() only_non_zeros = { k: float(v) for k, v in balances.items() if float(v) > 0.0 } except PoloniexError as e: print( colored('!!! Got exception (polo.get_balances): ' + str(e), 'red')) only_non_zeros = dict() return only_non_zeros def get_symbol_ticker(self, symbol, candle_size=5): """ Returns real-time ticker Data-Frame for given symbol/pair Info: Currently Poloniex returns tickers for ALL pairs. To speed the queries and avoid unnecessary API calls, this method implements temporary cache """ epoch_now = int(time.time()) if epoch_now < (self.last_tickers_fetch_epoch + self.tickers_cache_refresh_interval): # If the ticker request is within cache_fetch_interval, try to get data from cache pair_ticker = self.last_tickers_cache[symbol].copy() else: # If cache is too old fetch data from Poloniex API try: ticker = self.polo.returnTicker() pair_ticker = ticker[symbol] self.last_tickers_fetch_epoch = int(time.time()) self.last_tickers_cache = ticker.copy() except (PoloniexError | JSONDecodeError) as e: print( colored( '!!! Got exception in get_symbol_ticker. Details: ' + str(e), 'red')) pair_ticker = self.last_tickers_cache[symbol].copy() pair_ticker = dict.fromkeys(pair_ticker, None) df = pd.DataFrame.from_dict(pair_ticker, orient="index") df = df.T # We will use 'last' price as closing one df = df.rename(columns={'last': 'close', 'baseVolume': 'volume'}) df['close'] = df['close'].astype(float) df['volume'] = df['volume'].astype(float) df['pair'] = symbol df['date'] = int(datetime.datetime.utcnow().timestamp()) return df def return_ticker(self): """ Returns ticker for all currencies """ return self.polo.returnTicker() def cancel_order(self, order_number): """ Cancels order for given order number """ return self.polo.cancelOrder(order_number) def return_open_orders(self, currency_pair='all'): """ Returns your open orders """ return self.polo.returnOpenOrders(currency_pair) def get_pairs(self): """ Returns ticker pairs for all currencies """ ticker = self.polo.returnTicker() return list(ticker) def get_candles_df(self, currency_pair, epoch_start, epoch_end, period=False): """ Returns candlestick chart data in pandas dataframe """ try: data = self.get_candles(currency_pair, epoch_start, epoch_end, period) df = pd.DataFrame(data) df = df.tail(1) df['close'] = df['close'].astype(float) df['volume'] = df['volume'].astype(float) df['pair'] = currency_pair return df except (PoloniexError, JSONDecodeError) as e: print() print( colored( '!!! Got exception while retrieving polo data:' + str(e) + ', pair: ' + currency_pair, 'red')) return pd.DataFrame() def get_candles(self, currency_pair, epoch_start, epoch_end, interval_in_sec=False): """ Returns candlestick chart data """ candle_interval = self.get_valid_candle_interval(interval_in_sec) data = [] try: data = self.polo.returnChartData(currency_pair, candle_interval, epoch_start, epoch_end) except (PoloniexError, JSONDecodeError) as e: print() print( colored( '!!! Got exception while retrieving polo data:' + str(e) + ', pair: ' + currency_pair, 'red')) return data def get_valid_candle_interval(self, period_in_sec): """ Returns closest value from valid candle intervals """ if not period_in_sec: return period_in_sec if period_in_sec in self.valid_candle_intervals: return period_in_sec # Find the closest valid interval return min(self.valid_candle_intervals, key=lambda x: abs(x - period_in_sec)) def trade(self, actions, wallet, trade_mode): if trade_mode == TradeMode.backtest: return Base.trade(actions, wallet, trade_mode) else: actions = self.life_trade(actions) return actions def life_trade(self, actions): """ Places orders and returns order number !!! For now we are NOT handling postOnly type of orders !!! """ for action in actions: if action.action == TradeState.none: actions.remove(action) continue # Handle buy_sell mode wallet = self.get_balances() if action.buy_sell_mode == BuySellMode.all: action.amount = self.get_buy_sell_all_amount(wallet, action) elif action.buy_sell_mode == BuySellMode.fixed: action.amount = self.get_fixed_trade_amount(wallet, action) if self.verbosity: print( 'Processing live-action: ' + str(action.action) + ', amount:', str(action.amount) + ', pair:', action.pair + ', rate:', str(action.rate) + ', buy_sell_mode:', action.buy_sell_mode) # If we don't have enough assets, just skip/remove the action if action.amount == 0.0: print( colored( 'No assets to buy/sell, ...skipping: ' + str(action.amount) + ' ' + action.pair, 'green')) actions.remove(action) continue # ** Buy Action ** if action.action == TradeState.buy: try: print( colored( 'Setting buy order: ' + str(action.amount) + '' + action.pair, 'green')) action.order_number = self.polo.buy( action.pair, action.rate, action.amount, self.buy_order_type) except PoloniexError as e: print( colored( 'Got exception: ' + str(e) + ' Txn: buy-' + action.pair, 'red')) continue amount_unfilled = action.order_number.get('amountUnfilled') if float(amount_unfilled) == 0.0: actions.remove(action) print( colored( 'Bought: ' + str(action.amount) + '' + action.pair, 'green')) else: action.amount = amount_unfilled print( colored( 'Not filled 100% buy txn. Unfilled amount: ' + str(amount_unfilled) + '' + action.pair, 'red')) # ** Sell Action ** elif action.action == TradeState.sell: try: print( colored( 'Setting sell order: ' + str(action.amount) + '' + action.pair, 'yellow')) action.order_number = self.polo.sell( action.pair, action.rate, action.amount, self.buy_order_type) except PoloniexError as e: print( colored( 'Got exception: ' + str(e) + ' Txn: sell-' + action.pair, 'red')) continue amount_unfilled = action.order_number.get('amountUnfilled') if float(amount_unfilled) == 0.0: actions.remove(action) print( colored( 'Sold: ' + str(action.amount) + '' + action.pair, 'yellow')) else: action.amount = amount_unfilled print( colored( 'Not filled 100% sell txn. Unfilled amount: ' + str(amount_unfilled) + '' + action.pair, 'red')) return actions
class PoloniexBroker(BrokerBaseClass): """ Inherits from alchemist_lib.broker.broker.BrokerBaseClass. Website: https://poloniex.com/ Api documentation: https://poloniex.com/support/api/ Api wrapper: https://github.com/s4w3d0ff/python-poloniex Attributes: session (sqlalchemy.orm.session.Session): Database connection. polo (poloniex.Poloniex): Communication object. """ def __init__(self, api_key = None, secret_key = None): """ Costructor method. Args: api_key (str): The api key provided by Poloniex. secret_key (str): The secret key provided by Poloniex. Note: https://poloniex.com/apiKeys https://cryptocatbot.com/api-key-activation-exchanges/ """ BrokerBaseClass.__init__(self) self.polo = Poloniex(key = api_key, secret = secret_key) def get_best_rate(self, asset, amount, field): """ Poloniex doesn't allow to place market orders so we need to get the best bid/ask price for every order. Args: asset (alchemist_lib.database.asset.Asset): The asset we want to exchange for BTC. amount (decimal.Decimal): The amount we want to exchange. field (str): Must be "ask" or "bid". Return: price (decimal.Decimal): The best bid/ask, executing an order at this price is like execute a market order. If the book is too thin the return value is 0. """ amount = abs(amount) pair = "BTC_{}".format(asset.ticker) book = self.polo.returnOrderBook(currencyPair = pair, depth = 20) values = book["{}s".format(field)] orders_sum = Decimal(0) for book_item in values: orders_sum += Decimal(book_item[1]) if orders_sum > amount: return Decimal(book_item[0]) return Decimal(0) def place_order(self, asset, amount, order_type): """ Places an order for a specific asset on Poloniex. Args: asset (alchemist_lib.database.asset.Asset): The asset we want exchange for BTC. amount (decimal.Decimal): The amount we want to exchange. order_type (str): Type of order. Return: order_id (int): The order identifier, if some error occurs returns -1. """ pair = "BTC_{}".format(asset.ticker) if amount > 0: field = "ask" operation = "buy" else: field = "bid" operation = "sell" if order_type == "MKT": rate = self.get_best_rate(asset = asset, amount = abs(amount), field = field) else: logging.critical("Unknown order type. NotImplemented raised.") raise NotImplemented("Unknown order type. NotImplemented raised.") logging.debug("Order: Pair: {}. Amount: {}. Operation: {}".format(pair, amount, operation)) try: if operation == "buy": order_dict = self.polo.buy(currencyPair = pair, rate = rate, amount = amount) else: order_dict = self.polo.sell(currencyPair = pair, rate = rate, amount = abs(amount)) order_id = int(order_dict["orderNumber"]) order = ExecutedOrder(order_id = order_id, order_datetime = dt.datetime.utcnow(), ticker = asset.ticker, instrument_id = asset.instrument_id, amount = amount, operation = operation, order_type = order_type, broker_name = "poloniex", exchange_name = "poloniex" ) logging.info("{} order placed for {}. Amount: {}. Order id: {}.".format(operation.upper(), asset.ticker, amount, order_id)) print("{} order placed for {}. Amount: {}. Order id: {}.".format(operation.upper(), asset.ticker, amount, order_id)) self.session.add(order) self.session.commit() except PoloniexError: logging.debug("Order failed for {}.".format(asset.ticker)) order_id = -1 return order_id