示例#1
0
class BotTrade(object):
    def __init__(self,direction,amount,rate,total,date,stopLoss=0, takeProfit=0, backtest=True, live=False):
        global orderNb
        self.amount = amount
        self.backTest = backtest
        self.date = date
        self.direction = direction
        self.exitDate = 0.0
        self.exitRate = 0.0
        self.fee = float(shared.exchange['fee'])
        self.filledOn = ""
        self.live = live
        self.orderNumber = orderNb
        self.output = BotLog()
        self.rate = rate
        self.status = "OPEN"
        self.stopLoss = stopLoss
        self.takeProfit = takeProfit
        self.total = total

        # API
        self.api = BotApi()

        orderSuccess = True
        if self.direction == "BUY":
            if not self.backTest and self.live:
                try:
                    order = self.api.exchange.createLimitBuyOrder(shared.exchange['pair'], amount, rate)
                    self.orderNumber = order['id']
                except Exception as e:
                    self.output.fail(str(e))
                    orderSuccess = False
                    self.output.fail("Buy order failed")
            elif self.total < 0.00001:
                orderSuccess = False
                self.output.fail("Not enough funds to place Buy Order")
            if orderSuccess:
                shared.exchange['nbMarket'] -= self.total
                self.amount -= self.amount*self.fee
                self.output.info(str(time.ctime(date)) + " - Order "+str(self.orderNumber)+": Buy "+str(self.amount)+' '+shared.exchange['asset']+' ('+str(self.fee*100)+'% fees) at '+str(self.rate)+' for '+str(self.total)+' '+shared.exchange['market']+' - stopLoss: '+str(self.stopLoss)+' - takeProfit: '+str(self.takeProfit))

        elif self.direction == "SELL":
            if not self.backTest and self.live:
                try:
                    order = self.api.exchange.createLimitSellOrder(shared.exchange['pair'], amount, rate)
                    self.orderNumber = order['id']
                except Exception as e:
                    print(e)
                    orderSuccess = False
                    self.output.warning("Sell order failed")
            elif self.total < 0.00001:
                orderSuccess = False
                self.output.fail("Not enough funds to place Sell Order")
            if orderSuccess:
                shared.exchange['nbAsset'] -= self.amount
                self.total -= self.total*self.fee
                self.output.info(str(time.ctime(date)) + " - Order "+str(self.orderNumber)+": Sell "+str(self.amount)+' '+shared.exchange['asset']+' at '+str(self.rate)+' for '+str(self.total)+' ('+str(self.fee*100)+'% fees) '+shared.exchange['market']+' - stopLoss: '+str(self.stopLoss)+' - takeProfit: '+str(self.takeProfit))


        orderNb+=1
        if not orderSuccess:
            self.status = 'FAILED'

    def __setitem__(self, key, value):
          setattr(self, key, value)

    def __getitem__(self, key):
          return getattr(self, key)

    def toDict(self):
        return {
            'date': self.date,
            'direction': self.direction,
            'amount': self.amount,
            'rate': self.rate,
            'total': self.total,
            'stopLoss': self.stopLoss,
            'takeProfit': self.takeProfit,
            'exitRate': self.exitRate,
            'filledOn': self.filledOn,
            'exitDate': self.exitDate,
            'orderNumber': self.orderNumber
        }

    def tick(self, candlestick, date):
        if not self.backTest and self.live:
            date = float(time.time())
            # TODO: implement not backtest
            pass
        if not self.filledOn:
            if (self.direction == 'BUY' and candlestick.high > self.rate) or (self.direction == 'SELL' and candlestick.low < self.rate):
                self.filledOn = date
                if self.direction == 'BUY':
                    shared.exchange['nbAsset'] += self.amount
                elif self.direction == 'SELL':
                    shared.exchange['nbMarket'] += self.total
                if not self.stopLoss and not self.takeProfit:
                    self.status = 'CLOSED'
                else:
                    if self.direction =='BUY':
                        shared.exchange['coinsInOrder'] += self.amount
                    elif self.direction =='SELL':
                        shared.exchange['marketInOrder'] += self.total
                self.output.info(str(time.ctime(date)) + " - Order "+str(self.orderNumber)+" filled")

        if self.stopLoss and self.filledOn:
            # TODO: implement live
            if self.direction == 'BUY' and candlestick.low < self.stopLoss:
                self.total -= self.total*self.fee
                shared.exchange['nbAsset'] -= self.amount
                shared.exchange['coinsInOrder'] -= self.amount
                self.output.warning(str(time.ctime(date)) + " - Order "+str(self.orderNumber)+": Stop Loss - Sell "+str(self.amount)+' '+shared.exchange['asset']+' at '+str(self.stopLoss)+' for '+str(self.total)+' '+shared.exchange['market']+' ('+str(self.fee*100)+'% fees)')
                self.close(self.stopLoss, date)
                return
            elif self.direction == 'SELL' and candlestick.high > self.stopLoss:
                self.amount -= self.amount*self.fee
                shared.exchange['nbMarket'] -= self.total
                shared.exchange['marketInOrder'] -= self.total
                self.output.warning(str(time.ctime(date)) + " - Order "+str(self.orderNumber)+": Stop Loss - Buy "+str(self.amount)+' '+shared.exchange['asset']+' ('+str(self.fee*100)+'% fees) at '+str(self.stopLoss)+' for '+str(self.total)+' '+shared.exchange['market'])
                self.close(self.stopLoss, date)
                return
        if self.takeProfit and self.filledOn:
            if self.direction == 'BUY' and candlestick.high > self.takeProfit:
                self.total -= self.total*self.fee
                shared.exchange['nbAsset'] -= self.amount
                shared.exchange['coinsInOrder'] -= self.amount
                self.output.success(str(time.ctime(date)) + " - Order "+str(self.orderNumber)+": Take Profit - Sell "+str(self.amount)+' '+shared.exchange['asset']+' at '+str(self.stopLoss)+' for '+str(self.total)+' '+shared.exchange['market']+' ('+str(self.fee*100)+'% fees)')
                self.close(self.takeProfit, date)
                return
            elif self.direction == 'SELL' and candlestick.low < self.takeProfit:
                self.amount -= self.amount*self.fee
                shared.exchange['nbMarket'] -= self.total
                shared.exchange['marketInOrder'] -= self.total
                self.output.success(str(time.ctime(date)) + " - Order "+str(self.orderNumber)+": Take Profit - Buy "+str(self.amount)+' '+shared.exchange['asset']+' ('+str(self.fee*100)+'% fees) at '+str(self.stopLoss)+' for '+str(self.total)+' '+shared.exchange['market'])
                self.close(self.takeProfit, date)
                return

    def close(self, currentPrice, date=0.0):
        if not self.backTest and self.live:
            date = float(time.time())
            # TODO: implement not backtest
            pass
        self.status = "CLOSED"
        self.exitRate = currentPrice
        self.exitDate =  date
        if self.direction == 'BUY':
            shared.exchange['nbMarket'] += self.total
        elif self.direction == 'SELL':
            shared.exchange['nbAsset'] += self.amount
        self.output.info(str(time.ctime(date)) + " - Order "+str(self.orderNumber)+" Closed")
        self.showTrade()

    def showTrade(self):
        tradeStatus = "Order #"+str(self.orderNumber)+" - Entry Price: "+str(self.rate)+" Status: "+str(self.status)+" Exit Price: "+str(self.exitRate)

        if (self.status == "CLOSED"):
            if (self.direction == 'BUY' and self.exitRate > self.rate) or (self.direction == 'SELL' and self.exitRate < self.rate):
                tradeStatus = tradeStatus + " Profit: \033[92m"
            else:
                tradeStatus = tradeStatus + " Loss: \033[91m"
            if self.direction == 'BUY':
                tradeStatus = tradeStatus+str((self.exitRate - self.rate)/self.total)+str(shared.exchange['market'])+"\033[0m"
            else:
                tradeStatus = tradeStatus+str((self.rate - self.exitRate)/self.exitRate*self.amount)+str(shared.exchange['asset'])+"\033[0m"

        self.output.log(tradeStatus)

    def updateStop(self, newStop):
        oldStop = self.stopLoss
        self.stopLoss = float(newStop);
        self.output.log("Trade stop moved from "+str(oldStop)+" to "+str(newStop))
示例#2
0
class BotApi(object):
    def __init__(self):
        self.exchange = shared.exchange['name']
        self.key = shared.api['key']
        self.secret = shared.api['secret']
        self.output = BotLog()

        if shared.exchange['name'] == 'poloniex':
            self.api = poloniex.Poloniex(self.key, self.secret)
        elif shared.exchange['name'] == 'kraken':
            self.api = krakenex.API(self.key, self.secret)

    def returnChartData(self, pair, period, start, end):
        data = []
        if self.exchange == 'poloniex':
            if (period not in [300, 900, 1800, 7200, 14400, 86400]):
                self.output.fail(
                    'Poloniex requires periods in seconds: 300,900,1800,7200,14400, or 86400'
                )
                sys.exit(2)
            poloData = self.api.returnChartData(pair,
                                                period=int(period),
                                                start=int(start),
                                                end=int(end))
            #TODO: check for error
            for datum in poloData:
                if (datum['open'] and datum['close'] and datum['high']
                        and datum['low'] and datum['date'] and datum['volume']
                        and datum['weightedAverage']):
                    data.append(
                        BotCandlestick(period, float(datum['open']),
                                       float(datum['close']),
                                       float(datum['high']),
                                       float(datum['low']),
                                       float(datum['weightedAverage']),
                                       float(datum['volume']),
                                       float(datum['date'])))

        elif self.exchange == 'kraken':
            if (period not in [1, 5, 15, 30, 60, 240, 1440, 10080, 21600]):
                self.output.fail(
                    'Kraken requires periods in minutes: 1, 5, 15, 30, 60, 240, 1440, 10080, 21600'
                )
                sys.exit(2)
            krakenData = self.api.query_public('OHLC',
                                               data={
                                                   'pair': pair,
                                                   'since': start,
                                                   'interval': period
                                               })
            # check for error
            if len(krakenData['error']) > 0:
                for e in krakenData['error']:
                    self.output.fail(e)
                sys.exit()
            for datum in krakenData['result'][pair]:
                data.append(
                    BotCandlestick(period, float(datum[1]), float(datum[4]),
                                   float(datum[2]), float(datum[3]),
                                   float(datum[5]), float(datum[0])))

        else:
            self.output.fail("Not a valid exchange")
            sys.exit(2)
        return data

    def returnTicker(self, pair):
        ticker = {}
        if self.exchange == 'poloniex':
            ticker = self.api.returnTicker()[pair]
            #TODO: check for error
        elif self.exchange == 'kraken':
            data = self.api.query_public('Ticker', data={'pair': pair})
            #TODO: check for error
            data = data['result'][pair]
            ticker = {
                'last': float(data['c'][0]),
                'lowestAsk': float(data['a'][0]),
                'highestBid': float(data['b'][0]),
                'high24hr': float(data['h'][1]),
                'low24hr': float(data['l'][1])
            }
        else:
            self.output.fail("Not a valid exchange")
            sys.exit(2)
        print(ticker)
        return ticker

    def returnOpenOrders(self, pair):
        orders = []
        if self.exchange == 'poloniex':
            data = self.api.returnOpenOrders(pair)
            #TODO: check for error
            orders = data
        elif self.exchange == 'kraken':
            data = self.api.query_private('OpenOrders')
            #TODO: check for error
            orders = data['result']
            #TODO: This is a bit tricky for now, need to figure out how to deal with pair names (XXDGXXBT is "the same" as XDGXBT for example)
        else:
            self.output.fail("Not a valid exchange")
            sys.exit(2)
        return orders

    def returnBalances(self):
        balances = {}
        if self.exchange == 'poloniex':
            try:
                data = self.api.returnBalances()
                balances = data
            except Exception as e:
                print(e)
                return False
        elif self.exchange == 'kraken':
            data = self.api.query_private('Balance')
            #TODO: check for error
            balances = data['result']
        else:
            self.output.fail("Not a valid exchange")
            sys.exit(2)
        return balances

    def marketBuy(self, pair, rate, amout):
        order = {}
        if self.exchange == 'poloniex':
            try:
                #no market buy on poloniex, buying at 110% of the price "hacks" this
                data = self.api.buy(shared.exchange['pair'],
                                    rate='{0:.10f}'.format(rate * 1.1),
                                    amount=amount,
                                    orderType="fillOrKill")
                order = data
            except Exception as e:
                self.output.fail(e)
                return False
        elif self.exchange == 'kraken':
            data = self.api.query_private('AddOrder',
                                          data={
                                              'ordertype': 'market',
                                              'pair': pair,
                                              'type': 'buy',
                                              'volume': str(amount)
                                          })
            if len(data['error']) > 0:
                for e in data['error']:
                    self.output.fail(e)
                return False
            order = {'orderNumber': data['result']['txid'][0]}
        else:
            self.output.fail("Not a valid exchange")
            sys.exit(2)
        return order

    def limitBuy(self, pair, rate, amount):
        order = {}
        if self.exchange == 'poloniex':
            try:
                data = self.api.buy(shared.exchange['pair'],
                                    rate='{0:.10f}'.format(rate),
                                    amount=amount)
                order = data
            except Exception as e:
                print(e)
                return False
        elif self.exchange == 'kraken':
            data = self.api.query_private('AddOrder',
                                          data={
                                              'ordertype': 'limit',
                                              'pair': pair,
                                              'type': 'buy',
                                              'price': '{0:.10f}'.format(rate),
                                              'volume': str(amount)
                                          })
            print(data)
            if len(data['error']) > 0:
                for e in data['error']:
                    self.output.fail(e)
                return False
            order = {'orderNumber': data['result']['txid'][0]}
        else:
            self.output.fail("Not a valid exchange")
            sys.exit(2)
        return order

    def marketSell(self, pair, rate, amount):
        order = {}
        if self.exchange == 'poloniex':
            try:
                #no market sell on poloniex, selling at 90% of the price "hacks" this
                data = self.api.sell(shared.exchange['pair'],
                                     rate='{0:.10f}'.format(rate * 0.9),
                                     amount=amount,
                                     orderType="fillOrKill")
                order = data
            except Exception as e:
                print(e)
                return False
        elif self.exchange == 'kraken':
            data = self.api.query_private('AddOrder',
                                          data={
                                              'ordertype': 'market',
                                              'pair': pair,
                                              'type': 'sell',
                                              'volume': str(amount)
                                          })
            if len(data['error']) > 0:
                for e in data['error']:
                    self.output.fail(e)
                return False
            order = {'orderNumber': data['result']['txid'][0]}
        else:
            self.output.fail("Not a valid exchange")
            sys.exit(2)
        return order

    def limitSell(self, pair, rate, amount):
        order = {}
        if self.exchange == 'poloniex':
            try:
                data = self.api.sell(shared.exchange['pair'],
                                     rate='{0:.10f}'.format(rate),
                                     amount=amount)
                order = data
            except Exception as e:
                print(e)
                return False
        elif self.exchange == 'kraken':
            data = self.api.query_private('AddOrder',
                                          data={
                                              'ordertype': 'limit',
                                              'pair': pair,
                                              'type': 'sell',
                                              'price': '{0:.10f}'.format(rate),
                                              'volume': str(amount)
                                          })
            if len(data['error']) > 0:
                for e in data['error']:
                    self.output.fail(e)
                return False
            order = {'orderNumber': data['result']['txid'][0]}
        else:
            self.output.fail("Not a valid exchange")
            sys.exit(2)
        return order

    def cancelOrder(self, orderID):
        orderCanceled = True
        if self.exchange == 'poloniex':
            try:
                data = self.api.cancelOrder(orderID)
                if data['success'] == 0:
                    return False
            except Exception as e:
                print(e)
                return False
        elif self.exchange == 'kraken':
            data = self.api.query_private('CancelOrder',
                                          data={'txid': orderID})
            if len(data['error']) > 0:
                for e in data['error']:
                    self.output.fail(e)
                return False
        else:
            self.output.fail("Not a valid exchange")
            sys.exit(2)
        return orderCanceled