class StrategyLib(object): def __init__(self): self.indicators = BotIndicators() def MACrossover(self, lowMA, highMA): fifteenDayMA = self.indicators.movingAverage(self.prices,self.lowMA) fiftyDayMA = self.indicators.movingAverage(self.prices,self.highMA) # print(fifteenDayMA, fiftyDayMA) if (len(self.openTrades) < self.numSimulTrades): if (fifteenDayMA > fiftyDayMA * self.mamultfactor ): amountToBuy = self.balance * 0.2 / self.currentPrice fee = amountToBuy * self.currentPrice * self.fee stoploss = self.currentPrice * 0.1 self.currentId += 1 self.balance -= (amountToBuy * self.currentPrice + fee) self.trades.append(BotTrade(self.functions, self.currentDate, amountToBuy, self.currentPrice,self.currentId,stopLoss=stoploss, fee=fee)) for trade in self.openTrades: if (fifteenDayMA < fiftyDayMA / self.mamultfactor): self.balance += trade.volume * self.currentPrice trade.close(self.currentDate, self.currentPrice, "MA Crossover") elif (trade.stopLoss): if (trade.entryPrice - self.currentPrice > trade.stopLoss): trade.close(self.currentDate, self.currentPrice, "Stoploss") self.balance += trade.volume * self.currentPrice
def __init__(self): #connect; read and write to db self.TradeDatabase = TradeDatabase() self.TradeDatabase.connect() #amount to trade (capital): self.amountInUSD = 300 #prices information self.prices = [] self.currentPrice = "" #graph and indicators self.output = BotLog() self.indicators = BotIndicators() #self.graphdataPoints = [] self.dataDate = "" self.SMA = "" self.CResistance = 0.0 self.EMA9 = [] self.MACD = [] #trade details self.tradePlaced = [] self.typeOfTrade = [] self.cumulatedProfits = 0.0 #wins and loses self.numofwins = 0 self.numofloses = 0
def __init__(self, backtest=True, live=False): self.output = BotLog() self.pair = shared.exchange['pair'] self.coinsInOrder = shared.exchange['coinsInOrder'] self.marketInOrder = shared.exchange['marketInOrder'] self.trades = [] self.currentPrice = "" self.currentClose = "" self.live = live self.lowestAsk = 0.00 self.highestBid = 0.00 self.simultaneousTrades = 1 self.tradeMultiplier = 1 self.ticker = {} self.backTest = backtest self.indicators = BotIndicators() self.candlesticks = [] self.movingAverages = [] self.movingAveragePeriod = 3 self.trueRanges = [] self.averageTrueRanges = [] self.openOrders = [] # API self.api = BotApi()
def __init__(self, pair, period): BotStrategy.__init__(self, pair, period) self.highs = [] self.lows = [] self.closes = [] self.current_price = "" self.pair = pair self.stop_loss_percent = 2.5 self.indicators = BotIndicators() self.macd_fast = 12 self.macd_slow = 26 self.macd_signal = 9 self.macd_period = self.macd_signal + self.macd_slow # Number of data points needed to use MACD indicator self.hist_period = max(self.macd_fast, self.macd_slow, self.macd_signal, self.macd_period) self.max_hist = 0 # Used to keep track of the maximum value of the MACD histogram used on this trade. # Prime the bot with past data. self.past_typical_prices, self.past_opens, self.past_closes, self.past_highs, self.past_lows = self.get_past_prices( self.period, self.hist_period) if self.past_typical_prices and self.past_closes and self.past_highs and self.past_lows and self.past_opens: self.prices = self.past_typical_prices self.closes = self.past_closes self.highs = self.past_highs self.lows = self.past_lows
def __init__(self, backtest=True, forwardtest=True): self.output = BotLog() self.pair = shared.exchange['pair'] self.coinsInOrder = shared.exchange['coinsInOrder'] self.marketInOrder = shared.exchange['marketInOrder'] self.trades = [] self.currentPrice = "" self.currentClose = "" self.lowestAsk = 0.00 self.highestBid = 0.00 self.simultaneousTrades = 4 self.tradeMultiplier = 0.1 self.ticker = {} self.backTest = backtest self.forwardTest = forwardtest self.indicators = BotIndicators() self.candlesticks = [] self.movingAverages = [] self.movingAveragePeriod = shared.strategy['movingAverageLength'] self.trueRanges = [] self.averageTrueRanges = [] # portfolio self.openOrders = [] #api self.api = BotApi()
def __init__(self): self.output = BotLog() self.prices = [] self.trades = [] self.currentPrice = "" self.numSimulTrades = 1 self.indicators = BotIndicators()
def __init__(self): self.vars = botVariables() self.investement = self.vars.initialInvestment self.makeFee = self.vars.makeFee self.takeFee = self.vars.takeFee self.output = BotLog() self.prices = [] self.closes = [] # Needed for Momentum Indicator self.trades = [] self.numOfTrades = 0 self.currentPrice = "" self.currentTime = "" self.currentClose = "" self.numSimulTrades = 1 self.indicators = BotIndicators() self.absMargin = 0 self.relMargin = 0 #these are the values of the indicators qat each endTime self.SMA1 = 0 self.SMA2 = 0 self.EMA1 = 0 self.EMA2 = 0 self.RSI = 0 self.BollUp = 0 self.BollDown = 0
def __init__(self): self.output = BotLog() self.prices = [] self.closes = [] # Needed for Momentum Indicator self.trades = [] self.currentPrice = "" self.currentClose = "" self.numSimulTrades = 1 self.indicators = BotIndicators()
class BotStrategy(object): def __init__(self): self.output = BotLog() self.prices = [] self.closes = [] # Needed for Momentum Indicator self.trades = [] self.currentPrice = "" self.currentClose = "" self.numSimulTrades = 1 self.indicators = BotIndicators() def tick(self, candlestick): print candlestick.priceAverage self.currentPrice = float(candlestick.priceAverage) self.prices.append(self.currentPrice) #self.currentClose = float(candlestick['close']) #self.closes.append(self.currentClose) self.output.log("Price: " + str(candlestick.priceAverage) + "\tMoving Average: " + str(self.indicators.movingAverage(self.prices, 15))) self.evaluatePositions() self.updateOpenTrades() self.showPositions() def evaluatePositions(self): openTrades = [] for trade in self.trades: if (trade.status == "OPEN"): openTrades.append(trade) if (len(openTrades) < self.numSimulTrades): if (self.currentPrice < self.indicators.movingAverage( self.prices, 15)): self.trades.append(BotTrade(self.currentPrice, stopLoss=.0001)) for trade in openTrades: if (self.currentPrice > self.indicators.movingAverage( self.prices, 15)): trade.close(self.currentPrice) def updateOpenTrades(self): for trade in self.trades: if (trade.status == "OPEN"): trade.tick(self.currentPrice) def showPositions(self): for trade in self.trades: trade.showTrade()
def __init__(self): self.output = BotLog() self.prices = [] self.closes = [] # Needed for Momentum Indicator self.trades = [] self.currentPrice = "" self.currentClose = "" self.numSimulTrades = 10 self.indicators = BotIndicators() self.totalProfit = 0.0 self.minRSI = 30 self.maxRSI = 70 self.minMomentum = 103 self.maxMomentum = 97
def __init__(self): self.output = BotLog() self.prices = [] self.currentPrice = "" self.indicators = BotIndicators() self.GRC_bal = False self.BTC_bal = False self.Total_bal = False self.can_buy = False self.can_sell = False self.trade_amount = .00059 # BTC self.to_buy = False self.to_sell = False self.pair = 'BTC_GRC' self.order_num = False self.orders = [] self.high_bid_price = False self.low_ask_price = False self.low_ask_amount = False self.high_bid_amount = False self.price_to_buy = False self.price_to_sell = False self.openTrades = [] self.open_Bids = [] self.open_Asks = [] self.orders = [] self.last_sell_price = False self.last_buy_price = False self.open_sell_flag = False self.open_buy_flag = False self.raw_spread = 0 self.mod_spread = 0 self.place_orders_flag = True
def __init__(self, name, mode, pair, numTrades, startUSD, startUnit, tradeAmount, stopLoss, targetPrice, backtest, output): self.output = output self.name = name self.mode = mode self.pair = pair self.numTrades = numTrades self.startUSD = startUSD self.startUnit = startUnit self.tradeAmount = tradeAmount self.stopLoss = stopLoss self.targetPrice = targetPrice self.backtest = backtest self.prices = [] self.closes = [] self.trades = [] self.upperBBand = [] self.lowerBBand = [] self.midBBand = [] self.MACDDiff = [] self.MACDSignal = [] self.rsi = [] self.date = "" self.action = [] self.dataPoints = [] self.balancePoints = [] self.MACDPoints = [] self.rsiPoints = [] self.currentPrice = "" self.currentClose = "" self.holdingsUSD = startUSD self.holdingsUnits = startUnit self.balance = startUSD self.balanceNoTrade = startUSD self.profit = 0 self.fees = 0 self.indicators = BotIndicators() self.priceAverage = 0
def __init__(self): self.output = BotLog() self.prices = [] self.opens = [] self.closes = [] #for Momentum self.trades = [] self.MACD_History = [] # MACD History self.MACD_Signal_History = [] # MACD Signal History self.currentPrice = None self.numSimulTrades = 1 self.takeProfit = 0.0001 self.stopLoss = 1 self.indicators = BotIndicators() self.trendPeriod = 3 # ETH : 3 # DASH : 3 self.minVolume = 1.2 # ETH : 1.2 # DASH : 1
def __init__(self): self.result = 0 self.output = BotLog() self.prices = [] self.positions = [] self.low = [] self.high = [] self.current_price = "" self.indicators = BotIndicators() self.num_simulpositions = 1
def __init__(self, pair, period): BotStrategy.__init__(self, pair, period) self.highs = [] self.lows = [] self.closes = [] self.moving_avgs = [] # Keep track of MAs self.ma_slopes = [] # Keep track of Slope of MAs self.slope_difference = [] self.support_levels = [] self.resistance_levels = [] self.current_price = "" self.pair = pair self.stoch_stop_loss = 2.5 self.cool_down_period = 0 self.indicators = BotIndicators() # Lookback window sizes self.stoch_period = 5 # n previous candles for stochastic indicator self.ma_period_fast = 9 # n previous candles for fast moving average indicator self.ma_slope_lookback = 9 # n previous values for calculating slope of MA. self.ma_period_slow = 26 # n previous candles for slow moving average indicator self.sr_period = 700 # n previous candles for support/resistance self.sr_n = 25 # n-value for S/R indicator. Controls Smoothing. self.hist_period = max(self.stoch_period, self.sr_period, self.ma_period_fast, self.ma_period_slow) self.over_bought = 80 self.over_sold = 20 self.mid_line = 50 self.stoch_ready_to_buy = False # Prime the bot with past data. self.past_typical_prices, self.past_opens, self.past_closes, self.past_highs, self.past_lows = self.get_past_prices(self.period, self.hist_period) if self.past_typical_prices and self.past_closes and self.past_highs and self.past_lows and self.past_opens: self.prices = self.past_typical_prices self.closes = self.past_closes self.highs = self.past_highs self.lows = self.past_lows for i in reversed(range(self.ma_period_fast)): sub_slice = self.prices[:-i - 1] _ma = self.indicators.moving_average(sub_slice[-self.ma_period_fast:], self.ma_period_fast) self.moving_avgs.append(_ma)
def __init__(self, period, log, api, checker, stopLoss=0, startBalance=100): self.highs = {} self.lows = {} self.closes = {} self.dates = [] self.volumes = {} self.MFIs = {} self.MACD = {} self.MovingAverage = {} self.output = log self.api = api self.fee = {} self.fee['BTC'] = self.api.getFee('ETHBTC') self.fee['BNB'] = self.api.getFee('BNBBTC') self.fee['USDT'] = self.api.getFee('BTCUSDT') self.pairs = checker.pairs self.coins = checker.coins self.indicators = BotIndicators(period, self.pairs) # unused, but find application self.stopLoss = stopLoss # self.balance = {i: 0 for i in checker.coins} # disable (it has to be in the tick method below) # setting start values for USDT # self.balance['USDT'] = startBalance self.oldValue = 0 self.ovrValue = 0 self.MFIs = {} self.MovingAverage = {} self.MFI = None self.period = period self.counter = 0
def __init__(self, period, startTime, endTime, backTest=True): self.exchange = shared.exchange['name'] self.pair = shared.exchange['pair'] self.period = int(period) self.startTime = int(startTime) self.endTime = int(endTime) self.backTest = bool(backTest) self.output = BotLog() self.tempCandle = None self.indicators = BotIndicators() self.data = [] self.api = BotApi() if backTest: self.data = self.api.returnChartData(self.pair, period=int(self.period), start=self.startTime, end=self.endTime)
def __init__(self, pair): if (not config.CONFIG["VERBOSE"]): print("Calculating indicators") self.pair = pair self.output = BotLog() self.path = config.CONFIG['PATH'] self.prices = [] self.closes = [] self.trades = [] self.movingAVG = [] self.momentum = [] self.RSI = [] self.currentPrice = "" self.currentClose = "" self.numSimulTrades = 1 self.indicators = BotIndicators() self.graph_data = { "date": [], "movingAverage": [], "momentum": [], "RSI": [] }
def __init__(self, pair, period): BotStrategy.__init__(self, pair, period) self.highs = [] self.lows = [] self.closes = [] self.currentPrice = "" self.pair = pair self.stoch_stop_loss = 100.0 self.indicators = BotIndicators() self.stoch_period = 14 # n previous trading sessions (candles) self.over_bought = 80 self.over_sold = 20 self.past_avg_prices, self.past_opens, self.past_closes, self.past_highs, self.past_lows = self.get_past_prices( self.period, self.stoch_period) if self.past_avg_prices and self.past_closes and self.past_highs and self.past_lows and self.past_opens: self.prices = self.past_avg_prices self.closes = self.past_closes self.highs = self.past_highs self.lows = self.past_lows
def __init__(self, short_mode=False, backtest=True): self.capital = 1000 self.output = BotLog() self.prices = [] self.trades = [] self.low = [] self.high = [] self.currentPrice = "" self.numSimulTrades = 100000000 # inutile si seulement signaux ! self.indicators = BotIndicators() # self.stopLoss = 2 * self.indicators.average_true_range(self.high,self.low,self.prices) self.stopLoss = 0 # inutile pour signaux self.short_mode = short_mode self.backtest = backtest
def __init__(self): self.output = BotLog() self.prices = [] self.closes = [] # Needed for Momentum Indicator self.trades = [] self.currentPrice = "" self.numSimulTrades = 1 self.indicators = BotIndicators() self.type_trade = False self.GRC_bal = False self.BTC_bal = False self.Total_bal = False self.can_buy = False self.to_buy = False self.to_sell = False self.pair = 'BTC_GRC' self.order_num = False self.balance = False self.sell_price_last = False self.buy_price_last = False self.loss_break = 0 self.orders = [] self.high_bid_price = False self.low_ask_price = False self.low_ask_amount = False self.high_bid_amount = False self.price_to_buy = False self.price_to_sell = False self.short_MA_period = 12 self.long_MA_period = 26 self.signal_MA_period = 9 self.winsound = winsound self.frequency = 2500 # Set Frequency To 2500 Hertz self.duration = 1000 # Set Duration To 1000 ms == 1 second self.short_EMA_list = [] self.long_EMA_list = [] self.MACD_list = [] self.MACD_sig_list = [] self.MACD_hist_list = [] self.openTrades = []
class BotStrategy(object): def __init__(self, period, log, api, checker, stopLoss=0, startBalance=100): self.highs = {} self.lows = {} self.closes = {} self.dates = [] self.volumes = {} self.MFIs = {} self.MACD = {} self.MovingAverage = {} self.output = log self.api = api self.fee = {} self.fee['BTC'] = self.api.getFee('ETHBTC') self.fee['BNB'] = self.api.getFee('BNBBTC') self.fee['USDT'] = self.api.getFee('BTCUSDT') self.pairs = checker.pairs self.coins = checker.coins self.indicators = BotIndicators(period, self.pairs) # unused, but find application self.stopLoss = stopLoss # self.balance = {i: 0 for i in checker.coins} # disable (it has to be in the tick method below) # setting start values for USDT # self.balance['USDT'] = startBalance self.oldValue = 0 self.ovrValue = 0 self.MFIs = {} self.MovingAverage = {} self.MFI = None self.period = period self.counter = 0 def tick(self, history, timestamp, initialize_live): # are all dictionaries, with timestamp as 1st level key and pair becomes 2nd level key (nested dictionary) self.highs[timestamp] = {} self.lows[timestamp] = {} self.closes[timestamp] = {} self.dates.append(timestamp) self.volumes[timestamp] = {} self.MFIs[timestamp] = {} self.MovingAverage[timestamp] = {} self.MACD[timestamp] = {} for pair in self.pairs: self.highs[timestamp][pair] = history[timestamp][pair]['high'] self.lows[timestamp][pair] = history[timestamp][pair]['low'] self.closes[timestamp][pair] = history[timestamp][pair]['close'] self.volumes[timestamp][pair] = history[timestamp][pair]['volume'] self.MovingAverage[timestamp][ pair] = self.indicators.movingAverage(closes=self.closes, dates=self.dates, pair=pair, length=5) self.MFI = self.indicators.moneyFlowIndex(period=self.period, dates=self.dates, highs=self.highs, lows=self.lows, closes=self.closes, volumes=self.volumes, pair=pair) self.MFIs[timestamp][pair] = self.MFI self.MACD[timestamp][pair] = self.indicators.MACD_Histogram( period=self.period, dates=self.dates, closes=self.closes, pair=pair) if not initialize_live: self.evaluatePositions(timestamp) self.giveInfo() def evaluatePositions(self, timestamp): # self.balances is a dictionary with balance for each coin self.balances = self.api.getBalance() BuyOptions = [] SellOptions = [] list_of_trades = [] notTraded = [] # latest overall value becomes old value self.oldValue = self.ovrValue self.ovrValue = 0 # loops through pairs and checks if MFI indicates a buy or sell option for pair in self.pairs: if self.MFIs[timestamp][pair]: if self.MFIs[timestamp][pair] < 30: BuyOptions.append((pair, self.MFIs[timestamp][pair])) if self.MFIs[timestamp][pair] > 70: SellOptions.append(pair) # buy if MACD overtakes MACD Signal Line, sell if MACD gets overtaken by MACD Signal Line if len(self.MACD[timestamp][pair]) > int(86400 / self.period): if (0 > self.MACD[timestamp][pair][-2]) and ( self.MACD[timestamp][pair][-1] > 0): # BuyOptions.append(pair) print("According to MACD buy!", self.MACD[timestamp][pair][-2], self.MACD[timestamp][pair][-1], pair) ''' if (0 < self.MACD[timestamp][pair][-2]) and (self.MACD[timestamp][pair][-1] < 0): # SellOptions.append(pair) SellOptions.append(pair) ''' # sorts the definitive buy options starting with lowest MFI and takes the 5 with lowest MFI # todo: used for MFI, improve by spliting the money to different coins, somehow a voting system by different indicators definitiveBuyOptions = sorted(BuyOptions, key=lambda tup: tup[1])[:5] # definitiveBuyOptions = BuyOptions ## definitiveSellOptions.append(sorted(BuyOptions,key=lambda tup:tup[1])[-5:]) ## definitiveSellOptions=sorted(BuyOptions,key=lambda tup:tup[1]) # takes all Sell options as definitive (can be further improved) definitiveSellOptions = SellOptions print('MFIs:', self.MFIs[timestamp]) counter = 0 #########################################SELL################################### for sell in definitiveSellOptions: if sell == "BTCUSDT": continue other = sell[:-3] #other currency BTC = sell[-3:] #Bitcoin quantityTemp = self.balances[other] print(f"sell {sell}") quantity = self.api.filterSell(quantity=quantityTemp, pair=sell, closes=self.closes[timestamp]) if quantity: counter += 1 status, sellPrice = self.api.Sell(pair=sell, quantity=quantity) if status == "FILLED": list_of_trades.append(status) print(f'sold {sell} at {sellPrice}') else: notTraded.append(status, pair) print(status, pair) else: print(f"Would have sold but no coins of this currency, {sell}") # if there is any buy option, only the best option should be taken #########################Buy################################### print( f"Buy options look like (first pair, second MFI): {definitiveBuyOptions} " ) for i, buy in enumerate(definitiveBuyOptions): number_of_buys = len(definitiveBuyOptions) fraction = 1 / 5 # applied 10.September if buy[0] == "BTCUSDT": continue buy = buy[0] other = buy[:-3] # other currency BTC = buy[-3:] # Bitcoin quantityTemp = self.balances[BTC] * fraction if "BNB" not in [BTC, other]: quantityTemp = quantityTemp * (1 - self.fee['BTC']) else: quantityTemp = quantityTemp * (1 - self.fee['BNB']) print(f"quantityTemp is: {quantityTemp}") quantity = self.api.filterBuy(quantityBTCstart=quantityTemp, pair=buy, closes=self.closes[timestamp]) if quantity: counter += 1 status, buyPrice = self.api.Buy(pair=buy, quantity=quantity) if status == "FILLED": list_of_trades.append(status) print(f'bought {buy} at {buyPrice}') else: notTraded.append(status, buy) print(status, buy) else: print( f"Would have bought but no coins (BTC (or USDT)) to buy this currency, {buy}" ) # evaluate the portfolio value called overall if len(list_of_trades) == counter: self.balances = self.api.getBalance() else: print(f'{notTraded} is the list of not Traded pairs') time.sleep(10) print( f'{notTraded} is the list of not Traded pairs after additional 10 seconds, however the balance gets estimated now!' ) self.balances = self.api.getBalance() for pair in self.pairs: if pair == 'BTCUSDT': other = 'USDT' else: other = pair[:-3] # other currency self.ovrValue += self.balances[other] * self.closes[timestamp][ pair] * self.closes[timestamp]['BTCUSDT'] self.ovrValue += self.balances['USDT'] self.ovrValue += self.balances['BTC'] * self.closes[timestamp][ 'BTCUSDT'] print('USDT:', self.balances['USDT'], 'BTC:', self.balances['BTC'], 'overall value:', self.ovrValue) self.counter += self.period def giveInfo(self): Yield = self.ovrValue - self.oldValue if Yield > 1: print("The overall Value is:" + str(self.ovrValue) + color_front("The yield is: " + str(Yield), 0, 153, 76)) elif Yield > 0: print("The overall Value is:" + str(self.ovrValue) + color_front("The yield is: " + str(Yield), 0, 255, 0)) elif Yield < -1: print("The overall Value is:" + str(self.ovrValue) + color_front("The yield is: " + str(Yield), 255, 0, 0)) else: print("The overall Value is:" + str(self.ovrValue) + color_front("The yield is: " + str(Yield), 255, 128, 0)) print("{} days passed".format(self.counter / 86400))
class BotStrategy(object): def __init__(self, name, mode, pair, numTrades, startUSD, startUnit, tradeAmount, stopLoss, targetPrice, backtest, output): self.output = output self.name = name self.mode = mode self.pair = pair self.numTrades = numTrades self.startUSD = startUSD self.startUnit = startUnit self.tradeAmount = tradeAmount self.stopLoss = stopLoss self.targetPrice = targetPrice self.backtest = backtest self.prices = [] self.closes = [] self.trades = [] self.upperBBand = [] self.lowerBBand = [] self.midBBand = [] self.MACDDiff = [] self.MACDSignal = [] self.rsi = [] self.date = "" self.action = [] self.dataPoints = [] self.balancePoints = [] self.MACDPoints = [] self.rsiPoints = [] self.currentPrice = "" self.currentClose = "" self.holdingsUSD = startUSD self.holdingsUnits = startUnit self.balance = startUSD self.balanceNoTrade = startUSD self.profit = 0 self.fees = 0 self.indicators = BotIndicators() self.priceAverage = 0 def tick(self,candlestick): self.action = [] self.description = [] self.currentPrice = float(candlestick.priceAverage) self.prices.append(self.currentPrice) self.updateBalance(0, self.currentPrice) #self.currentClose = float(candlestick['close']) #self.closes.append(self.currentClose) currentUpperBBand, currentLowerBBand, currentMidBBand = self.indicators.bbands(self.prices[-30:]) self.upperBBand.append(currentUpperBBand) self.lowerBBand.append(currentLowerBBand) currentMACDSlow, currentMACDFast, currentMACDDiff, currentMACDSignal = self.indicators.MACD(self.prices[-30:]) self.MACDDiff.append(currentMACDDiff) self.MACDSignal.append(currentMACDSignal) # self.rsi.append(self.indicators.RSI(self.prices[-30:])) if self.backtest in ["backtest", "paper", "live"]: self.evaluatePositions() if self.backtest in ["backtest", "warm"]: tickdate = candlestick.date self.date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(tickdate)) else: tickdate = int(time.time()) self.date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(tickdate)) self.dataPoints.append({'date': str(tickdate * 1000), 'price': str(self.currentPrice), 'upperbb': str(currentUpperBBand), 'lowerbb': str(currentLowerBBand), 'action': 'null', 'description': 'null'}) self.balancePoints.append({'date': str(tickdate * 1000), 'balance': str(self.balance), 'balanceNoTrade': str(self.balanceNoTrade)}) self.MACDPoints.append({'date': str(tickdate * 1000), 'MACDDiff': str(self.MACDDiff[-1]), 'MACDSignal': str(self.MACDSignal[-1])}) # self.rsiPoints.append({'date': str(tickdate * 1000), 'RSI': str(self.rsi[-1]), 'RSIHIGH': str(70), 'RSILOW': str(30)}) if len(self.action) > 0: self.dataPoints[-1]['action'] = "'*'" self.dataPoints[-1]['description'] = "'" + ', '.join(self.action) + "'" def evaluatePositions(self): openTrades = [] for trade in self.trades: if (trade.status == "OPEN"): openTrades.append(trade) if len(openTrades) < self.numTrades and self.holdingsUSD > self.tradeAmount: if self.mode in ["MACD", "ALL"] and self.MACDDiff[-1] < self.MACDSignal[-1] and self.MACDDiff[-2] > self.MACDSignal[-2]: self.trades.append(BotTrade(self.date, "MACD", self.pair, self.currentPrice, self.tradeAmount, self.stopLoss, self.targetPrice, self.backtest, self.output)) self.updateBalance(self.tradeAmount / self.currentPrice, self.currentPrice) self.action.append('Open MACD=, Amount=' + str(self.tradeAmount) + ', Price=' + str(self.currentPrice)) elif self.mode in ["MACD2", "ALL"] and self.MACDDiff[-1] < 500 and ((self.MACDDiff[-1] > 0 and self.MACDDiff[-2] < 0) or (self.MACDDiff[-1] < self.MACDSignal[-1] and self.MACDDiff[-2] > self.MACDSignal[-2])): self.trades.append(BotTrade(self.date, "MACD2", self.pair, self.currentPrice, self.tradeAmount, self.stopLoss, self.targetPrice, self.backtest, self.output)) self.updateBalance(self.tradeAmount / self.currentPrice, self.currentPrice) self.action.append('Open MACD2=, Amount=' + str(self.tradeAmount) + ', Price=' + str(self.currentPrice)) elif self.mode in ["MACD3", "ALL"] and self.MACDDiff[-1] > 0 and self.MACDDiff[-2] < 0: self.trades.append(BotTrade(self.date, "MACD3", self.pair, self.currentPrice, self.tradeAmount, self.stopLoss, self.targetPrice, self.backtest, self.output)) self.updateBalance(self.tradeAmount / self.currentPrice, self.currentPrice) self.action.append('Open MACD3=, Amount=' + str(self.tradeAmount) + ', Price=' + str(self.currentPrice)) elif self.mode in ["BBAND", "ALL"] and self.prices[-1] > self.lowerBBand[-1] and self.prices[-2] < self.lowerBBand[-2]: self.trades.append(BotTrade(self.date, "BBAND", self.pair, self.currentPrice, self.tradeAmount, self.stopLoss, self.targetPrice, self.backtest, self.output)) self.updateBalance(self.tradeAmount / self.currentPrice, self.currentPrice) self.action.append('Open BBAND, Amount='+ str(self.tradeAmount) + ', Price=' + str(self.currentPrice)) elif self.mode in ["RSI"] and self.rsi[-1] < 30 and self.rsi[-2] > 30: self.trades.append(BotTrade(self.date, "RSI", self.pair, self.currentPrice, self.tradeAmount, self.stopLoss, self.targetPrice, self.backtest, self.output)) self.updateBalance(self.tradeAmount / self.currentPrice, self.currentPrice) self.action.append('Open RSI, Amount='+ str(self.tradeAmount) + ', Price=' + str(self.currentPrice)) elif len(self.prices) > 12: if self.mode in ["DROP", "ALL"] and self.prices[-1] < self.prices[-6] *.95 and self.prices[-1] > self.prices[-2]: self.trades.append(BotTrade(self.date, "DROP", self.pair, self.currentPrice, self.tradeAmount, self.stopLoss, self.targetPrice, self.backtest, self.output)) self.updateBalance(self.tradeAmount / self.currentPrice, self.currentPrice) self.action.append('Open DROP, Amount='+ str(self.tradeAmount) + ', Price=' + str(self.currentPrice)) for trade in openTrades: if (self.currentPrice < trade.stopLoss): trade.close(self.date, self.currentPrice, "STOPLOSS") self.updateBalance(-trade.quantity, self.currentPrice) self.action.append('Close STOPLOSS=' + str(self.currentPrice)) elif trade.type in ["MACD"] and ((self.MACDDiff[-2] > 0 and self.MACDDiff[-1] < 0) or (self.MACDDiff[-1] > self.MACDSignal[-1] and self.MACDDiff[-2] < self.MACDSignal[-2])) and self.currentPrice > trade.targetPrice: trade.close(self.date, self.currentPrice, "MACD") self.updateBalance(-trade.quantity, self.currentPrice) self.action.append('CLOSE MACD=' + str(self.currentPrice)) elif trade.type in ["MACD2"] and self.MACDDiff[-1] > self.MACDSignal[-1] and self.MACDDiff[-2] < self.MACDSignal[-2] and self.currentPrice > trade.targetPrice: trade.close(self.date, self.currentPrice, "MACD2") self.updateBalance(-trade.quantity, self.currentPrice) self.action.append('CLOSE MACD2=' + str(self.currentPrice)) elif trade.type in ["MACD3"] and self.MACDDiff[-2] > 0 and self.MACDDiff[-1] < 0 and self.currentPrice > trade.targetPrice: trade.close(self.date, self.currentPrice, "MACD3") self.updateBalance(-trade.quantity, self.currentPrice) self.action.append('CLOSE MACD3=' + str(self.currentPrice)) elif trade.type in ["BBAND"] and self.prices[-1] < self.upperBBand[-1] and self.prices[-2] > self.upperBBand[-2] and self.currentPrice > trade.targetPrice: trade.close(self.date, self.currentPrice, "BBAND") self.updateBalance(-trade.quantity, self.currentPrice) self.action.append('CLOSE BBAND=' + str(self.currentPrice)) elif trade.type in ["RSI"] and self.rsi[-1] > 65 and self.rsi[-2] < 65 and self.currentPrice > trade.targetPrice: trade.close(self.date, self.currentPrice, "RSI") self.updateBalance(-trade.quantity, self.currentPrice) self.action.append('CLOSE RSI=' + str(self.currentPrice)) """elif trade.type in ["DROP"] and self.currentPrice > trade.targetPrice: trade.close(self.date, self.currentPrice, "DROP") self.updateBalance(-trade.quantity, self.currentPrice) self.action.append('CLOSE DROP=' + str(self.currentPrice))""" self.tradeAmount = int((self.holdingsUSD - 1) / self.numTrades) #self.output.log(str(self.tradeAmount)) def showPositions(self): for trade in self.trades: trade.showTrade() def showProfit(self): self.profit = 0 self.fees = 0 for trade in self.trades: self.fees = self.fees + trade.fees if (trade.status == "CLOSED"): self.profit = self.profit + trade.profit tradesOpened = sum(1 for i in self.trades if i.status == "OPEN") tradesClosed = sum(1 for i in self.trades if i.status == "CLOSED") tradesProfitableNumber = sum(1 for i in self.trades if i.profit > 0 and i.status == "CLOSED") tradesProfitableAmount = sum(i.profit for i in self.trades if i.profit > 0 and i.status == "CLOSED") tradesLossesNumber = sum(1 for i in self.trades if i.profit < 0 and i.status == "CLOSED") tradesLossesAmount = sum(i.profit for i in self.trades if i.profit < 0 and i.status == "CLOSED") self.output.log("\nSummary for " + self.name + ", Target / StopLoss " + str(self.targetPrice) + " / " + str(self.stopLoss) + ", with " + self.mode + " Start with: " + str(self.startUnit) + " unit(s) and " + str(self.startUSD) + " USD") self.output.log("Hold: End valuation: " + str(self.balanceNoTrade) + " Units: " + str(self.startUnit) + " USD: " + str(self.startUSD) + " Price: " + str(self.currentPrice)) self.output.log("Trade: End valuation: " + str(self.balance) + " Units: " + str(self.holdingsUnits) + " USD: " + str(self.holdingsUSD) + ". Price: " + str(self.currentPrice) + "\n") if tradesClosed > 0: self.output.log("Profit inc Fees: " + str(self.profit) + ", Fees: " + str(self.fees) + ", " + str(len(self.trades)) + " Trades with " + str(tradesOpened) + " still open\n") #self.output.log("Trades > 0: Number: " + str(tradesProfitableNumber) + ", Total: " + str(tradesProfitableAmount)) #self.output.log("Trades < 0: Number: " + str(tradesLossesNumber) + ", Total: " + str(tradesLossesAmount)) def updateBalance(self, quantity, price): self.holdingsUSD = self.holdingsUSD - (quantity * price) self.holdingsUnits = self.holdingsUnits + quantity self.balance = self.holdingsUSD + (self.holdingsUnits * price) self.balanceNoTrade = self.startUSD + (self.startUnit * price) def drawGraph(self): self.output.drawGraph(self.dataPoints, self.balancePoints, self.MACDPoints, self.name, self.mode)
class BotStrategy(object): def __init__(self, backtest=True, forwardtest=True): self.output = BotLog() self.pair = shared.exchange['pair'] self.coinsInOrder = shared.exchange['coinsInOrder'] self.marketInOrder = shared.exchange['marketInOrder'] self.trades = [] self.currentPrice = "" self.currentClose = "" self.lowestAsk = 0.00 self.highestBid = 0.00 self.simultaneousTrades = 4 self.tradeMultiplier = 0.1 self.ticker = {} self.backTest = backtest self.forwardTest = forwardtest self.indicators = BotIndicators() self.candlesticks = [] self.movingAverages = [] self.movingAveragePeriod = shared.strategy['movingAverageLength'] self.trueRanges = [] self.averageTrueRanges = [] # portfolio self.openOrders = [] #api self.api = BotApi() def tick(self, candlestick): #strategy works on closed candles only if not candlestick.isClosed(): return else: self.candlesticks.append(candlestick) self.currentPrice = candlestick.currentPrice ma = self.indicators.sma(self.candlesticks, shared.strategy['movingAverageLength'], 'close') self.movingAverages.append(ma) tr = self.indicators.trueRange(self.candlesticks) self.trueRanges.append(tr) atr = self.indicators.averageTrueRange(self.trueRanges, 5) self.averageTrueRanges.append(atr) self.ticker = self.getTicker(self.pair) portfolioUpdated = self.updatePortfolio() # If live and portfolio not updated, we may run into some unpleasant issues. # Better stop here for now if not portfolioUpdated: return # Strategy needs at least 2 candles to work if len(self.candlesticks) > 1 and candlestick.isClosed(): self.updateOpenTrades(self.pair) self.evaluatePositions() def evaluatePositions(self): openOrders = self.getOpenOrders(self.pair) ''' Go Long (buy) if all of these are met: Previous price is lower movingAverage Current price is higher than moving average Go short (sell) if: Previous price is higher than moving average Current Price is lower than moving average ''' golong1 = self.candlesticks[-2].close < self.movingAverages[-1] golong2 = self.currentPrice > self.movingAverages[-1] goshort1 = self.candlesticks[-2].close > self.movingAverages[-1] goshort2 = self.currentPrice < self.movingAverages[-1] if golong1 and golong2 and len(openOrders) < self.simultaneousTrades: rate = float(self.ticker['lowestAsk']) total = (shared.exchange['nbMarket'] - shared.exchange['marketInOrder']) * self.tradeMultiplier stoploss = self.currentPrice - self.averageTrueRanges[-1] takeprofit = self.currentPrice + (2 * self.averageTrueRanges[-1]) self.buy(rate, total, self.candlesticks[-1].date, stoploss, takeprofit) if goshort1 and goshort2 and len(openOrders) < self.simultaneousTrades: rate = float(self.ticker['highestBid']) amount = (shared.exchange['nbCoin'] - shared.exchange['coinsInOrder']) * self.tradeMultiplier stoploss = self.currentPrice + self.averageTrueRanges[-1] takeprofit = self.currentPrice - (2 * self.averageTrueRanges[-1]) self.sell(rate, amount, self.candlesticks[-1].date, stoploss, takeprofit) def updateOpenTrades(self, pair): openOrders = self.getOpenOrders(pair) # TODO: implement not backtest for trade in openOrders: trade.tick(self.candlesticks[-1], self.candlesticks[-1].date) def getOpenOrders(self, pair): if not self.backTest and not self.forwardTest: orders = self.api.returnOpenOrders(pair) return orders else: openOrders = [] for order in self.trades: if order.status == 'OPEN': openOrders.append(order) return openOrders def getCurrentPrice(self, pair): if not self.backTest: return self.api.returnTicker(pair)['last'] else: return self.candlesticks[-1].close def getTicker(self, pair): if not self.backTest: return self.api.returnTicker(pair) else: return { 'last': self.currentPrice, 'highestBid': self.currentPrice - self.currentPrice * shared.exchange['spreadPercentage'], 'lowestAsk': self.currentPrice + self.currentPrice * shared.exchange['spreadPercentage'] } def updatePortfolio(self): if not self.backTest and not self.forwardTest: try: portfolio = self.api.returnBalances() if shared.exchange['market'] in portfolio: shared.exchange['nbMarket'] = float( portfolio[shared.exchange['market']]) else: shared.exchange['nbMarket'] = 0.00 if shared.exchange['coin'] in portfolio: shared.exchange['nbCoin'] = float( portfolio[shared.exchange['coin']]) else: shared.exchange['nbCoin'] = 0.00 return True except Exception as e: self.output.warning("Error updating portfolio") print(e) return False else: return True def showPortfolio(self): if not self.backTest and not self.forwardTest: self.updatePortfolio() self.output.log( str(shared.exchange['nbMarket']) + " " + str(shared.exchange['market']) + ' - ' + str(shared.exchange['nbCoin']) + " " + str(shared.exchange['coin'])) def buy(self, rate, total, date, stopLoss=0, takeProfit=0): amount = total / rate order = BotTrade('BUY', rate=rate, amount=amount, total=total, date=date, stopLoss=stopLoss, takeProfit=takeProfit, backtest=self.backTest, forwardtest=self.forwardTest) self.trades.append(order) def sell(self, rate, amount, date, stopLoss=0, takeProfit=0): total = rate * amount order = BotTrade('SELL', rate=rate, amount=amount, total=total, date=date, stopLoss=stopLoss, takeProfit=takeProfit, backtest=self.backTest, forwardtest=self.forwardTest) self.trades.append(order)
class BotStrategy(object): def __init__(self): self.output = BotLog() self.prices = [] self.closes = [] # Needed for Momentum Indicator self.trades = [] self.currentPrice = "" self.currentClose = "" self.numSimulTrades = 1 self.indicators = BotIndicators() self.spreadsheet = [] def tick(self, candlestick): # print candlestick.priceAverage self.currentPrice = float(candlestick.priceAverage) self.prices.append(self.currentPrice) #self.currentClose = float(candlestick['close']) #self.closes.append(self.currentClose) self.output.log("Price: " + str(candlestick.priceAverage) + "\tMoving Average: " + str(self.indicators.movingAverage(self.prices, 15))) self.evaluatePositions() self.updateOpenTrades() self.showPositions() mess = str(candlestick['weightedAverage']) self.GenSpreadsheetInfo(self.prices) def evaluatePositions(self): openTrades = [] for trade in self.trades: if (trade.status == "OPEN"): openTrades.append(trade) if (len(openTrades) < self.numSimulTrades): if (self.currentPrice < self.indicators.movingAverage( self.prices, 20)): self.trades.append(BotTrade(self.currentPrice, stopLoss=.0001)) for trade in openTrades: if (self.currentPrice > self.indicators.movingAverage( self.prices, 20)): trade.close(self.currentPrice) def updateOpenTrades(self): for trade in self.trades: if (trade.status == "OPEN"): trade.tick(self.currentPrice) def showPositions(self): for trade in self.trades: trade.showTrade() def GenSpreadsheetInfo(self, prices): newList = [] if len(self.spreadsheet) == 0: newList.append("Price") newList.append("20_Per_MA") newList.append("50_per_MA") newList.append("TOP_STD") newList.append("BOT_STD") self.spreadsheet.append(newList) newList = [] newList.append(self.currentPrice) newList.append(self.indicators.movingAverage(self.prices, 20)) newList.append(self.indicators.movingAverage(self.prices, 50)) newList.append(self.currentPrice + (2 * self.indicators.standardDeviation(self.prices, 20))) newList.append(self.currentPrice - (2 * self.indicators.standardDeviation(self.prices, 20))) self.spreadsheet.append(newList) def GetSpreadsheetInfo(): return self.spreadsheet
class StochasticStrategySR(BotStrategy): """ Stochastic Oscillator Strategy with Support and Resistance and moving average trends. Includes flags to control entry/exit based on various moving average cases. Trades will only be made once `ready to buy` is set to True when stochastic %K crosses over %D below mid line (50). """ _NAME = 'Stochastic-SR-MA Strategy' # Entry strategy flags. Keep at least one set to true or the trade will never enter PRICE_ABOVE_MA = False STOCH_OS = True # Exit strategy flags. Keep at least one set to true or the trade will never exit TAKE_PROFIT = True take_profit = 0.005 # Exit when realized profit of trade is above this percentage. e.g. 0.005 == 0.5% MA_SLOPE_SLOWING = True # Exit when moving average slope begins to decline PRICE_BELOW_MA = False # Exit when price is below moving average OVER_BOUGHT = False # Exit when stochastic oscillator is over bought def __init__(self, pair, period): BotStrategy.__init__(self, pair, period) self.highs = [] self.lows = [] self.closes = [] self.moving_avgs = [] # Keep track of MAs self.ma_slopes = [] # Keep track of Slope of MAs self.slope_difference = [] self.support_levels = [] self.resistance_levels = [] self.current_price = "" self.pair = pair self.stoch_stop_loss = 2.5 self.cool_down_period = 0 self.indicators = BotIndicators() # Lookback window sizes self.stoch_period = 5 # n previous candles for stochastic indicator self.ma_period_fast = 9 # n previous candles for fast moving average indicator self.ma_slope_lookback = 9 # n previous values for calculating slope of MA. self.ma_period_slow = 26 # n previous candles for slow moving average indicator self.sr_period = 700 # n previous candles for support/resistance self.sr_n = 25 # n-value for S/R indicator. Controls Smoothing. self.hist_period = max(self.stoch_period, self.sr_period, self.ma_period_fast, self.ma_period_slow) self.over_bought = 80 self.over_sold = 20 self.mid_line = 50 self.stoch_ready_to_buy = False # Prime the bot with past data. self.past_typical_prices, self.past_opens, self.past_closes, self.past_highs, self.past_lows = self.get_past_prices(self.period, self.hist_period) if self.past_typical_prices and self.past_closes and self.past_highs and self.past_lows and self.past_opens: self.prices = self.past_typical_prices self.closes = self.past_closes self.highs = self.past_highs self.lows = self.past_lows for i in reversed(range(self.ma_period_fast)): sub_slice = self.prices[:-i - 1] _ma = self.indicators.moving_average(sub_slice[-self.ma_period_fast:], self.ma_period_fast) self.moving_avgs.append(_ma) def tick(self, candlestick): if self.cool_down_period: self.cool_down_period -= 1 # self.output.log("cool down: {}".format(self.cool_down_period)) self.current_price = float(candlestick.typical_price) self.prices.append(self.current_price) # Highs self.currentHigh = float(candlestick.high) self.highs.append(self.currentHigh) # Lows self.currentLow = float(candlestick.low) self.lows.append(self.currentLow) # Closes self.currentClose = float(candlestick.close) self.closes.append(self.currentClose) # Resistance levels - highest highs self.highest_high = float(max(self.highs)) # self.resistance.append(self.highest_high) statsd.histogram('stochastic.resistance', self.highest_high, tags=['stochastic.resistance', 'bot_name:{}.bot_id:{}'.format(BOT_NAME, BOT_ID)]) # Support levels - lowest lows self.lowest_low = float(min(self.lows)) # self.support.append(self.lowest_low) statsd.histogram('stochastic.support', self.lowest_low, tags=['stochastic.support', 'bot_name:{}.bot_id:{}'.format(BOT_NAME, BOT_ID)]) if len(self.prices) > self.hist_period: # Price action self.output.log("\n{color}Typical Price: {price}".format(color=Red, price=str(candlestick.typical_price))) # Moving average m_a = self.indicators.moving_average(self.closes, self.ma_period_fast) self.moving_avgs.append(m_a) self.output.log("Current Moving Average Value: " + str(m_a)) # self.output.log("Last {} Moving Average Values: {}".format(self.ma_period_fast, str(self.moving_avgs[-self.ma_period_fast:]))) statsd.histogram('stochastic.moving_average', m_a, tags=['stochastic.moving_average', 'bot_name:{}.bot_id:{}'.format(BOT_NAME, BOT_ID)]) # Slope of moving averages trend line slope = self.indicators.slope(self.moving_avgs, lookback=self.ma_slope_lookback) self.ma_slopes.append(slope) self.output.log("Slope over last {} periods: {}".format(str(self.ma_slope_lookback), str(self.ma_slopes[-1]))) # self.output.log("Slope values: {}".format(str(self.ma_slopes))) # Create a new list of change in value between values in an old list. e.g. [1,1,2,3,5,8] == [0, 1, 1, 2, 3] # Simple approximation for rate of change. self.slope_difference = [j-i for i, j in zip(self.ma_slopes[:-1], self.ma_slopes[1:])] # self.output.log("Slope differences: {}".format(self.slope_difference)) statsd.histogram('stochastic.slope', slope, tags=['stochastic.slope', 'bot_name:{}.bot_id:{}'.format(BOT_NAME, BOT_ID)]) # Trend direction trend_dir = self.price_to_ma_trend(candlestick.typical_price, m_a) self.output.log("Price to MA trend direction: {} (price to moving average) ".format(str(trend_dir))) statsd.histogram('stochastic.trend', trend_dir, tags=['stochastic.trend', 'bot_name:{}.bot_id:{}'.format(BOT_NAME, BOT_ID)]) # Stochastic k, d = self.indicators.STOCH(self.highs, self.lows, self.closes, fastk_period=self.stoch_period) self.output.log("\n{color}%K: {k}\t%D: {d}".format(color=Yellow, k=str(k[-1:]), d=str(d[-1:]))) # Stochastic Ready to Buy - True if (k[-1] < self.mid_line and d[-1] < self.mid_line) and k[-1] > d[-1]: self.stoch_ready_to_buy = True # Stochastic Ready to Buy - False if (k[-1] > self.mid_line and d[-1] > self.mid_line) and k[-1] < d[-1]: self.stoch_ready_to_buy = False self.output.log("Stochastic ready to buy: {}".format(self.stoch_ready_to_buy)) statsd.histogram('stochastic.percent_k', k[-1], tags=['stochastic.percent_k', 'bot_name:{}.bot_id:{}'.format(BOT_NAME, BOT_ID)]) statsd.histogram('stochastic.percent_d', d[-1], tags=['stochastic.percent_d', 'bot_name:{}.bot_id:{}'.format(BOT_NAME, BOT_ID)]) # Support and Resistance self.sup, self.res = self.indicators.support_resistance(self.closes, n=self.sr_n) self.output.log("\n{color}n={n} - {prices} available prices".format(color=Cyan, n=self.sr_n, prices=len(self.closes))) self.output.log("Support: {sup}\nResistance: {res}{color}".format(sup=self.sup, res=self.res, color=White)) statsd.histogram('sr.support_major', min(self.sup), tags=['sr.support_major', 'bot_name:{}.bot_id:{}'.format(BOT_NAME, BOT_ID)]) statsd.histogram('sr.resistance_major', max(self.res), tags=['sr.resistance_major', 'bot_name:{}.bot_id:{}'.format(BOT_NAME, BOT_ID)]) statsd.histogram('sr.support_minor', max(self.sup), tags=['sr.support_minor', 'bot_name:{}.bot_id:{}'.format(BOT_NAME, BOT_ID)]) statsd.histogram('sr.resistance_minor', min(self.res), tags=['sr.resistance_minor', 'bot_name:{}.bot_id:{}'.format(BOT_NAME, BOT_ID)]) self.evaluate_positions() self.update_open_trades() self.show_positions() def evaluate_positions(self): openTrades = [] for trade in self.trades: if trade.status == "OPEN": openTrades.append(trade) # Instantiate indicator. slowk, slowd = self.indicators.STOCH(self.highs, self.lows, self.closes, fastk_period=self.stoch_period) # Only open a trade when the number of open trades is not more than the configured max allowed. # And there is enough data for indicator if len(openTrades) < self.num_simultaneous_trades and len(self.prices) > self.hist_period: ######################### # Entry Strategy ######################### # Buy/Long if self.PRICE_ABOVE_MA: if self.moving_avgs[-1] < self.current_price and self.stoch_ready_to_buy and not self.cool_down_period: self.output.log("{} buy signal. Ready to buy: {} & typical price {} above MA".format(self._NAME, self.stoch_ready_to_buy, self.current_price - self.moving_avgs[-1])) self.trades.append(BotTrade(pair=self.pair, current_price=self.current_price, trade_type="BUY", order_type='market', stop_loss_percent=self.stoch_stop_loss)) self.cool_down_period = 5 # Wait n periods until another trade can be made if self.STOCH_OS: # Stochastic %K crossover %D below midline (50) if slowk[-1] < self.mid_line and slowd[-1] < self.mid_line and slowk[-2] < slowd[-2] and slowk[-1] > slowd[-1]: self.output.log("{} buy signal. Stochastic %K crossover %D below midline(50)".format(self._NAME, self.stoch_ready_to_buy, self.current_price - self.moving_avgs[-1])) self.trades.append(BotTrade(pair=self.pair, current_price=self.current_price, trade_type="BUY", order_type='market', stop_loss_percent=self.stoch_stop_loss)) # NOTE: LEVERAGE REQUIRED FOR SELLING ON KRAKEN ############### # Exit Strategy ############### for trade in openTrades: # Buy/Long if self.PRICE_BELOW_MA: # Exit when price is below moving average for two consecutive candles, indicating a downward price trend if self.current_price < self.moving_avgs[-1] and self.current_price < self.moving_avgs[-2]: self.output.log("{} Closed on Price {} below MA for two candles".format(self._NAME, self.moving_avgs[-1] - self.current_price)) trade.close(self.current_price) continue if self.MA_SLOPE_SLOWING and len(self.slope_difference) > 6: # Exit when the rate of the SLOPE of the n-period MA begins to slow. if self.slope_difference[-1] < self.slope_difference[-2] < self.slope_difference[-3] < \ self.slope_difference[-4] < self.slope_difference[-5] < self.slope_difference[-6] < \ self.slope_difference[-7] < self.slope_difference[-8]: self.output.log("{} Closed on slope slowing. Slope went down by {}, {}, {}, {}".format( self._NAME, self.slope_difference[-4], self.slope_difference[-3], self.slope_difference[-2], self.slope_difference[-1])) trade.close(self.current_price) continue if self.TAKE_PROFIT: # Exit on % profit. if self.current_price >= (trade.entry_price * (1.0 + self.take_profit)) and trade.trade_type.upper() == "BUY": self.output.log("{} Closed on {}% gain".format(self._NAME, self.take_profit * 100)) trade.close(self.current_price) continue if self.OVER_BOUGHT: # Exit on overbought signal. if slowk[-1] >= self.over_bought and trade.trade_type.upper() == "BUY": self.output.log("{} Closed on over bought signal".format(self._NAME)) trade.close(self.current_price) continue # TODO # Sell/Short Exit Strategy LEVERAGE REQUIRED FOR SHORTING ON KRAKEN @staticmethod def price_to_ma_trend(price, moving_avg): if price <= moving_avg: trend = "DOWN" elif price > moving_avg: trend = "UP" else: trend = "NEUTRAL" return trend
class RoyTrader(): client = Client(api_key, api_secret) user = client.get_current_user() account = client.get_accounts() buys = [] sells = [] prices = [] signals = [] args = [] fibo = BotIndicators() #print(account) print('Trading As: %s (%s)' % (user['name'], user['email'])) #print ('Starting Balance: $%s (%s BTC @ $%s/BTC)' % (balance['EUR'], balance['BTC'], get_price())) def __init__(self, api_key, api_secret): #coinbase #poloniex self.startTrading() def startTrading(self): #prices = [] currentMovingAverage = 0 startTime = False endTime = False historicalData = False tradePlaced = False typeOfTrade = False dataDate = "" orderNumber = "" market_fees = 0.15 # coinbase per-transaction fee in dollars min_profit_margin = 2.0 # minimum price increase before we sell out MACD = 0 if webserver: WebServer.init_Webserver() WebServer.start_Webserver() idloop = 0 while True: try: if idloop < lengthOfMA: idloop = idloop + 1 if strategy == "classic": self.classic_strategy() elif strategy == "MACD": self.MACD_Strategy(idloop) time.sleep(int(period)) except KeyboardInterrupt: print("Bye") if webserver: WebServer.stop_Webserver() sys.exit() def MACD_Strategy(self, idloop): vectorEMAS_AMAF_MACD = [] MACD = 0 MACD_point = 0 RSI_point = 0 lastprice = self.get_price(pair) buyprice = self.get_buy_price() sellprice = self.get_sell_price() currentMovingAverage = 0 previousPrice = 0 emaSlow = 0 emaFast = 0 dataDate = datetime.datetime.now().strftime('%H:%M:%S') #RSI = self.fibo.rsiFunc(self.prices) if len(self.args) > 1: currentMovingAverage = sum(self.prices) / float(len(self.prices)) #elif len(self.args)>12: #emaFast condition #elif len(self.args)>14: #RSI condition appendLine = datetime.datetime.now( ), lastprice, buyprice, sellprice, previousPrice, 2 self.args.append(appendLine) self.prices.append(float(lastprice)) if len(self.args) > 26: vectorEMAS_AMAF_MACD = self.fibo.MACD(self.prices) emaSlow = vectorEMAS_AMAF_MACD[0] emaFast = vectorEMAS_AMAF_MACD[1] MACD = vectorEMAS_AMAF_MACD[2] MACD_point = MACD[0] RSI = self.fibo.rsiFunc(self.prices) RSI_point = RSI[0] print(idloop, " Date: ", str(dataDate), " Period: ", str(period), " coppia: ", str(pair), " Price: ", str(lastprice), " BUY: ", buyprice, "SELL: ", sellprice, " EMA: ", str(currentMovingAverage), " MACD: ", str(MACD_point), " RSI: ", RSI_point) if len(self.args) > 27: self.findSignals(self.args, RSI, MACD) if graphical: self.fibo.plot3(self.args, self.prices, self.signals, emaSlow, emaFast, MACD, RSI) if len(self.args) == lengthOfMA: self.prices.pop(0) self.args.pop(0) if len(self.signals) > 0: #print("data first signal:", self.signals[0][0]) #print("data first args:", self.args[0][0]) if self.signals[0][0] < self.args[0][0]: self.signals.pop(0) print( "************************** SIGNALS POPPED *******************************" ) @property def get_account(self): return [ acct for acct in self.client.get_accounts()['data'] if acct['balance']['currency'] == 'BTC' ][0] @property def get_balance(self): return { account['balance']['currency']: float(account['balance']['amount']), account['native_balance']['currency']: float(account['native_balance']['amount']), } def get_price(self, pair): return float(self.client.get_spot_price(currency_pairo=pair)['amount']) def get_price_LTC(self): print(self.client.get_spot_price(currency_pair=pair)) def get_buy_price(self): return float(self.client.get_buy_price(currency_pair=pair)['amount']) def get_sell_price(self): return float(self.client.get_sell_price(currency_pair=pair)['amount']) def buy(self, amount): buy_obj = self.account.buy(amount, 'EUR') self.buys.append(buy_obj) def sell(self, amount): sell_obj = self.account.sell(amount, 'EUR') self.sells.append(sell_obj) def localbuy(self, amount, price): buy_obj = json.dumps({ 'date': str(datetime.datetime.now()), 'amount': amount, 'price': price }) self.buys.append(buy_obj) with open("www/report.csv", "a") as myfile: myfile.write("BUY," + str(datetime.datetime.now()) + "," + str(amount) + "," + str(price) + "," + str(price * amount) + "\n") myfile.close() def localsell(self, amount, price): sell_obj = json.dumps({ 'date': str(datetime.datetime.now()), 'amount': amount, 'price': price }) self.sells.append(sell_obj) with open("www/report.csv", "a") as myfile: myfile.write("SELL," + str(datetime.datetime.now()) + "," + str(amount) + "," + str(price) + "," + str(price * amount) + "\n") myfile.close() def bytedate2num(self, fmt): def converter(b): return mdates.strpdate2num(fmt)(b.decode('ascii')) return converter def bytespdate2num(self, fmt, encoding='utf-8'): strconverter = mdates.strpdate2num(fmt) def bytesconverter(b): s = b.decode(encoding) return strconverter(s) return bytesconverter def findSignals(self, args, RSI, MACD): date = [x[0] for x in args] prices = [x[1] for x in args] buyprices = [x[2] for x in args] sellprices = [x[3] for x in args] lastprice = prices[-1] buyprice = buyprices[1] sellprice = sellprices[-1] if MACD[-1] > 0 and MACD[-2] < 0 and MACD[-3] < 0 and MACD[-4] < 0: self.signals.append([date[-1], float(lastprice), "buy", "MACD"]) print( str(date[-1]) + " *** MACD *** BUY SIGNAL INTERCEPTED @ " + str(lastprice)) if MACD[-1] < 0 and MACD[-2] > 0 and MACD[-3] > 0 and MACD[-4] > 0: self.signals.append([date[-1], float(lastprice), "sell", "MACD"]) print( str(date[-1]) + " *** MACD *** SELL SIGNAL INTERCEPTED @ " + str(lastprice)) if RSI[-1] < 20 and RSI[-2] > 20 and RSI[-3] > 20 and RSI[-4] > 20: self.signals.append([date[-1], float(lastprice), "buy", "RSI"]) print( str(date[-1]) + " *** RSI *** BUY SIGNAL INTERCEPTED @ " + str(lastprice)) elif RSI[-1] > 80 and RSI[-2] < 80 and RSI[-3] < 80 and RSI[-4] < 80: self.signals.append([date[-1], float(lastprice), "sell", "RSI"]) print( str(date[-1]) + " *** RSI *** SELL SIGNAL INTERCEPTED @ " + str(lastprice)) buycountsRSI = 0 buycountsMACD = 0 sellcountsRSI = 0 sellcountsMACD = 0 for idx, sign in enumerate(self.signals): if sign[2] == "buy": if sign[3] == "RSI": buycountsRSI = buycountsRSI + 1 if sign[3] == "MACD": buycountsMACD == buycountsMACD + 1 if sign[2] == "sell": if sign[3] == "RSI": buycountsRSI = sellcountsRSI + 1 if sign[3] == "MACD": buycountsMACD == sellcountsMACD + 1 if buycountsMACD + buycountsRSI == 2: self.localbuy(2, buyprice) if sellcountsMACD + sellcountsRSI == 2 and gainCheck(sellprice): self.localsell(2, sellprice) def percent(self, part, whole): return 100 * float(part) / float(whole) def percentage(self, percent, whole): return (percent * whole) / 100.0 def gainCheck(self, sellprice): for idx, buy in enumerate(self.buys): resp = json.loads(buy) if percent( (float(sellprice) - (float(resp['price']) - float(market_fees)), buyprice)) > 0: print( "GAIN %:", float(sellprice) - (float(buyprice) - float(market_fees))) return True else: return False
class BotStrategy(): def __init__(self, pair): if (not config.CONFIG["VERBOSE"]): print("Calculating indicators") self.pair = pair self.output = BotLog() self.path = config.CONFIG['PATH'] self.prices = [] self.closes = [] self.trades = [] self.movingAVG = [] self.momentum = [] self.RSI = [] self.currentPrice = "" self.currentClose = "" self.numSimulTrades = 1 self.indicators = BotIndicators() self.graph_data = { "date": [], "movingAverage": [], "momentum": [], "RSI": [] } def tick(self, candlestick): self.currentPrice = float(candlestick.priceAverage) self.currentClose = float(candlestick.close) self.movingAVG = self.indicators.movingAverage(self.prices, 15) self.momentum = self.indicators.momentum(self.closes, 15) self.RSI = self.indicators.RSI(self.prices, 15) self.MACD = self.indicators.MACD(self.prices) self.prices.append(self.currentPrice) self.closes.append(self.currentClose) self.output.log("Price: " + str(candlestick.priceAverage) + "\tMoving Average: " + str(self.movingAVG)) self.evaluatePositions(candlestick) self.updateOpenTrades() self.showPositions() def evaluatePositions(self, candlestick): openTrades = [] for trade in self.trades: if (trade.status == "OPEN"): openTrades.append(trade) # Make sure NoneType is handled if (self.movingAVG is None): self.movingAVG = 0 if (len(openTrades) < self.numSimulTrades): if (self.currentPrice < self.movingAVG): self.trades.append(BotTrade(self.currentPrice, stopLoss=.0001)) for trade in openTrades: if (self.currentPrice > self.movingAVG): trade.close(self.currentPrice) self.graph_data['date'].append(candlestick.date.astype(int)) self.graph_data['movingAverage'].append(self.movingAVG) self.graph_data['momentum'].append(self.momentum) self.graph_data['RSI'].append(self.RSI) df = pd.DataFrame(self.graph_data) df.to_csv( util.os.path.join( self.path, 'data/' + self.pair.replace('/', '-') + "/" + 'indicators.csv')) def updateOpenTrades(self): for trade in self.trades: if (trade.status == "OPEN"): trade.tick(self.currentPrice) def showPositions(self): for trade in self.trades: trade.showTrade()
def __init__(self): self.indicators = BotIndicators()
class MACDStrategy(BotStrategy): """ New MACD strategy """ _NAME = 'MACD Strategy' # Entry strategy flags. Keep at least one set to true or the trade will never enter MACD_CROSSOVER = True # Exit strategy flags. Keep at least one set to true or the trade will never exit TAKE_PROFIT = True take_profit = 0.007 # Exit when realized profit of trade is above this percentage. e.g. 0.005 == 0.5% def __init__(self, pair, period): BotStrategy.__init__(self, pair, period) self.highs = [] self.lows = [] self.closes = [] self.current_price = "" self.pair = pair self.stop_loss_percent = 2.5 self.indicators = BotIndicators() self.macd_fast = 12 self.macd_slow = 26 self.macd_signal = 9 self.macd_period = self.macd_signal + self.macd_slow # Number of data points needed to use MACD indicator self.hist_period = max(self.macd_fast, self.macd_slow, self.macd_signal, self.macd_period) self.max_hist = 0 # Used to keep track of the maximum value of the MACD histogram used on this trade. # Prime the bot with past data. self.past_typical_prices, self.past_opens, self.past_closes, self.past_highs, self.past_lows = self.get_past_prices( self.period, self.hist_period) if self.past_typical_prices and self.past_closes and self.past_highs and self.past_lows and self.past_opens: self.prices = self.past_typical_prices self.closes = self.past_closes self.highs = self.past_highs self.lows = self.past_lows def tick(self, candlestick): self.current_price = float(candlestick.typical_price) self.prices.append(self.current_price) # Highs self.currentHigh = float(candlestick.high) self.highs.append(self.currentHigh) # Lows self.currentLow = float(candlestick.low) self.lows.append(self.currentLow) # Closes self.currentClose = float(candlestick.close) self.closes.append(self.currentClose) if len(self.prices) > self.hist_period: # Price action self.output.log("\n{color}Typical Price: {price}".format( color=Cyan, price=str(candlestick.typical_price))) # MACD m, s, h = self.indicators.MACD(self.prices, self.macd_slow, self.macd_fast, self.macd_signal) self.output.log( "Last/Current indicator values:\tMACD {}\tSignal: {}\t Hist: {}" .format(str(m[-2:]), str(s[-2:]), str(h[-2:]))) statsd.histogram('macd.macd', m[-1], tags=[ 'macd.macd_line', 'bot_name:{}.bot_id:{}'.format( BOT_NAME, BOT_ID) ]) statsd.histogram('macd.signal', s[-1], tags=[ 'macd.signal_line', 'bot_name:{}.bot_id:{}'.format( BOT_NAME, BOT_ID) ]) statsd.histogram('macd.histogram', h[-1], tags=[ 'macd.histogram', 'bot_name:{}.bot_id:{}'.format( BOT_NAME, BOT_ID) ]) self.output.log(White) self.evaluate_positions() self.update_open_trades() self.show_positions() def evaluate_positions(self): openTrades = [] for trade in self.trades: if trade.status == "OPEN": openTrades.append(trade) # Instantiate indicator. _, _, hist = self.indicators.MACD(self.prices, self.macd_slow, self.macd_fast, self.macd_signal) # Only open a trade when the number of open trades is not more than the configured max allowed. # And there is enough data for indicator if len(openTrades) < self.num_simultaneous_trades and len( self.prices) > self.hist_period: ######################### # Entry Strategy ######################### # Buy/Long if self.MACD_CROSSOVER: if hist[-2] < 0.0 < hist[-1]: self.output.log("{} buy signal. MACD crossover".format( self._NAME)) self.trades.append( BotTrade(pair=self.pair, current_price=self.current_price, trade_type="BUY", order_type='market', stop_loss_percent=self.stop_loss_percent)) # NOTE: LEVERAGE REQUIRED FOR SELLING ON KRAKEN ############### # Exit Strategy ############### for trade in openTrades: # Buy/Long if self.TAKE_PROFIT: # Exit on % profit. if self.current_price >= ( trade.entry_price * (1.0 + self.take_profit) ) and trade.trade_type.upper() == "BUY": self.output.log("{} Closed on {}% gain".format( self._NAME, self.take_profit * 100)) trade.close(self.current_price) continue