· 6 years ago · Dec 04, 2019, 08:02 PM
1import json
2import pandas as pd
3import re
4import tkinter as tk
5from tkinter import ttk
6import urllib.request
7
8import matplotlib
9
10matplotlib.use('TkAgg')
11import matplotlib.animation as animation
12import matplotlib.dates as mdates
13from mpl_finance import candlestick_ohlc
14from matplotlib import pyplot as plt
15from matplotlib import style
16import matplotlib.ticker as mticker
17from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg,
18 NavigationToolbar2Tk)
19import numpy as np
20
21style.use('ggplot')
22
23f = plt.figure()
24
25TITLE_FONT = ("Helvetica", 11)
26
27NORM_FONT = ("Helvetica", 10)
28
29
30DataPace = '1d'
31paneCount = 1
32chartLoad = True
33refreshRate = 100
34resampleSize = '15Min'
35candleWidth = .008
36exchange = 'BTC-e'
37programName = 'btce'
38topIndicator = "none"
39bottomIndicator = "none"
40middleIndicators = "none"
41EMAs = []
42SMAs = []
43
44darkColor = '#183A54'
45lightColor = '#00A3E0'
46
47# OVER 9000!!! lol.
48DatCounter = 9000
49
50
51def popupmsg(msg):
52 popup = tk.Tk()
53
54 def leavemini():
55 popup.destroy()
56
57 popup.wm_title("!")
58
59 label = ttk.Label(popup, text=msg, font=NORM_FONT)
60 label.pack(side="top", fill="x", pady=10)
61 B1 = ttk.Button(popup, text="Okay", command=leavemini)
62 B1.pack()
63
64 popup.mainloop()
65
66
67def addTopIndicator(what):
68 global topIndicator
69 global DatCounter
70
71 if DataPace == "tick":
72 popupmsg("Indicators in Tick Data not available, choose 1 minute tf if you want short term.")
73
74 if what == "none":
75 topIndicator = what
76 DatCounter = 9000
77
78 elif what == "rsi":
79 rsiQ = tk.Tk()
80 rsiQ.wm_title("Periods?")
81 label = ttk.Label(rsiQ,
82 text="Choose how many periods you want each RSI calculation to consider.\nThese periods are contingent on your current time settings on the chart. 1 period = 1 OHLC candlestick.",
83 font=NORM_FONT)
84 label.pack(side="top", fill="x", pady=10)
85
86 e = ttk.Entry(rsiQ)
87 e.insert(0, 14)
88 e.pack()
89 e.focus_set()
90
91 def callback():
92 periods = (e.get())
93 group = []
94 group.append("rsi")
95 group.append(periods)
96 topIndicator = group
97 DatCounter = 9000
98 print("set top indicator to", group)
99 rsiQ.destroy()
100
101 b = ttk.Button(rsiQ, text="Submit", width=10, command=callback)
102 b.pack()
103
104 tk.mainloop()
105
106 elif what == "macd":
107 topIndicator = "macd"
108 DatCounter = 9000
109
110
111def addMiddleIndicator(what):
112 global middleIndicators
113 global DatCounter
114 if DataPace == "tick":
115 popupmsg("Indicators in Tick Data not available, choose 1 minute tf if you want short term.")
116
117 if what != "none":
118 if middleIndicators == "none":
119
120 if what == "sma":
121 midIQ = tk.Tk()
122 midIQ.wm_title("Periods?")
123 label = ttk.Label(midIQ,
124 text="Choose how many periods you want each SMA calculation to consider.\nThese periods are contingent on your current time settings on the chart.\n1 period = 1 OHLC candlestick.",
125 font=NORM_FONT)
126 label.pack(side="top", fill="x", pady=10)
127 e = ttk.Entry(midIQ)
128 e.insert(0, 10)
129 e.pack()
130 e.focus_set()
131
132 def callback():
133 middleIndicators = []
134 periods = (e.get())
135 group = []
136 group.append("sma")
137 group.append(int(periods))
138 middleIndicators.append(group)
139 DatCounter = 9000
140 print("mid indicator", middleIndicators)
141 midIQ.destroy()
142
143 b = ttk.Button(midIQ, text="Submit", width=10, command=callback)
144 b.pack()
145 tk.mainloop()
146
147 if what == "ema":
148 midIQ = tk.Tk()
149 midIQ.wm_title("Periods?")
150 label = ttk.Label(midIQ,
151 text="Choose how many periods you want each EMA calculation to consider.\nThese periods are contingent on your current time settings on the chart.\n1 period = 1 OHLC candlestick.",
152 font=NORM_FONT)
153 label.pack(side="top", fill="x", pady=10)
154 e = ttk.Entry(midIQ)
155 e.insert(0, 10)
156 e.pack()
157 e.focus_set()
158
159 def callback():
160 middleIndicators = []
161 periods = (e.get())
162 group = []
163 group.append("ema")
164 group.append(int(periods))
165 middleIndicators.append(group)
166 DatCounter = 9000
167 print("mid indicator", middleIndicators)
168 midIQ.destroy()
169
170 b = ttk.Button(midIQ, text="Submit", width=10, command=callback)
171 b.pack()
172 tk.mainloop()
173
174
175 else:
176 if what == "sma":
177 midIQ = tk.Tk()
178 midIQ.wm_title("Periods?")
179 label = ttk.Label(midIQ,
180 text="Choose how many periods you want each SMA calculation to consider.\nThese periods are contingent on your current time settings on the chart.\n1 period = 1 OHLC candlestick.",
181 font=NORM_FONT)
182 label.pack(side="top", fill="x", pady=10)
183 e = ttk.Entry(midIQ)
184 e.insert(0, 10)
185 e.pack()
186 e.focus_set()
187
188 def callback():
189 periods = (e.get())
190 group = []
191 group.append("sma")
192 group.append(int(periods))
193 middleIndicators.append(group)
194 DatCounter = 9000
195 print("mid indicator", middleIndicators)
196 midIQ.destroy()
197
198 b = ttk.Button(midIQ, text="Submit", width=10, command=callback)
199 b.pack()
200 tk.mainloop()
201
202 if what == "ema":
203 midIQ = tk.Tk()
204 midIQ.wm_title("Periods?")
205 label = ttk.Label(midIQ,
206 text="Choose how many periods you want each EMA calculation to consider.\nThese periods are contingent on your current time settings on the chart.\n1 period = 1 OHLC candlestick.",
207 font=NORM_FONT)
208 label.pack(side="top", fill="x", pady=10)
209 e = ttk.Entry(midIQ)
210 e.insert(0, 10)
211 e.pack()
212 e.focus_set()
213
214 def callback():
215 periods = (e.get())
216 group = []
217 group.append("ema")
218 group.append(int(periods))
219 middleIndicators.append(group)
220 DatCounter = 9000
221 print("mid indicator", middleIndicators)
222 midIQ.destroy()
223
224 b = ttk.Button(midIQ, text="Submit", width=10, command=callback)
225 b.pack()
226 tk.mainloop()
227 else:
228 middleIndicators = "none"
229
230
231def addBottomIndicator(what):
232 global bottomIndicator
233 global DatCounter
234
235 if DataPace == "tick":
236 popupmsg("Indicators in Tick Data not available, choose 1 minute tf if you want short term.")
237
238 if what == "none":
239 bottomIndicator = what
240 DatCounter = 9000
241
242 elif what == "rsi":
243 rsiQ = tk.Tk()
244 rsiQ.wm_title("Periods?")
245 label = ttk.Label(rsiQ,
246 text="Choose how many periods you want each RSI calculation to consider.\nThese periods are contingent on your current time settings on the chart. 1 period = 1 OHLC candlestick.",
247 font=NORM_FONT)
248 label.pack(side="top", fill="x", pady=10)
249
250 e = ttk.Entry(rsiQ)
251 e.insert(0, 14)
252 e.pack()
253 e.focus_set()
254
255 def callback():
256 periods = (e.get())
257 group = []
258 group.append("rsi")
259 group.append(periods)
260 bottomIndicator = group
261 DatCounter = 9000
262 print("set top indicator to", group)
263 rsiQ.destroy()
264
265 b = ttk.Button(rsiQ, text="Submit", width=10, command=callback)
266 b.pack()
267
268 tk.mainloop()
269
270 elif what == "macd":
271 bottomIndicator = "macd"
272 DatCounter = 9000
273
274
275def tutorial():
276 def leavemini(what):
277 what.destroy()
278
279 def page2():
280 leavemini(tut)
281 tut2 = tk.Tk()
282
283 def leavemini2(what):
284 what.destroy()
285
286 def page3():
287 leavemini2(tut2)
288 tut3 = tk.Tk()
289 tut3.wm_title("part 3!")
290
291 label = ttk.Label(tut3, text="Part 3", font=NORM_FONT)
292 label.pack(side="top", fill="x", pady=10)
293 B1 = ttk.Button(tut3, text="Done!", command=tut3.destroy)
294 B1.pack()
295 tut3.mainloop()
296
297 tut2.wm_title("part 2!")
298
299 label = ttk.Label(tut2, text="Part 2", font=NORM_FONT)
300 label.pack(side="top", fill="x", pady=10)
301 B1 = ttk.Button(tut2, text="next!", command=page3)
302 B1.pack()
303
304 tut.mainloop()
305
306 tut = tk.Tk()
307 tut.wm_title("Tutorial")
308 label = ttk.Label(tut, text="What do you need help with?", font=NORM_FONT)
309 label.pack(side="top", fill="x", pady=10)
310 B1 = ttk.Button(tut, text="Overview of the application", command=page2)
311 B1.pack()
312
313 B2 = ttk.Button(tut, text="How do I trade here?", command=lambda: popupmsg('Not supported just yet!'))
314 B2.pack()
315
316 B3 = ttk.Button(tut, text="Indicator questions/help", command=lambda: popupmsg('Not supported just yet!'))
317 B3.pack()
318
319 tut.mainloop()
320
321
322def changeSampleSize(size, width):
323 global resampleSize
324 global DatCounter
325 global candleWidth
326
327 if DataPace == '7d' and size == '1Min':
328 popupmsg("Too much data chosen, choose a smaller Data Time Frame or higher OHLC Interval!")
329
330 if DataPace == 'tick':
331 popupmsg("You are currently viewing tick data, not OHLC. Choose a larger Data Time Frame!")
332
333 else:
334 resampleSize = size
335 DatCounter = 9000
336 candleWidth = width
337
338
339def changeExchange(toWhat, pn):
340 global exchange
341 global DatCounter
342 global programName
343 exchange = toWhat
344 programName = pn
345 DatCounter = 9000
346
347
348def changeTimeFrame(tf):
349 global DataPace
350 global DatCounter
351 if tf == '7d' and resampleSize == '1Min':
352 popupmsg("Too much data chosen, choose a smaller data time frame or higher OHLC Interval!")
353 else:
354 DataPace = tf
355 DatCounter = 9000
356
357
358def loadChart(run):
359 global chartLoad
360
361 if run == 'start':
362 chartLoad = True
363 elif run == 'stop':
364 chartLoad = False
365
366
367# ... I know... This is my work around for cx_freeze saying quit is not defined.
368def quit():
369 quit()
370
371
372def animate(i):
373 global refreshRate
374 global DatCounter
375
376 def moving_average(x, n, type='simple'):
377
378 x = np.asarray(x)
379 if type == 'simple':
380 weights = np.ones(n)
381 else:
382 weights = np.exp(np.linspace(-1., 0., n))
383
384 weights /= weights.sum()
385
386 a = np.convolve(x, weights, mode='full')[:len(x)]
387 a[:n] = a[n]
388 return a
389
390 def computeMACD(x, slow=26, fast=12, location="bottom"):
391 """
392 compute the MACD (Moving Average Convergence/Divergence) using a fast and slow exponential moving avg'
393 return value is emaslow, emafast, macd which are len(x) arrays
394 """
395 values = {'key': 1, 'prices': x}
396
397 url = "http://seaofbtc.com/api/indicator/macd"
398 data = urllib.parse.urlencode(values)
399 data = data.encode('utf-8')
400 req = urllib.request.Request(url, data)
401 resp = urllib.request.urlopen(req)
402 respData = resp.read()
403 newData = str(respData).replace("b", "").replace('[', '').replace(']', '').replace("'", '')
404
405 # print(newData)
406
407 split = newData.split('::')
408
409 macd = split[0]
410 ema9 = split[1]
411 hist = split[2]
412
413 macd = macd.split(", ")
414 ema9 = ema9.split(", ")
415 hist = hist.split(", ")
416
417 try:
418 macd = [float(i) for i in macd]
419 except Exception as e:
420 print(str(e) + " macd")
421 try:
422 ema9 = [float(i) for i in ema9]
423 except Exception as e:
424 print(str(e) + " ema9")
425 try:
426 hist = [float(i) for i in hist]
427 except Exception as e:
428 print(str(e) + " hist")
429
430 print("call!!!")
431
432 if location == "top":
433 try:
434 a0.plot(OHLC['MPLDates'][fast:], macd[fast:], color=darkColor, lw=2)
435 a0.plot(OHLC['MPLDates'][fast:], ema9[fast:], color=lightColor, lw=1)
436 a0.fill_between(OHLC['MPLDates'][fast:], hist[fast:], 0, alpha=0.5, facecolor=darkColor,
437 edgecolor=darkColor)
438 datLabel = "MACD"
439 a0.set_ylabel(datLabel)
440 except Exception as e:
441 print(str(e))
442 topIndicator = "none"
443
444
445 elif location == "bottom":
446 try:
447 a3.plot(OHLC['MPLDates'][fast:], macd[fast:], color=darkColor, lw=2)
448 a3.plot(OHLC['MPLDates'][fast:], ema9[fast:], color=lightColor, lw=1)
449 a3.fill_between(OHLC['MPLDates'][fast:], hist[fast:], 0, alpha=0.5, facecolor=darkColor,
450 edgecolor=darkColor)
451 datLabel = "MACD"
452 a3.set_ylabel(datLabel)
453 except Exception as e:
454 print(str(e))
455 bottomIndicator = "none"
456
457 def rsiIndicator(priceData, location="top"):
458
459 if location == "top":
460 values = {'key': 1, 'prices': priceData, 'periods': topIndicator[1]}
461
462 elif location == "bottom":
463 values = {'key': 1, 'prices': priceData, 'periods': bottomIndicator[1]}
464
465 url = "http://seaofbtc.com/api/indicator/rsi"
466 data = urllib.parse.urlencode(values)
467 data = data.encode('utf-8')
468 req = urllib.request.Request(url, data)
469 resp = urllib.request.urlopen(req)
470 respData = resp.read()
471 newData = str(respData).replace("b", "").replace('[', '').replace(']', '').replace("'", '')
472 priceList = newData.split(', ')
473 rsiData = [float(i) for i in priceList]
474
475 print("call!!!")
476
477 if location == "top":
478 a0.plot_date(OHLC['MPLDates'], rsiData, lightColor, label="RSI")
479 datLabel = "RSI(" + str(topIndicator[1]) + ")"
480 a0.set_ylabel(datLabel)
481
482 elif location == "bottom":
483 a3.plot_date(OHLC['MPLDates'], rsiData, lightColor, label="RSI")
484 datLabel = "RSI(" + str(bottomIndicator[1]) + ")"
485 a3.set_ylabel(datLabel)
486
487 print(exchange)
488
489 if chartLoad:
490 if paneCount == 1:
491 if DataPace == 'tick':
492 try:
493 if exchange == 'BTC-e':
494 a = plt.subplot2grid((6, 4), (0, 0), rowspan=5, colspan=4)
495 a2 = plt.subplot2grid((6, 4), (5, 0), rowspan=1, colspan=4, sharex=a)
496
497 dataLink = 'https://btc-e.com/api/3/trades/btc_usd?limit=2000'
498
499 data = urllib.request.urlopen(dataLink)
500 data = data.readall().decode('utf-8')
501 data = json.loads(data)
502 data = data["btc_usd"]
503 data = pd.DataFrame(data)
504
505 data["datestamp"] = np.array(data['timestamp']).astype('datetime64[s]')
506 allDates = data["datestamp"].tolist()
507
508 buys = data[(data['type'] == 'bid')]
509 # buys["datestamp"] = np.array(buys['timestamp']).astype('datetime64[s]')
510 buyDates = (buys["datestamp"]).tolist()
511
512 sells = data[(data['type'] == 'ask')]
513 # sells["datestamp"] = np.array(sells['timestamp']).astype('datetime64[s]')
514 sellDates = (sells["datestamp"]).tolist()
515
516 volume = data["amount"]
517
518 a.clear()
519
520 a.plot_date(buyDates, buys["price"], '#00A3E0', label="buys")
521 a.plot_date(sellDates, sells["price"], '#183A54', label="sells")
522 a2.fill_between(allDates, 0, volume, facecolor='#183A54')
523 a.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,
524 ncol=2, borderaxespad=0.)
525
526 a.xaxis.set_major_locator(mticker.MaxNLocator(5))
527 a.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d %H:%M'))
528 plt.setp(a.get_xticklabels(), visible=False)
529
530 title = exchange + ' Tick Data\nLast Price: ' + str(data["price"][0])
531 a.set_title(title)
532 priceData = data["price"].apply(float).tolist()
533
534 if exchange == 'Bitstamp':
535 a = plt.subplot2grid((6, 4), (0, 0), rowspan=5, colspan=4)
536 a2 = plt.subplot2grid((6, 4), (5, 0), rowspan=1, colspan=4, sharex=a)
537
538 dataLink = 'https://www.bitstamp.net/api/transactions/'
539 data = urllib.request.urlopen(dataLink)
540 data = data.readall().decode('utf-8')
541 data = json.loads(data)
542 data = pd.DataFrame(data)
543 data["datestamp"] = np.array(data['date'].apply(int)).astype('datetime64[s]')
544 datestamps = data["datestamp"].tolist()
545 volume = data["amount"].apply(float).tolist()
546
547 a.clear()
548
549 a.plot_date(datestamps, data["price"], '#183A54')
550
551 a2.fill_between(datestamps, 0, volume, facecolor='#183A54')
552
553 a.xaxis.set_major_locator(mticker.MaxNLocator(5))
554 a.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d %H:%M'))
555 plt.setp(a.get_xticklabels(), visible=False)
556
557 title = exchange + ' Tick Data\nLast Price: ' + str(data["price"][0])
558 a.set_title(title)
559 priceData = data["price"].apply(float).tolist()
560
561 if exchange == 'Bitfinex':
562 a = plt.subplot2grid((6, 4), (0, 0), rowspan=5, colspan=4)
563 a2 = plt.subplot2grid((6, 4), (5, 0), rowspan=1, colspan=4, sharex=a)
564
565 dataLink = 'https://api.bitfinex.com/v1/trades/btcusd?limit=2000'
566
567 data = urllib.request.urlopen(dataLink)
568 data = data.readall().decode('utf-8')
569 data = json.loads(data)
570 data = pd.DataFrame(data)
571
572 volume = data["amount"].apply(float).tolist()
573
574 # print(data)
575
576 data["datestamp"] = np.array(data['timestamp']).astype('datetime64[s]')
577 allDates = data["datestamp"].tolist()
578
579 buys = data[(data['type'] == 'buy')]
580 # buys["datestamp"] = np.array(buys['timestamp']).astype('datetime64[s]')
581 buyDates = (buys["datestamp"]).tolist()
582
583 sells = data[(data['type'] == 'sell')]
584 # sells["datestamp"] = np.array(sells['timestamp']).astype('datetime64[s]')
585 sellDates = (sells["datestamp"]).tolist()
586
587 a.clear()
588
589 a.plot_date(buyDates, buys["price"], lightColor, label="buys")
590 a.plot_date(sellDates, sells["price"], darkColor, label="sells")
591 a2.fill_between(allDates, 0, volume, facecolor='#183A54')
592
593 a.xaxis.set_major_locator(mticker.MaxNLocator(5))
594 a.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d %H:%M'))
595 plt.setp(a.get_xticklabels(), visible=False)
596 a.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,
597 ncol=2, borderaxespad=0.)
598
599 title = exchange + ' Tick Data\nLast Price: ' + str(data["price"][0])
600 a.set_title(title)
601 priceData = data["price"].apply(float).tolist()
602
603 if exchange == 'Huobi':
604 try:
605 a = plt.subplot2grid((6, 4), (0, 0), rowspan=6, colspan=4)
606
607 data = urllib.request.urlopen(
608 'http://seaofbtc.com/api/basic/price?key=1&tf=1d&exchange=' + programName).read()
609
610 data = str(data).replace('b', '').replace("'", '')
611 data = json.loads(data)
612
613 dateStamp = np.array(data[0]).astype('datetime64[s]')
614 dateStamp = dateStamp.tolist()
615 print('here')
616
617 df = pd.DataFrame({'Datetime': dateStamp})
618
619 df['Price'] = data[1]
620
621 df['Volume'] = data[2]
622 df['Symbol'] = "BTCUSD"
623 df['MPLDate'] = df['Datetime'].apply(lambda date: mdates.date2num(date.to_pydatetime()))
624 df = df.set_index('Datetime')
625 lastPrice = df['Price'][-1]
626
627 a.plot_date(df['MPLDate'][-4500:], df['Price'][-4500:], lightColor, label="price")
628
629 a.xaxis.set_major_locator(mticker.MaxNLocator(5))
630 a.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d %H:%M'))
631
632 title = exchange + ' Tick Data\nLast Price: ' + str(lastPrice)
633 a.set_title(title)
634 priceData = df['Price'].apply(float).tolist()
635 except Exception as e:
636 print(str(e))
637
638 except:
639 DatCounter = 9000
640 ###### BEGIN NON-TICK GRAPHING#################################################################################
641
642 else:
643
644 if DatCounter > 12:
645 try:
646 if exchange == 'Huobi':
647 if topIndicator != "none":
648
649 a = plt.subplot2grid((6, 4), (1, 0), rowspan=5, colspan=4)
650 a0 = plt.subplot2grid((6, 4), (0, 0), sharex=a, rowspan=1, colspan=4)
651 else:
652 a = plt.subplot2grid((6, 4), (0, 0), rowspan=6, colspan=4)
653
654 else:
655 if topIndicator != "none" and bottomIndicator != "none":
656 # actual price chart.
657 a = plt.subplot2grid((6, 4), (1, 0), rowspan=3, colspan=4)
658 # volume!
659 a2 = plt.subplot2grid((6, 4), (4, 0), sharex=a, rowspan=1, colspan=4)
660 # top indicator
661 a0 = plt.subplot2grid((6, 4), (0, 0), sharex=a, rowspan=1, colspan=4)
662 # bottom indicator
663 a3 = plt.subplot2grid((6, 4), (5, 0), sharex=a, rowspan=1, colspan=4)
664
665 elif topIndicator != "none":
666 a = plt.subplot2grid((6, 4), (1, 0), rowspan=4, colspan=4)
667 a2 = plt.subplot2grid((6, 4), (5, 0), sharex=a, rowspan=1, colspan=4)
668 a0 = plt.subplot2grid((6, 4), (0, 0), sharex=a, rowspan=1, colspan=4)
669 elif bottomIndicator != "none":
670 a = plt.subplot2grid((6, 4), (0, 0), rowspan=4, colspan=4)
671 a2 = plt.subplot2grid((6, 4), (4, 0), sharex=a, rowspan=1, colspan=4)
672 # a0 = plt.subplot2grid((6,4), (0,0), sharex=a, rowspan=1, colspan=4)
673 a3 = plt.subplot2grid((6, 4), (5, 0), sharex=a, rowspan=1, colspan=4)
674
675 else:
676 a = plt.subplot2grid((6, 4), (0, 0), rowspan=5, colspan=4)
677 a2 = plt.subplot2grid((6, 4), (5, 0), sharex=a, rowspan=1, colspan=4)
678
679 print('http://seaofbtc.com/api/basic/price?key=1&tf=' + DataPace + '&exchange=' + programName)
680 data = urllib.request.urlopen(
681 'http://seaofbtc.com/api/basic/price?key=1&tf=' + DataPace + '&exchange=' + programName).read()
682
683 data = str(data).replace('b', '').replace("'", '')
684 data = json.loads(data)
685
686 dateStamp = np.array(data[0]).astype('datetime64[s]')
687 dateStamp = dateStamp.tolist()
688
689 df = pd.DataFrame({'Datetime': dateStamp})
690 df['Price'] = data[1]
691 df['Volume'] = data[2]
692 df['Symbol'] = "BTCUSD"
693 df['MPLDate'] = df['Datetime'].apply(lambda date: mdates.date2num(date.to_pydatetime()))
694 df = df.set_index('Datetime')
695
696 OHLC = df['Price'].resample(resampleSize, how='ohlc')
697 OHLC = OHLC.dropna()
698
699 volumeData = df['Volume'].resample(resampleSize, how={'volume': 'sum'})
700
701 OHLC['dateCopy'] = OHLC.index
702 OHLC['MPLDates'] = OHLC['dateCopy'].apply(lambda date: mdates.date2num(date.to_pydatetime()))
703 del OHLC['dateCopy']
704
705 volumeData['dateCopy'] = volumeData.index
706 volumeData['MPLDates'] = volumeData['dateCopy'].apply(
707 lambda date: mdates.date2num(date.to_pydatetime()))
708 del volumeData['dateCopy']
709
710 priceData = OHLC['close'].apply(float).tolist()
711
712 a.clear()
713 if middleIndicators != "none":
714 for eachMA in middleIndicators:
715 ewma = pd.stats.moments.ewma
716 # print("type:",eachMA[0],"periods:",eachMA[1])
717 if eachMA[0] == "sma":
718 sma = pd.rolling_mean(OHLC["close"], eachMA[1])
719 label = str(eachMA[1]) + " SMA"
720 a.plot(OHLC['MPLDates'], sma, label=label)
721 if eachMA[0] == "ema":
722 ewma = pd.stats.moments.ewma
723 label = str(eachMA[1]) + " EMA"
724 a.plot(OHLC['MPLDates'], ewma(OHLC["close"], eachMA[1]), label=label)
725
726 # a.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,
727 # ncol=2, borderaxespad=0.)
728
729 a.legend(loc=0)
730
731 if topIndicator[0] == "rsi":
732 rsiIndicator(priceData, "top")
733 elif topIndicator == "macd":
734 try:
735 computeMACD(priceData, location="top")
736 except:
737 print("failed macd")
738
739 if bottomIndicator[0] == "rsi":
740 rsiIndicator(priceData, "bottom")
741 elif bottomIndicator == "macd":
742 try:
743 computeMACD(priceData, location="bottom")
744 except:
745 print("failed macd")
746
747 csticks = candlestick_ohlc(a, OHLC[['MPLDates', 'open', 'high', 'low', 'close']].values,
748 width=candleWidth, colorup=lightColor, colordown=darkColor)
749 a.set_ylabel("price")
750 if exchange != 'Huobi':
751 a2.fill_between(volumeData['MPLDates'], 0, volumeData['volume'],
752 facecolor='#183A54') # , alpha=.4)
753 a2.set_ylabel("volume")
754
755 a.xaxis.set_major_locator(mticker.MaxNLocator(3))
756 a.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d %H:%M'))
757
758 plt.setp(a.get_xticklabels(), visible=False)
759
760 if topIndicator != "none":
761 plt.setp(a0.get_xticklabels(), visible=False)
762
763 if bottomIndicator != "none":
764 plt.setp(a2.get_xticklabels(), visible=False)
765
766 x = (len(OHLC['close'])) - 1
767
768 if DataPace == '1d':
769 title = exchange + ' 1 Day Data with ' + resampleSize + ' Bars\nLast Price: ' + str(
770 OHLC['close'][x])
771 if DataPace == '3d':
772 title = exchange + ' 3 Day Data with ' + resampleSize + ' Bars\nLast Price: ' + str(
773 OHLC['close'][x])
774 if DataPace == '7d':
775 title = exchange + ' 7 Day Data with ' + resampleSize + ' Bars\nLast Price: ' + str(
776 OHLC['close'][x])
777
778 if topIndicator != "none":
779 a0.set_title(title)
780 else:
781 a.set_title(title)
782 print('NewGraph!')
783
784 DatCounter = 0
785
786
787
788
789
790
791
792
793
794 except Exception as e:
795 print(str(e), "main animate non tick")
796 DatCounter = 9000
797
798 else:
799 DatCounter += 1
800
801
802class SeaofBTCapp(tk.Tk):
803 def __init__(self, *args, **kwargs):
804
805 tk.Tk.__init__(self, *args, **kwargs)
806
807 # menubar = tk.Menu(tk.Tk)
808
809 style = ttk.Style()
810 style.layout("Button", [
811 ("Menubutton.background", None),
812 ("Menubutton.foreground", None),
813 ("Menubutton.button", {"children":
814 [("Menubutton.focus", {"children":
815 [("Menubutton.padding", {"children":
816 [("Menubutton.label",
817 {"side": "left",
818 "expand": 1})]
819 })]
820 })]
821 }),
822 ])
823
824 style.layout("TMenubutton", [
825 ("Menubutton.background", None),
826 ("Menubutton.button", {"children":
827 [("Menubutton.focus", {"children":
828 [("Menubutton.padding", {"children":
829 [("Menubutton.label",
830 {"side": "left",
831 "expand": 1})]
832 })]
833 })]
834 }),
835 ])
836
837 # the container is where we'll stack a bunch of frames
838 # on top of each other, then the one we want visible
839 # will be raised above the others
840 container = tk.Frame(self, width=1280, height=720)
841 container.pack(side="top", fill="both", expand=True)
842 container.grid_rowconfigure(0, weight=1)
843 container.grid_columnconfigure(0, weight=1)
844
845 menubar = tk.Menu(container)
846 filemenu = tk.Menu(menubar, tearoff=0)
847 filemenu.add_command(label="Save settings", command=lambda: popupmsg('Not supported just yet!'))
848 filemenu.add_separator()
849 filemenu.add_command(label="Exit", command=quit)
850 menubar.add_cascade(label="File", menu=filemenu)
851
852 helpmenu = tk.Menu(menubar, tearoff=0)
853 helpmenu.add_command(label="Tutorial", command=tutorial)
854 menubar.add_cascade(label="Help", menu=helpmenu)
855
856 tk.Tk.config(self, menu=menubar)
857 # editmenu.add_separator()
858 # menubar.add_cascade(label="Edit", menu=filemenu)
859 # container.title('test')
860
861 self.frames = {}
862 for F in (StartPage, dashboard):
863 frame = F(container, self)
864 self.frames[F] = frame
865 # put all of the pages in the same location;
866 # the one on the top of the stacking order
867 # will be the one that is visible.
868 frame.grid(row=0, column=0, sticky="nsew")
869
870 self.show_frame(StartPage)
871
872 try:
873 tk.Tk.iconbitmap(self, default='clienticon.ico')
874 tk.Tk.wm_title(self, "Sea of BTC Client")
875 except Exception as e:
876 print(str(e))
877
878 def show_frame(self, c):
879 '''Show a frame for the given class'''
880 frame = self.frames[c]
881 frame.tkraise()
882
883
884class StartPage(tk.Frame):
885 def __init__(self, parent, controller):
886 tk.Frame.__init__(self, parent)
887 label = tk.Label(self, text="""The Sea of BTC trading client is a client intended to help traders
888 interact with their exchanges. We do this by allowing you to enter
889 your API keys into the program. We, as in Sea of BTC, never
890 see your API information. The program may save them locally, however,
891 to make things easier on you. Keep in mind that it is a fantastic idea
892 to enable 'IP Whitelisting' if your exchange supports it, and only allow
893 trading via your specific IP address. On most exchanges, even if someone
894 was to acquire your API key, withdrawals are not possible. Some still
895 give the option, so make sure this is turned OFF if your exchange allows it.
896 Sea of BTC makes no promise of warranty, satisfaction, performance, or
897 anything else. Understand that your use of this client is completely
898 at your own risk.""", font=TITLE_FONT)
899
900 label.pack(side="top", fill="x", pady=10)
901
902 button1 = ttk.Button(self, text="Agree",
903 command=lambda: controller.show_frame(dashboard))
904 button2 = ttk.Button(self, text="Disagree",
905 command=quit)
906 button1.pack()
907 button2.pack()
908
909
910### Deprecated, lost the point of needing this page leaving mostly for future reference.
911##class HomePage(tk.Frame):
912## def __init__(self, parent, controller):
913## tk.Frame.__init__(self, parent)
914##
915## label = tk.Label(self, text="Sea of BTC Client", font=TITLE_FONT)
916## label.pack(side="top", fill="x", pady=10)
917## label = tk.Label(self, text="Choose your Exchange", font=NORM_FONT)
918## label.pack(side="top", fill="x", pady=10)
919##
920##
921## button = ttk.Button(self, text="BTC-e",
922## command=lambda: controller.show_frame(BTCe_main))
923## button.pack(pady=10)
924##
925## button = ttk.Button(self, text="*NOT ACTIVE* Bitstamp",
926## command=lambda: controller.show_frame(StartPage))
927## button.pack(pady=10)
928##
929## button = ttk.Button(self, text="*NOT ACTIVE* Bitfinex",
930## command=lambda: controller.show_frame(StartPage))
931## button.pack(pady=10)
932##
933## button = ttk.Button(self, text="*NOT ACTIVE* Huobi",
934## command=lambda: controller.show_frame(StartPage))
935## button.pack(pady=10)
936
937
938class dashboard(tk.Frame):
939
940 def __init__(self, parent, controller):
941 tk.Frame.__init__(self, parent)
942
943 # title and leading text #
944 label = tk.Label(self, text="Dashboard", font=TITLE_FONT)
945 label.pack(side="top", fill="x", pady=10)
946 if float(Version) < float(latestVersion[0]):
947 label = tk.Label(self, text="There is a new version of the client out! SeaofBTC.com/bitcoin-trading-client",
948 font=NORM_FONT)
949 label.pack(side="top", fill="x", pady=10)
950
951 # setting up the frame #
952 canvas = FigureCanvasTkAgg(f, self)
953 canvas.draw()
954 canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=1)
955
956 toolbar = NavigationToolbar2Tk(canvas, self)
957 toolbar.update()
958 canvas._tkcanvas.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=1)
959
960 mb = ttk.Menubutton(self, text="Resume/Pause Updates")
961 mb.menu = tk.Menu(mb, tearoff=0)
962 mb["menu"] = mb.menu
963 mb.menu.add_command(label="Resume",
964 command=lambda: loadChart('start'))
965 mb.menu.add_command(label="Pause",
966 command=lambda: loadChart('stop'))
967 mb.pack(side='right')
968
969 mb = ttk.Menubutton(self, text="Exchange")
970 mb.menu = tk.Menu(mb, tearoff=0)
971 mb["menu"] = mb.menu
972 mb.menu.add_command(label="BTC-e",
973 command=lambda: changeExchange('BTC-e', 'btce'))
974 mb.menu.add_command(label="Bitfinex",
975 command=lambda: changeExchange('Bitfinex', 'bitfinex'))
976 mb.menu.add_command(label="Bitstamp",
977 command=lambda: changeExchange('Bitstamp', 'bitstamp'))
978 mb.menu.add_command(label="Huobi",
979 command=lambda: changeExchange('Huobi', 'huobi'))
980 mb.pack(side='left')
981
982 mb = ttk.Menubutton(self, text="Data Time Frame")
983 mb.menu = tk.Menu(mb, tearoff=0)
984 mb["menu"] = mb.menu
985 mb.menu.add_command(label="Tick",
986 command=lambda: changeTimeFrame('tick'))
987 mb.menu.add_command(label="1 day",
988 command=lambda: changeTimeFrame('1d'))
989 mb.menu.add_command(label="3 day",
990 command=lambda: changeTimeFrame('3d'))
991 mb.menu.add_command(label="1 Week",
992 command=lambda: changeTimeFrame('7d'))
993 mb.pack(side='left')
994
995 mb = ttk.Menubutton(self, text="OHLC Interval")
996 mb.menu = tk.Menu(mb, tearoff=0)
997 mb["menu"] = mb.menu
998 mb.menu.add_command(label="Tick",
999 command=lambda: changeTimeFrame('tick'))
1000 mb.menu.add_command(label="1 minute",
1001 command=lambda: changeSampleSize('1Min', 0.0005))
1002 mb.menu.add_command(label="5 minute",
1003 command=lambda: changeSampleSize('5Min', 0.003))
1004 mb.menu.add_command(label="15 minute",
1005 command=lambda: changeSampleSize('15Min', 0.008))
1006 mb.menu.add_command(label="30 minute",
1007 command=lambda: changeSampleSize('30Min', 0.016))
1008 mb.menu.add_command(label="1 Hour",
1009 command=lambda: changeSampleSize('1H', 0.032))
1010 mb.menu.add_command(label="3 Hour",
1011 command=lambda: changeSampleSize('3H', 0.096))
1012
1013 mb.pack(side='left')
1014
1015 mb = ttk.Menubutton(self, text="Top Indicator")
1016 mb.menu = tk.Menu(mb, tearoff=0)
1017 mb["menu"] = mb.menu
1018 mb.menu.add_command(label="None",
1019 command=lambda: addTopIndicator('none'))
1020 mb.menu.add_command(label="RSI",
1021 command=lambda: addTopIndicator('rsi'))
1022 mb.menu.add_command(label="MACD",
1023 command=lambda: addTopIndicator('macd'))
1024 mb.pack(side='left')
1025
1026 mb = ttk.Menubutton(self, text="Main Graph Indicator")
1027 mb.menu = tk.Menu(mb, tearoff=0)
1028 mb["menu"] = mb.menu
1029 mb.menu.add_command(label="None",
1030 command=lambda: addMiddleIndicator('none'))
1031 mb.menu.add_command(label="SMA",
1032 command=lambda: addMiddleIndicator('sma'))
1033 mb.menu.add_command(label="EMA",
1034 command=lambda: addMiddleIndicator('ema'))
1035
1036 mb.pack(side='left')
1037
1038 mb = ttk.Menubutton(self, text="Bottom Indicator")
1039 mb.menu = tk.Menu(mb, tearoff=0)
1040 mb["menu"] = mb.menu
1041 mb.menu.add_command(label="None",
1042 command=lambda: addBottomIndicator('none'))
1043 mb.menu.add_command(label="RSI",
1044 command=lambda: addBottomIndicator('rsi'))
1045 mb.menu.add_command(label="MACD",
1046 command=lambda: addBottomIndicator('macd'))
1047 mb.pack(side='left')
1048
1049
1050if __name__ == "__main__":
1051 Version = '0.00'
1052 # quickVisit = urllib.request.urlopen("http://seaofbtc.com/bitcoin-trading-client").read()
1053 latestVersion = '0.00'
1054
1055 app = SeaofBTCapp()
1056 app.geometry("1280x720")
1057 ani = animation.FuncAnimation(f, animate, interval=refreshRate)
1058 # create a toplevel menu
1059 app.mainloop()