11from datetime import datetime , timezone
2- from pytest import Instance
32import pytz
43
54import pandas as pd
5+ import numpy as np
66import matplotlib .pyplot as plt
7+ import pyqtgraph as pg
78
89import finplot_lib as fplt
910
@@ -24,23 +25,148 @@ def create_observation_matrix(mp_slice):
2425
2526 # slice_dt = pytz.timezone('Asia/Hong_Kong').localize(datetime(2022,3,17,17,23,0)) # input in HKT
2627 slice_start = pytz .timezone ('Asia/Hong_Kong' ).localize (datetime (2021 ,12 ,10 ,0 ,0 ,0 )) # input in HKT
27- slice_end = pytz .timezone ('Asia/Hong_Kong' ).localize (datetime (2021 ,12 ,12 , 0 ,0 ,0 )) # input in HKT
28+ slice_end = pytz .timezone ('Asia/Hong_Kong' ).localize (datetime (2021 ,12 ,10 , 16 ,0 ,0 )) # input in HKT
2829
2930 # mp_slice = profile[slice_dt]
3031 mp_slice = profile [slice_start :slice_end ]
3132
32- ochl = pd .DataFrame (
33+ ohlcv = pd .DataFrame (
3334 {
3435 'o' : [mp .open for mp in mp_slice ],
35- 'c' : [mp .close for mp in mp_slice ],
3636 'h' : [mp .high for mp in mp_slice ],
3737 'l' : [mp .low for mp in mp_slice ],
38- # 'v': [mp.volume_qty for mp in mp_slice]
38+ 'c' : [mp .close for mp in mp_slice ],
39+ 'v' : [mp .volume_qty for mp in mp_slice ],
40+ 'd' : [mp .delta_qty for mp in mp_slice ]
3941 },
4042 index = [mp .timepoint for mp in mp_slice ]
4143 )
4244
43- # ohlcv.plot(y='o')
44- # plt.show()
45- fplt .candlestick_ochl (datasrc = ochl , candle_width = 0.2 )
45+ # plotting
46+ fplt .foreground = '#D6DBDF'
47+ fplt .background = '#151E26'
48+ ax , ax2 = fplt .create_plot (
49+ title = 'Orderflow' ,
50+ rows = 2 , # row1: candlestick, volume; row2: delta table; row2:
51+ )
52+
53+ # set font
54+ '''
55+ TODO: set font
56+ '''
57+
58+ # fplt.windows[0].ci.layout.setRowStretchFactor(0, 8) # make primary plot large, and implicitly table small
59+
60+ # add candlestick
61+ candlestick_plot = fplt .candlestick_ochl (datasrc = ohlcv [['o' , 'c' , 'h' , 'l' ]], candle_width = 0.6 , ax = ax )
62+
63+ # add volume
64+ volume_plot = fplt .volume_ocv (ohlcv [['o' , 'c' , 'v' ]], ax = ax .overlay ())
65+
66+ # add delta table
67+ '''
68+ Ref: examples/bubble-table.py
69+ '''
70+ # def skip_y_crosshair_info(x, y, xt, yt): # we don't want any Y crosshair info on the table
71+ # return xt, ''
72+ # ax2.set_visible(yaxis=False)
73+ # fplt.add_crosshair_info(skip_y_crosshair_info, ax=ax2)
74+ # fplt.set_y_range(0, 2, ax2)
75+ # # hmmm it is weird that finplot requires the column to be visualized to be named int 0,1,2,...
76+ # delta_df = ohlcv.copy()
77+ # delta_df[1] = delta_df['d']
78+ # delta_df[0] = delta_df['d'].cumsum()
79+
80+ # colmap = fplt.ColorMap([0.0, 0.5, 1.0], [[200, 80, 60], [200, 190, 100], [40, 170, 30]]) # traffic light colors
81+ # ts = [int(t.timestamp()) for t in ohlcv.index]
82+ # fplt.heatmap(delta_df[[1, 0]], colmap=colmap, colcurve=lambda x: x, ax=ax2)
83+ # fplt.labels(ts, [1.5] * len(ohlcv), [f'{d:2f}' for d in ohlcv['d']], ax=ax2, anchor=(0.5, 0.5))
84+ # fplt.labels(ts, [0.5] * len(ohlcv), [f'{d:2f}' for d in ohlcv['d'].cumsum()], ax=ax2, anchor=(0.5, 0.5))
85+
86+ '''
87+ Ref: examples/snp500.py
88+ '''
89+ # plot cvd
90+ line_color = '#3498DB'
91+ cvd_plot = fplt .plot (np .cumsum (ohlcv ['d' ]), ax = ax2 , legend = 'CVD' , color = line_color , fillLevel = 0 , brush = line_color + '10' )
92+ # and set background
93+ vb = cvd_plot .getViewBox ()
94+ vb .setBackgroundColor ('#00000000' )
95+
96+ '''
97+ Ref: examples/complicated.py
98+ '''
99+ # set bull body to same color as bull frame; otherwise it is default background color (transparent)
100+ bull = '#1ABC9C'
101+ bear = '#E74C3C'
102+ fplt .candle_bull_color = bull
103+ fplt .candle_bull_body_color = bull
104+ fplt .candle_bear_color = bear
105+ candlestick_plot .colors .update ({
106+ 'bull_body' : fplt .candle_bull_color
107+ })
108+
109+ transparency = '45'
110+ volume_plot .colors .update ({
111+ 'bull_frame' : fplt .candle_bull_color + transparency ,
112+ 'bull_body' : fplt .candle_bull_body_color + transparency ,
113+ 'bear_frame' : fplt .candle_bear_color + transparency ,
114+ 'bear_body' : fplt .candle_bear_color + transparency ,
115+ })
116+
117+ # set gridlines
118+ ax .showGrid (x = True , y = True , alpha = 0.2 )
119+ ax2 .showGrid (x = True , y = True , alpha = 0.2 )
120+
121+ # add legend of ohlcv data
122+ '''
123+ Ref: examples/snp500.py
124+ '''
125+ hover_label = fplt .add_legend ('' , ax = ax )
126+ def update_legend_text (x , y ):
127+ dt = datetime .fromtimestamp (x // 1000000000 )
128+ utcdt = dt .astimezone (pytz .utc )
129+ # dt = dt.replace(tzinfo=timezone.utc)
130+ row = ohlcv .loc [utcdt ]
131+ # format html with the candle and set legend
132+ fmt = '<span style="color:%s; margin: 16px;">%%s</span>' % (bull if (row ['o' ] < row ['c' ]).all () else bear )
133+ rawtxt = '<span style="font-size:14px">%%s %%s</span> O: %s H: %s L: %s C: %s Delta: %s' % (fmt , fmt , fmt , fmt , fmt )
134+ hover_label .setText (rawtxt % ('TOKEN' , 'INTERVAL' , row ['o' ], row ['h' ], row ['l' ], row ['c' ], row ['d' ]))
135+ fplt .set_time_inspector (update_legend_text , ax = ax , when = 'hover' )
136+
137+ # additional crosshair info
138+ def enrich_info (x , y , xtext , ytext ):
139+ o = ohlcv .iloc [x ]['o' ]
140+ h = ohlcv .iloc [x ]['h' ]
141+ l = ohlcv .iloc [x ]['l' ]
142+ c = ohlcv .iloc [x ]['c' ]
143+ add_yt = f'\t Open: { o } \n \t High: { h } \n \t Low: { l } \n \t Close: { c } '
144+ return xtext , add_yt
145+
146+ fplt .add_crosshair_info (enrich_info , ax = ax )
147+
148+ # set dark themes ====================
149+ pg .setConfigOptions (foreground = fplt .foreground , background = fplt .background )
150+
151+ # window background
152+ for win in fplt .windows :
153+ win .setBackground (fplt .background )
154+
155+ # axis, crosshair, candlesticks, volumes
156+ axs = [ax for win in fplt .windows for ax in win .axs ]
157+ vbs = set ([ax .vb for ax in axs ])
158+ axs += fplt .overlay_axs
159+ axis_pen = fplt ._makepen (color = fplt .foreground )
160+ for ax in axs :
161+ ax .axes ['left' ]['item' ].setPen (axis_pen )
162+ ax .axes ['left' ]['item' ].setTextPen (axis_pen )
163+ ax .axes ['bottom' ]['item' ].setPen (axis_pen )
164+ ax .axes ['bottom' ]['item' ].setTextPen (axis_pen )
165+ if ax .crosshair is not None :
166+ ax .crosshair .vline .pen .setColor (pg .mkColor (fplt .foreground ))
167+ ax .crosshair .hline .pen .setColor (pg .mkColor (fplt .foreground ))
168+ ax .crosshair .xtext .setColor (fplt .foreground )
169+ ax .crosshair .ytext .setColor (fplt .foreground )
170+ # ====================================
171+
46172 fplt .show ()
0 commit comments