├── TradingBot ├── botlog.py ├── botexecutions.py ├── bottrades.py ├── test_support.py ├── bottrade.py ├── botChart.py ├── BotGetData.py ├── AutoScroll.py ├── botMetrics.py ├── botstrategy.py └── Gui.py └── README.md /TradingBot/botlog.py: -------------------------------------------------------------------------------- 1 | class BotLog(object): 2 | def __init__(self): 3 | pass 4 | 5 | def log(self, message): 6 | print (message) -------------------------------------------------------------------------------- /TradingBot/botexecutions.py: -------------------------------------------------------------------------------- 1 | 2 | class executionsData(object): 3 | 4 | def __init__(self): 5 | self.execData= [] 6 | 7 | def addExecutions(self, entryTime, pair, entryPrice, side, pnl): 8 | self.execData.append([str(entryTime), pair, entryPrice, side, pnl]) 9 | 10 | -------------------------------------------------------------------------------- /TradingBot/bottrades.py: -------------------------------------------------------------------------------- 1 | 2 | class tradesData(object): 3 | 4 | def __init__(self): 5 | self.tradesData= [] 6 | 7 | def addTrades(self, entryTime, exitTime, pair, entryPrice, exitPrice, side, pnl): 8 | self.tradesData.append([str(entryTime), str(exitTime), pair, entryPrice, exitPrice, side, pnl]) 9 | -------------------------------------------------------------------------------- /TradingBot/test_support.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # 3 | # Support module generated by PAGE version 4.9 4 | # In conjunction with Tcl version 8.6 5 | # Jan 26, 2018 10:29:14 PM 6 | 7 | 8 | import sys 9 | 10 | try: 11 | from Tkinter import * 12 | except ImportError: 13 | from tkinter import * 14 | 15 | try: 16 | import ttk 17 | py3 = 0 18 | except ImportError: 19 | import tkinter.ttk as ttk 20 | py3 = 1 21 | 22 | 23 | def init(top, gui, *args, **kwargs): 24 | global w, top_level, root 25 | w = gui 26 | top_level = top 27 | root = top 28 | 29 | def destroy_window(): 30 | # Function which closes the window. 31 | global top_level 32 | top_level.destroy() 33 | top_level = None 34 | 35 | if __name__ == '__main__': 36 | import test 37 | test.vp_start_gui() 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cryptocurrency trading platform 2 | 3 | Retrieves data using poloniex api. 4 | 5 | ### Availble: 6 | * Control trading sessinon via Start and Stop buttons. 7 | * Immediate close all opened positions, or stop session Together with closing all positions. 8 | * Real time interactive chart with trading strategy executions. 9 | * Real time updating table with opened postions and all trades. 10 | * Trading history storing into csv file. 11 | * Real time messages from exchange and from platform in console. 12 | 13 | Easy to change trading logic, available different markets indicators to use in strategy module(BotGetData.py). 14 | For using neccessary to have your own id and key from poloniex api. 15 | Go to BotGetData.py, 14 row and put your keys Poloniex('your-Api-Key-Here-xxxx','yourSecretKeyHere123456789'). 16 |
17 | 18 | ### Requiremets: 19 | * python 3.6 20 | * poloniex 21 | * tkinter 22 | * pandas 23 | * cayons 24 | * colorama 25 | 26 | ### Install latest poloniex api release: 27 | ``` 28 | pip install https://github.com/s4w3d0ff/python-poloniex/archive/v0.4.7.zip 29 | ``` 30 | ### Run application: 31 | ```From cmd: 32 | python Gui.py 33 | ``` 34 | ### Usage: 35 | ``` 36 | Press Run button on gui. 37 | Data collection from exchange poloniex will be on, after that you can press StartTrade button. 38 | Trading simulation will be started with specified logic in BotStrategy.py 39 | ``` 40 | 41 |
42 | 43 | ### Trading example: 44 | 45 | ![alt text](https://user-images.githubusercontent.com/10981310/36055671-a45e4e42-0e06-11e8-9d3e-875830092582.PNG) 46 | -------------------------------------------------------------------------------- /TradingBot/bottrade.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from botlog import BotLog 3 | import colorama 4 | import crayons 5 | colorama.init() 6 | 7 | 8 | class BotTrade(object): 9 | def __init__(self, currentPrice, stopLossEdge): 10 | self.output = BotLog() 11 | self.status = "OPEN" 12 | self.entryPrice = currentPrice 13 | self.exitPrice = 0 14 | self.pnl= 0 15 | self.side= "Buy" 16 | self.entryTime= datetime.datetime.now() 17 | self.exitTime = "" 18 | self.output.log("Trade opened") 19 | self.stopLoss = currentPrice-stopLossEdge 20 | 21 | def close(self, currentPrice): 22 | self.exitTime = datetime.datetime.now() 23 | self.status = "CLOSED" 24 | self.side = "Sell" 25 | self.exitPrice = currentPrice 26 | self.output.log("Trade closed") 27 | self.pnl = self.exitPrice - self.entryPrice 28 | 29 | tradeStatus = "Entry Price: " + str(round(self.entryPrice, 3)) + " Status: " + \ 30 | str(self.status) + " Exit Price: " + str(round(self.exitPrice, 3)) 31 | tradeStatus = tradeStatus + " Pnl: " + str(round(self.pnl, 3)) 32 | if (self.pnl>0): 33 | tradeStatus = crayons.green(tradeStatus) 34 | else: 35 | tradeStatus = crayons.red(tradeStatus) 36 | self.output.log(tradeStatus) 37 | 38 | 39 | def tick(self, currentPrice): 40 | if (self.stopLoss>0): 41 | if (currentPrice <= self.stopLoss): 42 | self.output.log(crayons.magenta("Exit By Stop Loss")) 43 | self.close(currentPrice) 44 | 45 | def showStatus(self): 46 | if (self.status == "OPEN"): 47 | tradeStatus = "Entry Price: " + str(round(self.entryPrice, 3)) + " Status: " + str(self.status) 48 | tradeStatus= crayons.yellow(tradeStatus) 49 | self.output.log(tradeStatus) 50 | 51 | -------------------------------------------------------------------------------- /TradingBot/botChart.py: -------------------------------------------------------------------------------- 1 | 2 | import matplotlib.pyplot as plt 3 | from matplotlib import style 4 | import numpy as np 5 | import pandas as pd 6 | from matplotlib.ticker import MaxNLocator 7 | import matplotlib.dates as mdates 8 | 9 | 10 | class botChart(object): 11 | def __init__(self): 12 | style.use("dark_background") 13 | #plt.ion() 14 | plt.ioff() 15 | self.fig = plt.figure(figsize=(7, 5)) 16 | self.ax = plt.subplot(111) 17 | plt.ion() 18 | 19 | 20 | def botLiveChart(self, x, y, tradesLive, lastTradePnl, totalPnl, percentChange): 21 | 22 | plt.cla() 23 | #plt.clf() 24 | tradesLiveInterval= [j for j in tradesLive if j[0]>=str(x.min())] 25 | 26 | self.ax.plot(x, y, color="steelblue", label="Price", linewidth=0.6, alpha=0.8) 27 | if len(tradesLive)>0: 28 | buyTime= [pd.Timestamp(j[0]) for j in tradesLiveInterval if j[3]=="Buy"] 29 | buyPrice = [j[2] for j in tradesLiveInterval if j[3] == "Buy"] 30 | sellTime = [pd.Timestamp(j[0]) for j in tradesLiveInterval if j[3] == "Sell"] 31 | sellPrice = [j[2] for j in tradesLiveInterval if j[3] == "Sell"] 32 | self.ax.scatter(np.array(buyTime), buyPrice, marker="^", color="g", s=30, label="Buy") 33 | self.ax.scatter(np.array(sellTime), sellPrice, marker="v", color="r", s=30, label="Sell") 34 | self.ax.tick_params(axis="x", labelsize=10, colors="#b3d9ff") 35 | self.ax.tick_params(axis="y", labelsize=10, colors="#b3d9ff") 36 | self.ax.xaxis.set_major_formatter(mdates.DateFormatter("%H:%M:%S")) 37 | locator = MaxNLocator(prune='both', nbins=10, n=10) 38 | self.ax.xaxis.set_major_locator(locator) 39 | for tick in self.ax.get_xticklabels(): 40 | tick.set_rotation(30) 41 | 42 | self.ax.grid(True) 43 | self.ax.grid(linestyle="-", linewidth="0.2") 44 | self.ax.legend() 45 | pnlText= "LastPnl: "+str(round(lastTradePnl, 3)) + \ 46 | "\nTotalPnl: "+str(round(totalPnl, 3)) + \ 47 | "\nPercChange: "+str(round(percentChange, 3)) 48 | plt.text(0.02, 0.85, pnlText, fontsize=9, transform=plt.gcf().transFigure, \ 49 | color="#b3d9ff",bbox=dict(facecolor='steelblue', alpha=0.3)) 50 | plt.subplots_adjust(left=0.27) 51 | plt.pause(0.001) 52 | plt.draw() 53 | -------------------------------------------------------------------------------- /TradingBot/BotGetData.py: -------------------------------------------------------------------------------- 1 | 2 | import pandas as pd 3 | from poloniex import Poloniex 4 | import time 5 | import datetime 6 | 7 | 8 | 9 | class BotGetData(object): 10 | 11 | def __init__(self, pair, peroid): 12 | self.pair= pair 13 | self.period= peroid 14 | self.conn = Poloniex("YourID", "YourKey") 15 | BotGetData.getHistoricalData(self) 16 | self.lastPrice= 0 17 | self.percentChange= 0 18 | self.askPrice= 0 19 | self.bidPrice= 0 20 | 21 | def getHistoricalData(self): 22 | startTime = str(datetime.datetime.now() - datetime.timedelta(hours=1))[:19] 23 | startTimeUnix = time.mktime(datetime.datetime.strptime(startTime, "%Y-%m-%d %H:%M:%S").timetuple()) 24 | 25 | endTime = str(datetime.datetime.now())[:19] 26 | endTimeUnix = time.mktime(datetime.datetime.strptime(endTime, "%Y-%m-%d %H:%M:%S").timetuple()) 27 | 28 | dd = self.conn.returnChartData(currencyPair=self.pair, start=startTimeUnix, end=endTimeUnix, period=300) 29 | dd = pd.DataFrame(dd) 30 | dd.date = [pd.Timestamp(datetime.datetime.fromtimestamp(x).strftime("%Y-%m-%d %H:%M:%S")) for x in dd.date] 31 | dd.weightedAverage = dd.weightedAverage.astype(float) 32 | prices = dd[["date", "weightedAverage"]] 33 | prices.columns= ["Date", "Price"] 34 | prices["Ask"]= prices.Price 35 | prices["Bid"] = prices.Price 36 | self.historicalData= prices 37 | 38 | def getLastPrice(self): 39 | self.lastPrice = float(self.conn.returnTicker()[self.pair]["last"]) 40 | 41 | def getBestBid(self): 42 | self.bidPrice = float(self.conn.returnTicker()[self.pair]["highestBid"]) 43 | 44 | def getBestAsk(self): 45 | self.askPrice = float(self.conn.returnTicker()[self.pair]["lowestAsk"]) 46 | 47 | def getPercentChange(self): 48 | self.percentChange = float(self.conn.returnTicker()[self.pair]["percentChange"]) 49 | 50 | def updateData(self): 51 | self.getLastPrice() 52 | self.getBestAsk() 53 | self.getBestBid() 54 | self.getPercentChange() 55 | self.historicalData= self.historicalData.append({"Date":datetime.datetime.now(),\ 56 | "Price":self.lastPrice, \ 57 | "Ask":self.askPrice, \ 58 | "Bid": self.bidPrice}, ignore_index=True) 59 | 60 | -------------------------------------------------------------------------------- /TradingBot/AutoScroll.py: -------------------------------------------------------------------------------- 1 | 2 | from tkinter import * 3 | import tkinter.ttk as ttk 4 | 5 | # The following code is added to facilitate the Scrolled widgets you specified. 6 | class AutoScroll(object): 7 | '''Configure the scrollbars for a widget.''' 8 | 9 | def __init__(self, master): 10 | # Rozen. Added the try-except clauses so that this class 11 | # could be used for scrolled entry widget for which vertical 12 | # scrolling is not supported. 5/7/14. 13 | try: 14 | vsb = ttk.Scrollbar(master, orient='vertical', command=self.yview) 15 | except: 16 | pass 17 | hsb = ttk.Scrollbar(master, orient='horizontal', command=self.xview) 18 | 19 | #self.configure(yscrollcommand=_autoscroll(vsb), 20 | # xscrollcommand=_autoscroll(hsb)) 21 | try: 22 | self.configure(yscrollcommand=self._autoscroll(vsb)) 23 | except: 24 | pass 25 | self.configure(xscrollcommand=self._autoscroll(hsb)) 26 | 27 | self.grid(column=0, row=0, sticky='nsew') 28 | try: 29 | vsb.grid(column=1, row=0, sticky='ns') 30 | except: 31 | pass 32 | hsb.grid(column=0, row=1, sticky='ew') 33 | 34 | master.grid_columnconfigure(0, weight=1) 35 | master.grid_rowconfigure(0, weight=1) 36 | 37 | # Copy geometry methods of master (taken from ScrolledText.py) 38 | methods = Pack.__dict__.keys() | Grid.__dict__.keys() \ 39 | | Place.__dict__.keys() 40 | 41 | for meth in methods: 42 | if meth[0] != '_' and meth not in ('config', 'configure'): 43 | setattr(self, meth, getattr(master, meth)) 44 | 45 | @staticmethod 46 | def _autoscroll(sbar): 47 | '''Hide and show scrollbar as needed.''' 48 | def wrapped(first, last): 49 | first, last = float(first), float(last) 50 | if first <= 0 and last >= 1: 51 | sbar.grid_remove() 52 | else: 53 | sbar.grid() 54 | sbar.set(first, last) 55 | return wrapped 56 | 57 | def __str__(self): 58 | return str(self.master) 59 | 60 | def _create_container(func): 61 | '''Creates a ttk Frame with a given master, and use this new frame to 62 | place the scrollbars and the widget.''' 63 | def wrapped(cls, master, **kw): 64 | container = ttk.Frame(master) 65 | return func(cls, container, **kw) 66 | return wrapped 67 | 68 | class ScrolledTreeView(AutoScroll, ttk.Treeview): 69 | '''A standard ttk Treeview widget with scrollbars that will 70 | automatically show/hide as needed.''' 71 | @_create_container 72 | def __init__(self, master, **kw): 73 | ttk.Treeview.__init__(self, master, **kw) 74 | AutoScroll.__init__(self, master) 75 | -------------------------------------------------------------------------------- /TradingBot/botMetrics.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class botMetrics(object): 5 | def __init__(self): 6 | pass 7 | 8 | def movingAverage(self, data, period): 9 | ma= 0 10 | if len(data)> 1: 11 | ma= sum(data[-period:])/len(data[-period:]) 12 | return(ma) 13 | 14 | def momentum(self, dataPoints, period=14): 15 | if (len(dataPoints) > period - 1): 16 | return dataPoints[-1] * 100 / dataPoints[-period] 17 | 18 | def EMA(self, prices, period): 19 | x = np.asarray(prices) 20 | if period>len(x): 21 | period=len(x) 22 | weights = None 23 | weights = np.exp(np.linspace(-1., 0., period)) 24 | weights /= weights.sum() 25 | 26 | dd= sum([a*b for a,b in zip(weights,x[-period:])]) 27 | return dd 28 | 29 | def EMA2(self, prices, period): 30 | s = np.array(prices) 31 | n = period 32 | if len(s)0: 52 | result= ema[0] 53 | 54 | return result 55 | 56 | 57 | def MACD(self, prices, nslow=26, nfast=12): 58 | emaslow = self.EMA(prices, nslow) 59 | emafast = self.EMA(prices, nfast) 60 | return emaslow, emafast 61 | 62 | def RSI(self, prices, period=14): 63 | deltas = np.diff(prices) 64 | seed = deltas[:period + 1] 65 | up = seed[seed >= 0].sum() / period 66 | down = -seed[seed < 0].sum() / period 67 | rs = up / down 68 | rsi = np.zeros_like(prices) 69 | rsi[:period] = 100. - 100. / (1. + rs) 70 | 71 | for i in range(period, len(prices)): 72 | delta = deltas[i - 1] # cause the diff is 1 shorter 73 | if delta > 0: 74 | upval = delta 75 | downval = 0. 76 | else: 77 | upval = 0. 78 | downval = -delta 79 | 80 | up = (up * (period - 1) + upval) / period 81 | down = (down * (period - 1) + downval) / period 82 | rs = up / down 83 | rsi[i] = 100. - 100. / (1. + rs) 84 | if len(prices) > period: 85 | return rsi[-1] 86 | else: 87 | return 50 # output a neutral amount until enough prices in list to calculate RSI -------------------------------------------------------------------------------- /TradingBot/botstrategy.py: -------------------------------------------------------------------------------- 1 | from botlog import BotLog 2 | from bottrade import BotTrade 3 | from botexecutions import executionsData 4 | from bottrades import tradesData 5 | from botMetrics import botMetrics 6 | import pandas as pd 7 | import datetime 8 | import colorama 9 | import crayons 10 | colorama.init() 11 | 12 | 13 | class BotStrategy(object): 14 | 15 | def __init__(self, prices, pair, lengthMA, openPosLimit, stopLossEdge, entryEdge, timePosEdge): 16 | self.output = BotLog() 17 | self.prices = prices 18 | self.closes = [] # Needed for Momentum Indicator 19 | self.trades = [] 20 | self.currentPrice = 0 21 | self.numSimulTrades = openPosLimit 22 | self.pair= pair 23 | self.side= "" 24 | self.lengthMA= lengthMA 25 | self.movAverage= 0 26 | self.expMovAverage= 0 27 | self.strategyTradingMetric= 0 28 | self.allExecutions = executionsData() 29 | self.allTrades = tradesData() 30 | self.metrics= botMetrics() 31 | self.openedPositions =[] 32 | self.lastTradePnl=0 33 | self.totalPnl=0 34 | self.stopLossEdge= stopLossEdge 35 | self.entryEdge= entryEdge 36 | self.timePosEdge= timePosEdge 37 | 38 | def movingAverage(self, data, period): 39 | ma= 0 40 | if len(data)> 1: 41 | ma= sum(data[-period:])/len(data[-period:]) 42 | return(ma) 43 | 44 | def tick(self, price, startTrade): 45 | self.currentPrice= price 46 | self.prices.append(self.currentPrice) 47 | self.movAverage= self.metrics.movingAverage(data=self.prices, period=self.lengthMA) 48 | self.expMovAverage = self.metrics.EMA(prices=self.prices, period=self.lengthMA) 49 | self.strategyTradingMetric= self.expMovAverage 50 | self.output.log("Price: " + str(round(price, 3)) + " MA: " + str(round(self.movAverage ,3)) + \ 51 | " EMA: "+str(round(self.expMovAverage ,3))) 52 | 53 | if startTrade: 54 | self.evaluatePositions() 55 | if self.stopLossEdge>0: 56 | self.updateOpenTrades() 57 | self.showPositions() 58 | self.updateOpenPositions() 59 | 60 | def evaluatePositions(self): 61 | currentTime= datetime.datetime.now() 62 | openTrades = [] 63 | for trade in self.trades: 64 | if (trade.status == "OPEN"): 65 | openTrades.append(trade) 66 | 67 | if (len(openTrades) < self.numSimulTrades): 68 | if ((self.strategyTradingMetric-self.currentPrice)> self.entryEdge): 69 | btrade= BotTrade(self.currentPrice, stopLossEdge=self.stopLossEdge) 70 | self.trades.append(btrade) 71 | self.updateExecutions(trade=btrade, executionTime=btrade.entryTime, executionPrice=btrade.entryPrice) 72 | 73 | for trade in openTrades: 74 | if (self.currentPrice > self.strategyTradingMetric): 75 | if (currentTime-trade.entryTime).seconds>self.timePosEdge: 76 | trade.close(self.currentPrice) 77 | self.updateExecutions(trade=trade, executionTime=trade.exitTime, executionPrice=trade.exitPrice) 78 | self.updateTrades(trade=trade) 79 | self.lastTradePnl= trade.pnl 80 | self.totalPnl= self.totalPnl+self.lastTradePnl 81 | 82 | def closeAll(self): 83 | for trade in self.trades: 84 | if (trade.status == "OPEN"): 85 | trade.close(self.currentPrice) 86 | self.updateExecutions(trade=trade, executionTime=trade.exitTime, executionPrice=trade.exitPrice) 87 | self.updateTrades(trade=trade) 88 | self.lastTradePnl = trade.pnl 89 | self.totalPnl = self.totalPnl + self.lastTradePnl 90 | self.trades= [] 91 | self.openedPositions =[] 92 | 93 | 94 | def updateExecutions(self, trade, executionTime, executionPrice): 95 | self.allExecutions.addExecutions(entryTime=executionTime, pair=self.pair, \ 96 | entryPrice=executionPrice, side=trade.side, pnl=trade.pnl) 97 | def updateTrades(self, trade): 98 | self.allTrades.addTrades(entryTime=trade.entryTime, exitTime=trade.exitTime, pair=self.pair,\ 99 | entryPrice=trade.entryPrice, exitPrice=trade.exitPrice, side=trade.side, 100 | pnl=trade.pnl) 101 | def updateOpenTrades(self): 102 | for trade in self.trades: 103 | if (trade.status == "OPEN"): 104 | if (self.currentPrice < trade.stopLoss): 105 | print("Exit StopLoss") 106 | self.output.log(crayons.magenta("Exit By Stop Loss")) 107 | trade.close(self.currentPrice) 108 | self.updateExecutions(trade=trade, executionTime=trade.exitTime, executionPrice=trade.exitPrice) 109 | self.updateTrades(trade=trade) 110 | self.lastTradePnl = trade.pnl 111 | self.totalPnl = self.totalPnl + self.lastTradePnl 112 | 113 | def updateOpenPositions(self): 114 | openedPositions = [] 115 | for trade in self.trades: 116 | if (trade.status=="OPEN"): 117 | openedPositions.append([trade.entryTime, self.pair, trade.side, \ 118 | round(trade.entryPrice,2), round(trade.pnl,2)]) 119 | self.openedPositions= openedPositions 120 | 121 | 122 | def showPositions(self): 123 | openedPositions= [] 124 | for trade in self.trades: 125 | trade.showStatus() 126 | return openedPositions 127 | 128 | def showOpenedPositions(self): 129 | temp= pd.DataFrame(self.openedPositions) 130 | if len(temp)>0: 131 | temp.columns= ["Time", "Pair", "Side", "EntryPrice", "Pnl"] 132 | return temp 133 | 134 | def showExecutions(self): 135 | temp= pd.DataFrame(self.allExecutions.execData) 136 | if len(temp)>0: 137 | temp.columns= ["Time", "Pair", "Price", "Side", "Pnl"] 138 | return temp 139 | 140 | def showTrades(self): 141 | temp = pd.DataFrame(self.allTrades.tradesData) 142 | if len(temp) > 0: 143 | temp.columns = ["EntryTime", "ExitTime", "Pair", "EntryPrice", "ExitPrice", "Side", "Pnl"] 144 | return temp 145 | 146 | def clearExecutions(self): 147 | self.allExecutions = executionsData() 148 | self.allTrades = tradesData() 149 | -------------------------------------------------------------------------------- /TradingBot/Gui.py: -------------------------------------------------------------------------------- 1 | 2 | from tkinter import * 3 | from tkinter import messagebox 4 | import tkinter.ttk as ttk 5 | import test_support 6 | import datetime 7 | from BotGetData import BotGetData 8 | from botstrategy import BotStrategy 9 | from botChart import botChart 10 | from botlog import BotLog 11 | from AutoScroll import * 12 | import matplotlib.pyplot as plt 13 | import colorama 14 | import crayons 15 | import warnings 16 | warnings.filterwarnings("ignore") 17 | colorama.init() 18 | 19 | def vp_start_gui(): 20 | '''Starting point when module is the main routine.''' 21 | global val, w, root 22 | root = Tk() 23 | top = Trading_Gui (root) 24 | test_support.init(root, top) 25 | root.mainloop() 26 | 27 | w = None 28 | def create_Trading_Gui(root, *args, **kwargs): 29 | '''Starting point when module is imported by another program.''' 30 | global w, w_win, rt 31 | rt = root 32 | w = Toplevel (root) 33 | top = Trading_Gui (w) 34 | test_support.init(w, top, *args, **kwargs) 35 | return (w, top) 36 | 37 | def destroy_Trading_Gui(): 38 | global w 39 | w.destroy() 40 | w = None 41 | 42 | def chartHorizon(histDataUpdated, interval): 43 | currentTime= histDataUpdated.Date.iloc[-1] 44 | histDataUpdated= histDataUpdated[histDataUpdated.Date>=currentTime-datetime.timedelta(minutes=interval)] 45 | return histDataUpdated 46 | 47 | def clear_all(): 48 | gl = globals().copy() 49 | for var in gl: 50 | if var[0] == '_': continue 51 | if 'func' in str(globals()[var]): continue 52 | if 'module' in str(globals()[var]): continue 53 | 54 | del globals()[var] 55 | 56 | class Trading_Gui: 57 | def __init__(self, top=None): 58 | '''This class configures and populates the toplevel window. 59 | top is the toplevel containing window.''' 60 | _bgcolor = '#d9d9d9' # X11 color: 'gray85' 61 | _fgcolor = '#000000' # X11 color: 'black' 62 | _compcolor = '#d9d9d9' # X11 color: 'gray85' 63 | _ana1color = '#d9d9d9' # X11 color: 'gray85' 64 | _ana2color = '#d9d9d9' # X11 color: 'gray85' 65 | self.root = root 66 | self.style = ttk.Style() 67 | self.style.theme_use("vista") 68 | self.style.configure('.',background=_bgcolor) 69 | self.style.configure('.',foreground=_fgcolor) 70 | self.style.configure('.',font="TkDefaultFont") 71 | self.style.map('.',background= [('selected', _compcolor), ('active',_ana2color)]) 72 | self.strategy= [] 73 | self.showChart = False 74 | self.startTrading = False 75 | self.closeAll= False 76 | self.stopRunning= False 77 | self.numberOfExecutions= 0 78 | self.numberOfTrades = 0 79 | self.output = BotLog() 80 | self.liveChartObject= [] 81 | self.CheckVar = IntVar() 82 | 83 | top.geometry("990x518+446+155") 84 | top.title("Trading Gui") 85 | top.configure(background="#d9d9d9") 86 | 87 | self.TFrame1 = ttk.Frame(top) 88 | self.TFrame1.place(relx=0.01, rely=0.02, relheight=0.98, relwidth=0.11) 89 | self.TFrame1.configure(relief=GROOVE) 90 | self.TFrame1.configure(borderwidth="2") 91 | self.TFrame1.configure(relief=GROOVE) 92 | self.TFrame1.configure(width=95) 93 | 94 | self.Run = ttk.Button(self.TFrame1, command=self.main) 95 | self.Run.place(relx=0.11, rely=0.07, height=35, width=76) 96 | self.Run.configure(takefocus="") 97 | self.Run.configure(text='''Run''') 98 | self.Run.configure(width=76) 99 | 100 | self.Stop = ttk.Button(self.TFrame1, command=self.stopRun) 101 | self.Stop.place(relx=0.11, rely=0.17, height=35, width=76) 102 | self.Stop.configure(takefocus="") 103 | self.Stop.configure(text='''Stop''') 104 | self.Stop.configure(width=76) 105 | 106 | self.StartTrade = ttk.Button(self.TFrame1, command= self.useStartegy) 107 | self.StartTrade.place(relx=0.11, rely=0.27, height=35, width=76) 108 | self.StartTrade.configure(takefocus="") 109 | self.StartTrade.configure(text='''StartTrade''') 110 | self.StartTrade.configure(width=76) 111 | 112 | self.StopTrade = ttk.Button(self.TFrame1, command=self.stopTrade) 113 | self.StopTrade.place(relx=0.11, rely=0.37, height=35, width=76) 114 | self.StopTrade.configure(takefocus="") 115 | self.StopTrade.configure(text='''StopTrade''') 116 | self.StopTrade.configure(width=76) 117 | 118 | self.ShowChart = ttk.Button(self.TFrame1, command= self.chartOpen) 119 | self.ShowChart.place(relx=0.11, rely=0.47, height=35, width=76) 120 | self.ShowChart.configure(takefocus="") 121 | self.ShowChart.configure(text='''ShowChart''') 122 | self.ShowChart.configure(width=76) 123 | 124 | self.CloseChart = ttk.Button(self.TFrame1, command= self.chartClose) 125 | self.CloseChart.place(relx=0.11, rely=0.57, height=35, width=76) 126 | self.CloseChart.configure(takefocus="") 127 | self.CloseChart.configure(text='''CloseChart''') 128 | self.CloseChart.configure(width=76) 129 | 130 | self.ClosePos = ttk.Button(self.TFrame1, command= self.closeAllPositions) 131 | self.ClosePos.place(relx=0.11, rely=0.67, height=35, width=76) 132 | self.ClosePos.configure(takefocus="") 133 | self.ClosePos.configure(text='''ClosePos''') 134 | 135 | self.CheckVar.set(1) 136 | self.SaveTrades = Checkbutton(self.TFrame1, text="SaveHistory", variable=self.CheckVar, bg=_bgcolor) 137 | self.SaveTrades.place(relx=0.11, rely=0.77, height=35, width=80) 138 | 139 | self.Exit = ttk.Button(self.TFrame1, command= self.CloseWindow) 140 | self.Exit.place(relx=0.11, rely=0.9, height=35, width=76) 141 | self.Exit.configure(takefocus="") 142 | self.Exit.configure(text='''Exit''') 143 | self.Exit.configure(width=76) 144 | 145 | self.TFrame3 = Frame(top) 146 | self.TFrame3.place(relx=0.15, rely=0.05, relheight=0.1, relwidth=0.8) 147 | self.TFrame3.configure(relief=GROOVE) 148 | self.TFrame3.configure(borderwidth="2") 149 | self.TFrame3.configure(relief=GROOVE) 150 | self.TFrame3.configure(width=475) 151 | self.TFrame3.configure(takefocus="0") 152 | 153 | self.TLabel5 = Label(self.TFrame3) 154 | self.TLabel5.place(relx=0.01, rely=0.18, height=19, width=55) 155 | self.TLabel5.configure(font=('Helvetica', 8)) 156 | self.TLabel5.configure(foreground="#075bb8") 157 | self.TLabel5.configure(relief=FLAT) 158 | self.TLabel5.configure(text='''Ticker:''') 159 | 160 | self.ticker = Entry(self.TFrame3) 161 | self.ticker.insert(END, str("USDT_BTC")) 162 | self.ticker.place(relx=0.07, rely=0.18, relheight=0.44, relwidth=0.09) 163 | self.ticker.configure(font=('Helvetica', 10)) 164 | self.ticker.configure(background="white") 165 | self.ticker.configure(font="TkTextFont") 166 | self.ticker.configure(foreground="black") 167 | self.ticker.configure(highlightbackground="#d9d9d9") 168 | self.ticker.configure(highlightcolor="black") 169 | self.ticker.configure(insertbackground="black") 170 | self.ticker.configure(selectbackground="#c4c4c4") 171 | self.ticker.configure(selectforeground="black") 172 | self.ticker.configure(takefocus="0") 173 | 174 | self.TLabel4 = Label(self.TFrame3) 175 | self.TLabel4.place(relx=0.18, rely=0.18, height=19, width=75) 176 | self.TLabel4.configure(font=('Helvetica', 8)) 177 | self.TLabel4.configure(foreground="#075bb8") 178 | self.TLabel4.configure(relief=FLAT) 179 | self.TLabel4.configure(text='''StopLossEdge:''') 180 | 181 | self.StopLossEdge = Entry(self.TFrame3) 182 | self.StopLossEdge.insert(END, str(10)) 183 | self.StopLossEdge.place(relx=0.28, rely=0.18, relheight=0.44, relwidth=0.09) 184 | self.StopLossEdge.configure(font=('Helvetica', 10)) 185 | self.StopLossEdge.configure(background="white") 186 | self.StopLossEdge.configure(font="TkTextFont") 187 | self.StopLossEdge.configure(foreground="black") 188 | self.StopLossEdge.configure(highlightbackground="#d9d9d9") 189 | self.StopLossEdge.configure(highlightcolor="black") 190 | self.StopLossEdge.configure(insertbackground="black") 191 | self.StopLossEdge.configure(selectbackground="#c4c4c4") 192 | self.StopLossEdge.configure(selectforeground="black") 193 | self.StopLossEdge.configure(takefocus="0") 194 | 195 | self.TLabel5 = Label(self.TFrame3) 196 | self.TLabel5.place(relx=0.39, rely=0.2, height=19, width=65) 197 | self.TLabel5.configure(font=('Helvetica', 8)) 198 | self.TLabel5.configure(foreground="#075bb8") 199 | self.TLabel5.configure(relief=FLAT) 200 | self.TLabel5.configure(takefocus="0") 201 | self.TLabel5.configure(text='''EntryEdge:''') 202 | 203 | self.EntryEdge = Entry(self.TFrame3) 204 | self.EntryEdge.insert(END, str(1)) 205 | self.EntryEdge.place(relx=0.47, rely=0.15, relheight=0.44, relwidth=0.09) 206 | self.EntryEdge.configure(background="white") 207 | self.EntryEdge.configure(font="TkTextFont") 208 | self.EntryEdge.configure(foreground="black") 209 | self.EntryEdge.configure(highlightbackground="#d9d9d9") 210 | self.EntryEdge.configure(highlightcolor="black") 211 | self.EntryEdge.configure(insertbackground="black") 212 | self.EntryEdge.configure(selectbackground="#c4c4c4") 213 | self.EntryEdge.configure(selectforeground="black") 214 | self.EntryEdge.configure(takefocus="0") 215 | 216 | self.TLabel6 = Label(self.TFrame3) 217 | self.TLabel6.place(relx=0.58, rely=0.2, height=19, width=85) 218 | self.TLabel6.configure(font=('Helvetica', 8)) 219 | self.TLabel6.configure(foreground="#075bb8") 220 | self.TLabel6.configure(relief=FLAT) 221 | self.TLabel6.configure(takefocus="0") 222 | self.TLabel6.configure(text='''OpenTradesLimit:''') 223 | 224 | self.OpenTradesLimit = Entry(self.TFrame3) 225 | self.OpenTradesLimit.insert(END, str(4)) 226 | self.OpenTradesLimit.place(relx=0.69, rely=0.15, relheight=0.44, relwidth=0.09) 227 | self.OpenTradesLimit.configure(background="white") 228 | self.OpenTradesLimit.configure(font="TkTextFont") 229 | self.OpenTradesLimit.configure(foreground="black") 230 | self.OpenTradesLimit.configure(highlightbackground="#d9d9d9") 231 | self.OpenTradesLimit.configure(highlightcolor="black") 232 | self.OpenTradesLimit.configure(insertbackground="black") 233 | self.OpenTradesLimit.configure(selectbackground="#c4c4c4") 234 | self.OpenTradesLimit.configure(selectforeground="black") 235 | self.OpenTradesLimit.configure(takefocus="0") 236 | 237 | 238 | self.TLabel7 = Label(self.TFrame3) 239 | self.TLabel7.place(relx=0.79, rely=0.2, height=19, width=85) 240 | self.TLabel7.configure(font=('Helvetica', 8)) 241 | self.TLabel7.configure(foreground="#075bb8") 242 | self.TLabel7.configure(relief=FLAT) 243 | self.TLabel7.configure(takefocus="0") 244 | self.TLabel7.configure(text='''Maintenance:''') 245 | 246 | self.Maintenance = Entry(self.TFrame3) 247 | self.Maintenance.insert(END, str(1)) 248 | self.Maintenance.place(relx=0.89, rely=0.15, relheight=0.44, relwidth=0.09) 249 | self.Maintenance.configure(background="white") 250 | self.Maintenance.configure(font="TkTextFont") 251 | self.Maintenance.configure(foreground="black") 252 | self.Maintenance.configure(highlightbackground="#d9d9d9") 253 | self.Maintenance.configure(highlightcolor="black") 254 | self.Maintenance.configure(insertbackground="black") 255 | self.Maintenance.configure(selectbackground="#c4c4c4") 256 | self.Maintenance.configure(selectforeground="black") 257 | self.Maintenance.configure(takefocus="0") 258 | 259 | 260 | self.style.configure('Treeview.Heading', font="TkDefaultFont") 261 | self.Scrolledtreeview1 = ScrolledTreeView(top) 262 | self.Scrolledtreeview1.place(relx=0.15, rely=0.23, relheight=0.28, relwidth=0.6) 263 | self.Scrolledtreeview1.configure(columns="Col1 Col2 Col3 Col4 Col5") 264 | self.Scrolledtreeview1.configure(takefocus="0") 265 | self.Scrolledtreeview1.heading("#0",text="Id") 266 | self.Scrolledtreeview1.heading("#0",anchor="center") 267 | self.Scrolledtreeview1.column("#0",width="35") 268 | self.Scrolledtreeview1.column("#0",minwidth="20") 269 | self.Scrolledtreeview1.column("#0",stretch="1") 270 | self.Scrolledtreeview1.column("#0",anchor="w") 271 | self.Scrolledtreeview1.heading("Col1",text="Time") 272 | self.Scrolledtreeview1.heading("Col1",anchor="center") 273 | self.Scrolledtreeview1.column("Col1",width="150") 274 | self.Scrolledtreeview1.column("Col1",minwidth="20") 275 | self.Scrolledtreeview1.column("Col1",stretch="1") 276 | self.Scrolledtreeview1.column("Col1",anchor="w") 277 | self.Scrolledtreeview1.heading("Col2",text="Symbol") 278 | self.Scrolledtreeview1.heading("Col2",anchor="center") 279 | self.Scrolledtreeview1.column("Col2",width="80") 280 | self.Scrolledtreeview1.column("Col2",minwidth="20") 281 | self.Scrolledtreeview1.column("Col2",stretch="1") 282 | self.Scrolledtreeview1.column("Col2",anchor="w") 283 | self.Scrolledtreeview1.heading("Col3",text="Side") 284 | self.Scrolledtreeview1.heading("Col3",anchor="center") 285 | self.Scrolledtreeview1.column("Col3",width="80") 286 | self.Scrolledtreeview1.column("Col3",minwidth="20") 287 | self.Scrolledtreeview1.column("Col3",stretch="1") 288 | self.Scrolledtreeview1.column("Col3",anchor="w") 289 | self.Scrolledtreeview1.heading("Col4",text="Price") 290 | self.Scrolledtreeview1.heading("Col4",anchor="center") 291 | self.Scrolledtreeview1.column("Col4",width="80") 292 | self.Scrolledtreeview1.column("Col4",minwidth="20") 293 | self.Scrolledtreeview1.column("Col4",stretch="1") 294 | self.Scrolledtreeview1.column("Col4",anchor="w") 295 | self.Scrolledtreeview1.heading("Col5",text="Pnl") 296 | self.Scrolledtreeview1.heading("Col5",anchor="center") 297 | self.Scrolledtreeview1.column("Col5",width="80") 298 | self.Scrolledtreeview1.column("Col5",minwidth="20") 299 | self.Scrolledtreeview1.column("Col5",stretch="1") 300 | self.Scrolledtreeview1.column("Col5",anchor="w") 301 | 302 | 303 | self.menubar = Menu(top,font="TkMenuFont",bg='#bef7bb',fg=_fgcolor) 304 | top.configure(menu = self.menubar) 305 | 306 | self.Scrolledtreeview2 = ScrolledTreeView(top) 307 | self.style.configure("Scrolledtreeview2", font='helvetica 24') 308 | self.Scrolledtreeview2.place(relx=0.15, rely=0.61, relheight=0.32, relwidth=0.8) 309 | self.Scrolledtreeview2.configure(columns="Col1 Col2 Col3 Col4 Col5 Col6 Col7") 310 | self.Scrolledtreeview2.configure(takefocus="0") 311 | self.Scrolledtreeview2.heading("#0", text="Id") 312 | self.Scrolledtreeview2.heading("#0", anchor="center") 313 | self.Scrolledtreeview2.column("#0", width="35") 314 | self.Scrolledtreeview2.column("#0", minwidth="20") 315 | self.Scrolledtreeview2.column("#0", stretch="1") 316 | self.Scrolledtreeview2.column("#0", anchor="w") 317 | self.Scrolledtreeview2.heading("Col1", text="EntryTime") 318 | self.Scrolledtreeview2.heading("Col1", anchor="center") 319 | self.Scrolledtreeview2.column("Col1", width="150") 320 | self.Scrolledtreeview2.column("Col1", minwidth="20") 321 | self.Scrolledtreeview2.column("Col1", stretch="1") 322 | self.Scrolledtreeview2.column("Col1", anchor="w") 323 | self.Scrolledtreeview2.heading("Col2", text="ExitTime") 324 | self.Scrolledtreeview2.heading("Col2", anchor="center") 325 | self.Scrolledtreeview2.column("Col2", width="150") 326 | self.Scrolledtreeview2.column("Col2", minwidth="20") 327 | self.Scrolledtreeview2.column("Col2", stretch="1") 328 | self.Scrolledtreeview2.column("Col2", anchor="w") 329 | self.Scrolledtreeview2.heading("Col3", text="Symbol") 330 | self.Scrolledtreeview2.heading("Col3", anchor="center") 331 | self.Scrolledtreeview2.column("Col3", width="81") 332 | self.Scrolledtreeview2.column("Col3", minwidth="20") 333 | self.Scrolledtreeview2.column("Col3", stretch="1") 334 | self.Scrolledtreeview2.column("Col3", anchor="w") 335 | self.Scrolledtreeview2.heading("Col4", text="Side") 336 | self.Scrolledtreeview2.heading("Col4", anchor="center") 337 | self.Scrolledtreeview2.column("Col4", width="80") 338 | self.Scrolledtreeview2.column("Col4", minwidth="20") 339 | self.Scrolledtreeview2.column("Col4", stretch="1") 340 | self.Scrolledtreeview2.column("Col4", anchor="w") 341 | self.Scrolledtreeview2.heading("Col5", text="EntryPrice") 342 | self.Scrolledtreeview2.heading("Col5", anchor="center") 343 | self.Scrolledtreeview2.column("Col5", width="80") 344 | self.Scrolledtreeview2.column("Col5", minwidth="20") 345 | self.Scrolledtreeview2.column("Col5", stretch="1") 346 | self.Scrolledtreeview2.column("Col5", anchor="w") 347 | self.Scrolledtreeview2.heading("Col6", text="ExitPrice") 348 | self.Scrolledtreeview2.heading("Col6", anchor="center") 349 | self.Scrolledtreeview2.column("Col6", width="80") 350 | self.Scrolledtreeview2.column("Col6", minwidth="20") 351 | self.Scrolledtreeview2.column("Col6", stretch="1") 352 | self.Scrolledtreeview2.column("Col6", anchor="w") 353 | self.Scrolledtreeview2.heading("Col7", text="Pnl") 354 | self.Scrolledtreeview2.heading("Col7", anchor="center") 355 | self.Scrolledtreeview2.column("Col7", width="80") 356 | self.Scrolledtreeview2.column("Col7", minwidth="20") 357 | self.Scrolledtreeview2.column("Col7", stretch="1") 358 | self.Scrolledtreeview2.column("Col7", anchor="w") 359 | 360 | self.Label1 = Label(top) 361 | self.Label1.place(relx=0.15, rely=0.17, height=25, width=595) 362 | self.Label1.configure(font=('Helvetica', 10)) 363 | self.Label1.configure(anchor=N) 364 | self.Label1.configure(background="#b4c2fe") 365 | self.Label1.configure(compound="left") 366 | self.Label1.configure(cursor="bottom_left_corner") 367 | self.Label1.configure(disabledforeground="#a3a3a3") 368 | self.Label1.configure(foreground="#000000") 369 | self.Label1.configure(justify=LEFT) 370 | self.Label1.configure(relief=RIDGE) 371 | self.Label1.configure(text='''Opened Positions''') 372 | self.Label1.configure(textvariable=test_support) 373 | self.Label1.configure(width=459) 374 | 375 | self.Label2 = Label(top) 376 | self.Label2.place(relx=0.15, rely=0.55, height=25, width=788) 377 | self.Label2.configure(font=('Helvetica', 10)) 378 | self.Label2.configure(activebackground="#f9f9f9") 379 | self.Label2.configure(activeforeground="black") 380 | self.Label2.configure(anchor=N) 381 | self.Label2.configure(background="#b4c2fe") 382 | self.Label2.configure(compound="left") 383 | self.Label2.configure(cursor="bottom_left_corner") 384 | self.Label2.configure(disabledforeground="#a3a3a3") 385 | self.Label2.configure(foreground="#000000") 386 | self.Label2.configure(highlightbackground="#d9d9d9") 387 | self.Label2.configure(highlightcolor="black") 388 | self.Label2.configure(justify=LEFT) 389 | self.Label2.configure(relief=RIDGE) 390 | self.Label2.configure(text='''Trades''') 391 | self.Label2.configure(width=459) 392 | 393 | self.TFrame2 = Frame(top) 394 | self.TFrame2.place(relx=0.76, rely=0.23, relheight=0.22, relwidth=0.2) 395 | self.TFrame2.configure(relief=SUNKEN) 396 | self.TFrame2.configure(borderwidth="2") 397 | self.TFrame2.configure(relief=SUNKEN) 398 | self.TFrame2.configure(width=150) 399 | self.TFrame2.configure(takefocus="0") 400 | 401 | self.TotalPnl = Label(self.TFrame2) 402 | self.TotalPnl.place(relx=0.002, rely=0.17, height=29, width=86) 403 | self.TotalPnl.configure(font=('Helvetica', 11)) 404 | self.TotalPnl.configure(foreground="#075bb8") 405 | self.TotalPnl.configure(relief=FLAT) 406 | self.TotalPnl.configure(justify=RIGHT) 407 | self.TotalPnl.configure(takefocus="0") 408 | self.TotalPnl.configure(text='''TotalPnl:''') 409 | 410 | self.TradesCount = Label(self.TFrame2) 411 | self.TradesCount.place(relx=0.01, rely=0.63, height=29, width=106) 412 | self.TradesCount.configure(font=('Helvetica', 11)) 413 | self.TradesCount.configure(foreground="#075bb8") 414 | self.TradesCount.configure(relief=FLAT) 415 | self.TradesCount.configure(justify=RIGHT) 416 | self.TradesCount.configure(takefocus="0") 417 | self.TradesCount.configure(text='''TradesCount:''') 418 | 419 | self.tradesCount = Text(self.TFrame2) 420 | self.tradesCount.configure(font=('Helvetica', 10)) 421 | self.tradesCount.place(relx=0.52, rely=0.6, relheight=0.3, relwidth=0.4) 422 | self.tradesCount.configure(font=('Helvetica', 10)) 423 | self.tradesCount.configure(background="white") 424 | self.tradesCount.configure(font="TkTextFont") 425 | self.tradesCount.configure(foreground="black") 426 | self.tradesCount.configure(highlightbackground="#d9d9d9") 427 | self.tradesCount.configure(highlightcolor="black") 428 | self.tradesCount.configure(insertbackground="black") 429 | self.tradesCount.configure(selectbackground="#c4c4c4") 430 | self.tradesCount.configure(selectforeground="black") 431 | self.tradesCount.configure(takefocus="0") 432 | self.tradesCount.configure(width=104) 433 | 434 | self.totalPnl = Text(self.TFrame2, font= ('Times', '24', 'bold italic') ) 435 | self.totalPnl.place(relx=0.52, rely=0.1, relheight=0.3, relwidth=0.4) 436 | self.totalPnl.configure(font=('Helvetica', 10)) 437 | self.totalPnl.configure(background="white") 438 | self.totalPnl.configure(font="TkTextFont") 439 | self.totalPnl.configure(foreground="black") 440 | self.totalPnl.configure(highlightbackground="#d9d9d9") 441 | self.totalPnl.configure(highlightcolor="black") 442 | self.totalPnl.configure(insertbackground="black") 443 | self.totalPnl.configure(selectbackground="#c4c4c4") 444 | self.totalPnl.configure(selectforeground="black") 445 | self.totalPnl.configure(takefocus="0") 446 | self.totalPnl.configure(width=104) 447 | 448 | 449 | def stopRun(self): 450 | self.root.update() 451 | self.stopRunning= True 452 | self.output.log(crayons.red("System stop..........")) 453 | 454 | def CloseWindow(self) : 455 | self.root.destroy() 456 | 457 | def chartOpen(self) : 458 | self.liveChartObject = botChart() 459 | self.root.update() 460 | self.showChart= True 461 | 462 | def chartClose(self) : 463 | self.root.update() 464 | self.showChart= False 465 | plt.close() 466 | 467 | def useStartegy(self) : 468 | self.root.update() 469 | self.startTrading= True 470 | self.stopRunning= False 471 | self.output.log(crayons.green("Start trading..........")) 472 | 473 | def stopTrade(self) : 474 | self.root.update() 475 | try: 476 | opPos= self.strategy.openedPositions 477 | except: 478 | opPos= [] 479 | if len(opPos)>0: 480 | messagebox.showinfo("Warning", "There are opened position. Close all before stopping trading!") 481 | else: 482 | self.startTrading = False 483 | self.output.log(crayons.green("End trading..........")) 484 | 485 | def closeAllPositions(self) : 486 | self.root.update() 487 | self.closeAll = True 488 | 489 | def insertDataExecutions(self, executions): 490 | n= len(executions) 491 | if n>self.numberOfExecutions: 492 | newExecutions= executions[-(n-self.numberOfExecutions):] 493 | k= n 494 | for row in newExecutions: 495 | self.Scrolledtreeview1.insert('', 'end', text=str(k),\ 496 | values=( str(row[0]).split(" ")[-1], row[1], row[3], round(row[2],2), round(row[4],3))) 497 | k= k+1 498 | self.numberOfExecutions= n 499 | 500 | 501 | def insertDataTrades(self, trades): 502 | n= len(trades) 503 | if n>self.numberOfTrades: 504 | newTrades= trades[-(n-self.numberOfTrades):] 505 | k= self.numberOfTrades 506 | for row in newTrades: 507 | self.Scrolledtreeview2.insert('', 'end', text=str(k),\ 508 | values=( str(row[0]).split(" ")[-1], str(row[1]).split(" ")[-1], row[2], \ 509 | row[5], round(row[3],2), round(row[4],2), round(row[6],3))) 510 | k= k+1 511 | self.numberOfTrades= n 512 | 513 | def insertOpenData(self, openedPositions): 514 | self.Scrolledtreeview1.delete(*self.Scrolledtreeview1.get_children()) 515 | for i,row in enumerate(openedPositions): 516 | self.Scrolledtreeview1.insert('', 'end', text=str(i),\ 517 | values=( str(row[0]).split(" ")[-1], row[1], \ 518 | row[2], round(row[3], 2), round(row[4], 2)), tags=('new')) 519 | 520 | def saveTradeHistory(self, strategy): 521 | if self.CheckVar: 522 | data= strategy.showExecutions() 523 | if len(data)>0: 524 | data.to_csv("TradingHistory.csv", index=False) 525 | else: 526 | with open("TradingHistory.csv", 'w'): 527 | pass 528 | 529 | 530 | def main(self): 531 | period = 10 532 | pair = "USDT_BTC" 533 | lengthMA = 50 534 | error=False 535 | self.stopRunning= False 536 | self.numberOfTrades= 0 537 | try: 538 | data = BotGetData(pair, period) 539 | historical = data.historicalData 540 | except Exception as e: 541 | historical = [] 542 | messagebox.showinfo("Error", e) 543 | error= True 544 | try: 545 | stopLossEdge= float(self.StopLossEdge.get()) 546 | except: 547 | messagebox.showinfo("Error", "Wrong StopLoss input. Must be integer.") 548 | error= True 549 | try: 550 | entryEdge= float(self.EntryEdge.get()) 551 | entryEdge= 0 552 | except: 553 | messagebox.showinfo("Error", "Wrong StopLoss input. Must be numeric.") 554 | error= True 555 | try: 556 | openPosLimit= int(self.OpenTradesLimit.get()) 557 | if openPosLimit<=0: 558 | messagebox.showinfo("Error", "Wrong openPosLimit input. Must be integer>0.") 559 | openPosLimit= 1 560 | except: 561 | messagebox.showinfo("Error", "Wrong openPosLimit input. Must be integer.") 562 | error= True 563 | try: 564 | timePosEdge= int(self.Maintenance.get()) 565 | if timePosEdge<0: 566 | messagebox.showinfo("Error", "Wrong Maintenance input. Must be integer>=0.") 567 | timePosEdge= 1 568 | except: 569 | messagebox.showinfo("Error", "Wrong Maintenance input. Must be integer.") 570 | error= True 571 | if not error: 572 | prices = historical.Price.tolist() 573 | if (len(historical) > lengthMA): 574 | prices = prices[-lengthMA:] 575 | else: 576 | print("Not enough historical data for MA=" + str(lengthMA)) 577 | lengthMA = len(prices) 578 | 579 | self.strategy = BotStrategy(prices=prices, pair=pair, lengthMA=lengthMA, \ 580 | openPosLimit=openPosLimit, stopLossEdge=stopLossEdge, \ 581 | entryEdge=entryEdge, timePosEdge=timePosEdge) 582 | while True: 583 | try: 584 | if self.stopRunning: 585 | self.startTrading = False 586 | self.saveTradeHistory(strategy=self.strategy) 587 | self.Scrolledtreeview1.delete(*self.Scrolledtreeview1.get_children()) 588 | self.Scrolledtreeview2.delete(*self.Scrolledtreeview2.get_children()) 589 | self.strategy.closeAll() 590 | self.strategy.clearExecutions() 591 | break 592 | data.updateData() 593 | lastPairPrice = data.lastPrice 594 | prices.append(lastPairPrice) 595 | prices = prices[-lengthMA:] 596 | self.strategy.tick(lastPairPrice, self.startTrading) 597 | executions = self.strategy.allExecutions.execData 598 | trades = self.strategy.allTrades.tradesData 599 | histDataUpdated = chartHorizon(histDataUpdated=data.historicalData, interval=15) 600 | openedPositions= self.strategy.openedPositions 601 | self.insertDataTrades(trades) 602 | self.insertOpenData(openedPositions) 603 | self.tradesCount.delete(1.0, END) 604 | self.tradesCount.insert(END, str(len(trades))) 605 | self.totalPnl.delete(1.0, END) 606 | self.totalPnl.insert(END, str(round(self.strategy.totalPnl,1))) 607 | if self.closeAll: 608 | self.strategy.closeAll() 609 | self.saveTradeHistory(strategy=self.strategy) 610 | if self.showChart: 611 | self.liveChartObject.botLiveChart(x=histDataUpdated.Date, y=histDataUpdated.Price, \ 612 | tradesLive=executions, lastTradePnl=self.strategy.lastTradePnl, \ 613 | totalPnl=self.strategy.totalPnl, percentChange=data.percentChange) 614 | self.root.update() 615 | 616 | except Exception as e: 617 | messagebox.showinfo("Error", str(e)) 618 | self.strategy.closeAll() 619 | self.saveTradeHistory(strategy=self.strategy) 620 | break 621 | 622 | 623 | vp_start_gui() 624 | --------------------------------------------------------------------------------