Bob Ross
Bob Ross личный блог
10 февраля 2024, 16:53

Бесплатные графики кластеров с помощью Python

Бывает нужно мне посмотреть где и как распределился объем по свечам внутри определенного диапазона.
Обычно смотрю за последние 2-3 часа на 5-минутках (можно и точные срезы делать) или за день на 15/60-минутках.

Минусы текущей реализации:
— картинку 5 минуток за большой промежуток времени смотреть не получится, но за 2-3-4 часа вполне себе. Зависит от таймфрейма, диапазона, за который надо посмотреть данные, и ваших требований по красоте картинки. Мне хватает пока.
— данные обрабатываются относительно долго (библиотека matplotlib каждый раз рисует график заново + недостаток знаний программирования/ума).

Плюсы:
— свое, родное, надежное и хоть как-то контролируемое. И бесплатное.

Данные: КВИК (Финам или Мосбиржа с задержкой).
Подключаюсь к КВИКу — вывод по ODBC — использую MS SQL 2012.
Обработка данных: Python (pandas + matplotlib) + просмотр графиков через браузер.

Знания Python поверхностные, но добрые люди здесь помогли построить график.

Вкратце суть такая.
1. Сначала делаю с помощью pandas мультииндексный таймфрейм следующего вида:
Бесплатные графики кластеров с помощью Python


2. Потом строю график в matplotlib. График строю по тупому и не оптимально (от нехватки знаний), т.к. по сути строю и накладываю три графика друг на друга (кол-во сделок, дельты плюс, дельты минус). По уму надо сразу строить только один график.
Бесплатные графики кластеров с помощью Python



Здесь приведу код как у меня есть — рассчитано на отрисовку одного или нескольких тикеров из списка. Кому надо, думаю, разберется и переделает.

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))
Проверьте отступы — задолбался с редактором здесь воевать.
Можно и такие графики с дельтами в разные стороны рисовать
Бесплатные графики кластеров с помощью Python

Если кто оптимизирует и ускорит код, буду благодарен.
1 Комментарий

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн