Бывает нужно мне посмотреть где и как распределился объем по свечам внутри определенного диапазона.
Обычно смотрю за последние 2-3 часа на 5-минутках (можно и точные срезы делать) или за день на 15/60-минутках.
Минусы текущей реализации:
— картинку 5 минуток за большой промежуток времени смотреть не получится, но за 2-3-4 часа вполне себе. Зависит от таймфрейма, диапазона, за который надо посмотреть данные, и ваших требований по красоте картинки. Мне хватает пока.
— данные обрабатываются относительно долго (библиотека matplotlib каждый раз рисует график заново + недостаток знаний программирования/ума).
Плюсы:
— свое, родное, надежное и хоть как-то контролируемое. И бесплатное.
Данные: КВИК (Финам или Мосбиржа с задержкой).
Подключаюсь к КВИКу — вывод по ODBC — использую MS SQL 2012.
Обработка данных: Python (pandas + matplotlib) + просмотр графиков через браузер.
Знания Python поверхностные, но добрые люди
здесь помогли построить график.
Вкратце суть такая.
1. Сначала делаю с помощью pandas мультииндексный таймфрейм следующего вида:
2. Потом строю график в matplotlib. График строю по тупому и не оптимально (от нехватки знаний), т.к. по сути строю и накладываю три графика друг на друга (кол-во сделок, дельты плюс, дельты минус). По уму надо сразу строить только один график.
Здесь приведу код как у меня есть — рассчитано на отрисовку одного или нескольких тикеров из списка. Кому надо, думаю, разберется и переделает.
import pandas as pd<br />import pyodbc<br /><br />import matplotlib.pyplot as plt<br />from matplotlib.colors import TABLEAU_COLORS<br />from itertools import cycle<br /><br />from pandas import DataFrame, Timestamp<br />from datetime import timedelta<br />import requests<br />import datetime<br />import winsound<br /><br /><br />connection = pyodbc.connect('Driver={SQL Server}; Server=1-ПК\SQLEXPRESS; Database=Quik_export'); # Соединяемся с сервером
SymbolList = ['yndx', 'LKOH']
timeframe = '5min'
h = 3 #кол-во отображаемых часов за день
if (timeframe == '60min' or timeframe == '15min'):
h=12
last_hour = max((datetime.datetime.now() - timedelta(hours = h)).strftime('%H:%M:%S'),'10:00:00') #для последующего среза данных
while True:
try:
#готовлю данные из SQL
data0 = pd.read_sql("SELECT * FROM Quik_export.dbo.sdelki", connection)
data0['symbol'] = data0['symbol'].str.replace(r'\[TQBR]', '').map(str.strip) #убираем [TQBR] и пробелы
data0['date'] = str(datetime.datetime.now().date())
data0['date_time'] = pd.to_datetime(data0['date'] + ' ' + data0['time_str']) # datetime формат делаю
#обрабатываю данные
for i in SymbolList:
# 1-й этап - подготовка мультииндексного таймфрейма
symbol = i.upper() #изменение на заглавные буквы
data = data0.copy(deep=True) #уже не помню, но почему-то такое решение сделал
data = data.loc[(data['symbol'] == symbol) & (data['date_time'] >= last_hour)] #делаю срез данных
df = data.drop_duplicates (subset=['numerator']) # убираю дубликаты по номеру сделок на всякий случай
df['price'] = df['price'].astype (str).astype (float)
df['quantity'] = pd.to_numeric(df['quantity']).astype (int) #quantity - кол-во сделок
df.loc[df['operation'] == 'SELL', 'delta'] = df['quantity']*(-1) # делаю знак дельты
df.loc[df['operation'] == 'BUY', 'delta'] = df['quantity']
df = df[['quantity','delta','date_time',"price"]]
df['data_interval'] = df['date_time'].dt.floor(timeframe)
df_0= df.copy(deep=True)
df_0.index = df_0['date_time']
df_0 = df_0['price'].resample(timeframe).ohlc(_method='ohlc')
df.sort_values(by=['date_time'])
df = df.groupby(["data_interval", "price"]).sum()
df = df.sort_values (by = ["data_interval", "price"], ascending = [ True, False ]) # мультииндексная основа для графиков готова
df.loc[df['delta'] >= 0, 'delta_plus'] = df['delta']
df.loc[df['delta'] < 0, 'delta_minus'] = df['delta'].abs() #если убрать модуль, то в разные стороны смотреть будет
# 2-й этап - отрисовка
unique_time = df.index.get_level_values(0).unique().sort_values()
unique_price = df.index.get_level_values(1).unique().sort_values()
spacing = 0.1 # a minimum distance between two consecutive horizontal lines 0.1
values1 = (1-spacing) * df['quantity']/df['quantity'].max() # relative lengths of horizontal lines - для каждого графика (кол-во сделок, дельты минус, дельты плюс)
values2 = (1-spacing) * df['delta_plus']/df['quantity'].max()
values3 = (1-spacing) * df['delta_minus']/df['quantity'].max()
base = DataFrame(index=unique_price) # the widest blank frame with prices
fig, ax = plt.subplots(figsize=(50,20))
xlabels = unique_time.astype(str)
ylabels = unique_price.astype(str)
ax.set_title(" ".join(symbol), fontsize=60)
ax.set_xticks(range(len(xlabels)), xlabels, rotation=45)
ax.set_yticks(range(len(ylabels)), ylabels)
ax.yaxis.set_ticks_position('right')
ax.set_xlim([-0.5,len(xlabels)])
ax.set_ylim([-1, len(ylabels)])
for i, t in enumerate(unique_time):<br /> #три графика по сути накладываются друг на друга - объемы, дельты плюс и дельты минус
pr = base.join(values1.loc[t]).squeeze()
# draw horizontal lines, shifted left by i-th timepoint
ax.barh(ylabels, pr, 0.3, i, color='black') #0.3 - толщина линии
pr2 = base.join(values2.loc[t]).squeeze()
ax.barh(ylabels, pr2, 0.3, i, color='green')
pr3 = base.join(values3.loc[t]).squeeze()
ax.barh(ylabels, pr3, 0.3, i, color='red')
fig.tight_layout()
plt.savefig ('Z://OSPanel//domains//localhost//' + str(symbol) + '.png') # путь для сохранения рисунков<br /><br /> winsound.Beep(200, 1000) #чтобы узнать, когда график готов
exit() # выход
except Exception as e:
print('ошибка: %s' % str(e))
Проверьте отступы — задолбался с редактором здесь воевать.
Можно и такие графики с дельтами в разные стороны рисовать
Если кто оптимизирует и ускорит код, буду благодарен.