Skip to content

Commit

Permalink
+ Стоимость портфеля: 1181319.98 Свободные средства: 5947427.37 ==> t…
Browse files Browse the repository at this point in the history
…o find error )))
  • Loading branch information
WISEPLAT committed May 13, 2022
1 parent d63065b commit 331bc6d
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 57 deletions.
55 changes: 55 additions & 0 deletions 02 - Symbols.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from datetime import datetime
from backtrader import Cerebro, TimeFrame
from BackTraderQuik.QKStore import QKStore # Хранилище QUIK
import Strategy as ts # Торговые системы
from QuikPy import QuikPy # Работа с QUIK из Python через LUA скрипты QuikSharp

if __name__ == '__main__': # Точка входа при запуске этого скрипта
qpProvider = QuikPy() # Вызываем конструктор QuikPy с подключением к локальному компьютеру с QUIK
cerebro = Cerebro() # Инициируем "движок" BackTrader

cerebro.broker.setcash(1000000)
cerebro.broker.setcommission(commission=0.01)
#cerebro.broker.set_fundmode(True) # the default is 100

symbols = ('TQBR.SBER', 'TQBR.GAZP', 'TQBR.LKOH', 'TQBR.GMKN',) # Кортеж тикеров

all_lots = {}

for ticker in symbols:
# Данные тикера
part_symbol = ticker.split(".")
classCode = part_symbol[0] # Класс тикера
secCode = part_symbol[1] # Тикер

# Данные тикера
securityInfo = qpProvider.GetSecurityInfo(classCode, secCode)["data"]
print(f'Информация о тикере {classCode}.{secCode} ({securityInfo["short_name"]}):')
print('Валюта:', securityInfo['face_unit'])
print('Кол-во десятичных знаков:', securityInfo['scale'])
print('Лот:', securityInfo['lot_size'])
print('Шаг цены:', securityInfo['min_price_step'])

all_lots[ticker] = securityInfo['lot_size']

print(all_lots)


store = QKStore() # Хранилище QUIK (QUIK на локальном компьютере)
# store = QKStore(Host='<Ваш IP адрес>') # Хранилище QUIK (К QUIK на удаленном компьютере обращаемся по IP или названию)
for symbol in symbols: # Пробегаемся по всем тикерам
data = store.getdata(dataname=symbol, timeframe=TimeFrame.Minutes, compression=15, fromdate=datetime(2021, 10, 4), LiveBars=False) # Исторические и новые бары по первому тикеру
cerebro.adddata(data, name=symbol) # Добавляем данные
#cerebro.addstrategy(ts.TestStrategy01, name="One Ticker", symbols=('TQBR.SBER',)) # Добавляем торговую систему по одному тикеру
#cerebro.addstrategy(ts.TestStrategy01, name="Two Tickers", symbols=('TQBR.GAZP', 'TQBR.LKOH',)) # Добавляем торговую систему по двум тикерам
cerebro.addstrategy(ts.TestStrategy01, name="All Tickers", lots=all_lots) # Добавляем торговую систему по всем тикерам

cerebro.run() # Запуск торговой системы

print('Стоимость портфеля: %.2f' % cerebro.broker.getvalue())
print('Свободные средства: %.2f' % cerebro.broker.get_cash())

cerebro.plot(style='candle') # Рисуем график. Требуется matplotlib версии 3.2.2 (pip install matplotlib==3.2.2)

# Выход
qpProvider.CloseConnectionAndThread() # Перед выходом закрываем соединение и поток QuikPy из любого экземпляра
37 changes: 29 additions & 8 deletions Strategy.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import backtrader as bt
from collections import defaultdict # для списков в словарях
import functions

class PrintStatusAndBars(bt.Strategy):

class TestStrategy01(bt.Strategy):
"""
- Отображает статус подключения
- При приходе нового бара отображает его цены/объем
Expand All @@ -9,6 +12,8 @@ class PrintStatusAndBars(bt.Strategy):
params = ( # Параметры торговой системы
('name', ''), # Название торговой системы
('symbols', ''), # Список торгуемых тикеров. По умолчанию торгуем все тикеры
('Percent', 20),
('lots', ''),
)

def __init__(self):
Expand All @@ -20,6 +25,11 @@ def __init__(self):

self.dataclose = None

self.orders_bar_executed = defaultdict(list)

print(self.p.lots)


def log(self, txt, dt=None):
"""Вывод строки с датой на консоль"""
dt = bt.num2date(
Expand All @@ -34,7 +44,7 @@ def next(self):
lastdatetimes = [bt.num2date(data.datetime[0]) for data in self.datas] # Дата и время последнего бара каждого тикера
if lastdatetimes.count(lastdatetimes[0]) != len(lastdatetimes): # Если дата и время последних баров не идентичны
return # то еще не пришли все новые бары. Ждем дальше, выходим
print(self.p.name)
#print(self.p.name)
for data in self.datas: # Пробегаемся по всем запрошенным тикерам
if self.p.symbols == '' or data._dataname in self.p.symbols: # Если торгуем все тикеры или данный тикер
self.log(f'{data._dataname} - {bt.TimeFrame.Names[data.p.timeframe]} {data.p.compression} - Open={data.open[0]:.2f}, High={data.high[0]:.2f}, Low={data.low[0]:.2f}, Close={data.close[0]:.2f}, Volume={data.volume[0]:.0f}',
Expand All @@ -57,21 +67,31 @@ def next(self):
if self.dataclose[-1] < self.dataclose[-2]:
# previous close less than the previous close

# size, lots_can_buy = functions.calc_size(depo=self.cerebro.broker.get_cash(),
# lot=self.p.lots[self.data._name],
# percent=self.p.Percent,
# ticker_price=self.dataclose[0])
# print(size, lots_can_buy)

# BUY, BUY, BUY!!! (with default parameters)
self.log('BUY CREATE, %.2f' % self.dataclose[0])

# Keep track of the created order to avoid a 2nd order
self.order = self.buy()
self.order = self.buy(data=data) #, size=size)

else:

# Already in the market ... we might sell
if len(self) >= (self.bar_executed + 5):
# SELL, SELL, SELL!!! (with all possible default parameters)
self.log('SELL CREATE, %.2f' % self.dataclose[0])
print(len(self), self.orders_bar_executed[data._name], data._name, self.orders_bar_executed)
try:
if len(self) >= (self.orders_bar_executed[data._name] + 5):
# SELL, SELL, SELL!!! (with all possible default parameters)
self.log('SELL CREATE, %.2f' % self.dataclose[0])

# Keep track of the created order to avoid a 2nd order
self.order = self.sell()
# Keep track of the created order to avoid a 2nd order
self.order = self.sell(data=data)
except:
pass

def notify_trade(self, trade):
if not trade.isclosed:
Expand All @@ -94,6 +114,7 @@ def notify_order(self, order):
self.log('SELL EXECUTED, %.2f' % order.executed.price)

self.bar_executed = len(self)
self.orders_bar_executed[order.data._name] = len(self)

elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log('Order Canceled/Margin/Rejected')
Expand Down
72 changes: 23 additions & 49 deletions get_all_shares_ok_quik.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,60 +23,33 @@

load_data = DataQuik()

classSecurities = ['ABRD', 'ACKO', 'AFKS', 'AFLT', 'AGRO', 'AKRN', 'ALRS', 'AMEZ', 'APTK', 'AQUA', 'ARSA', 'ASSB',
'AVAN', 'BANE', 'BANEP', 'BELU', 'BISV', 'BISVP', 'BLNG', 'BRZL', 'BSPB', 'BSPBP', 'CBOM',
'CHGZ', 'CHKZ', 'CHMF', 'CHMK', 'CIAN', 'CNTL', 'CNTLP', 'DERZP', 'DIOD', 'DSKY', 'DVEC', 'DZRD',
'DZRDP', 'EELT', 'ELTZ', 'EM44', 'ENPG', 'ENRU', 'ETLN', 'FEES', 'FESH', 'FIVE', 'FIXP', 'FLOT',
'GAZA', 'GAZAP', 'GAZC', 'GAZP', 'GAZS', 'GAZT', 'GCHE', 'GEMA', 'GEMC', 'GLTR', 'GMKN', 'GTRK',
'GTSS', 'HHRU', 'HIMC', 'HIMCP', 'HMSG', 'HYDR', 'IGST', 'IGSTP', 'INGR', 'IRAO', 'IRGZ', 'IRKT',
'ISKJ', 'JNOS', 'JNOSP', 'KAZT', 'KAZTP', 'KBSB', 'KCHE', 'KCHEP', 'KGKC', 'KGKCP', 'KLSB',
'KMAZ', 'KMEZ', 'KMTZ', 'KOGK', 'KRKN', 'KRKNP', 'KRKO', 'KRKOP', 'KROT', 'KROTP', 'KRSB',
'KRSBP', 'KSGR', 'KTSB', 'KTSBP', 'KUBE', 'KUZB', 'KZMS', 'KZOS', 'KZOSP', 'LENT', 'LIFE',
'LKOH', 'LNZL', 'LNZLP', 'LPSB', 'LSNG', 'LSNGP', 'LSRG', 'LVHK', 'MAGE', 'MAGEP', 'MAGN',
'MDMG', 'MFGS', 'MFGSP', 'MFON', 'MGNT', 'MGNZ', 'MGTS', 'MGTSP', 'MISB', 'MISBP', 'MOEX',
'MORI', 'MRKC', 'MRKK', 'MRKP', 'MRKS', 'MRKU', 'MRKV', 'MRKY', 'MRKZ', 'MRSB', 'MSNG', 'MSRS',
'MSTT', 'MTLR', 'MTLRP', 'MTSS', 'MVID', 'NAUK', 'NFAZ', 'NKHP', 'NKNC', 'NKNCP', 'NKSH', 'NLMK',
'NMTP', 'NNSB', 'NNSBP', 'NPOF', 'NSVZ', 'NVTK', 'OGKB', 'OKEY', 'OMZZP', 'OZON', 'PAZA', 'PHOR',
'PIKK', 'PLZL', 'PMSB', 'PMSBP', 'POGR', 'POLY', 'POSI', 'PRMB', 'QIWI', 'RASP', 'RAVN', 'RBCM',
'RDRB', 'RENI', 'RGSS', 'RKKE', 'RNFT', 'ROLO', 'ROSB', 'ROSN', 'ROST', 'RSTI', 'RSTIP', 'RTGZ',
'RTKM', 'RTKMP', 'RTSB', 'RTSBP', 'RUAL', 'RUGR', 'RUSI', 'RUSP', 'RZSB', 'SAGO', 'SAGOP',
'SARE', 'SAREP', 'SBER', 'SBERP', 'SELG', 'SFIN', 'SFTL', 'SGZH', 'SIBN', 'SLEN', 'SMLT', 'SNGS',
'SNGSP', 'SPBE', 'STSB', 'STSBP', 'SVAV', 'SVET', 'TASB', 'TASBP', 'TATN', 'TATNP', 'TCSG',
'TGKA', 'TGKB', 'TGKBP', 'TGKD', 'TGKDP', 'TGKN', 'TNSE', 'TORS', 'TORSP', 'TRCN', 'TRFM',
'TRMK', 'TRNFP', 'TTLK', 'TUZA', 'UCSS', 'UKUZ', 'UNAC', 'UNKL', 'UPRO', 'URKA', 'URKZ', 'USBN',
'UTAR', 'VEON-RX', 'VGSB', 'VGSBP', 'VJGZ', 'VJGZP', 'VKCO', 'VLHZ', 'VRSB', 'VRSBP', 'VSMO',
'VSYD', 'VSYDP', 'VTBR', 'WTCM', 'WTCMP', 'YAKG', 'YKEN', 'YKENP', 'YNDX', 'YRSB', 'YRSBP',
'ZILL', 'ZVEZ']

# error with: classSecurities = ['BISV', 'DERZP', 'EM44', 'GAZC', 'GAZS', 'GAZT', 'GTSS', 'HIMC', 'KMTZ', 'KRKO', 'KSGR', 'KZMS', 'MFON', 'MORI', 'NPOF', 'RUSP', 'TRCN', 'TRFM', 'URKA']

# ok
classSecurities = ['ABRD', 'ACKO', 'AFKS', 'AFLT', 'AGRO', 'AKRN', 'ALRS', 'AMEZ', 'APTK', 'AQUA', 'ARSA', 'ASSB',
'AVAN', 'BANE', 'BANEP', 'BELU', 'BISVP', 'BLNG', 'BRZL', 'BSPB', 'BSPBP', 'CBOM', 'CHGZ',
'CHKZ', 'CHMF', 'CHMK', 'CIAN', 'CNTL', 'CNTLP', 'DIOD', 'DSKY', 'DVEC', 'DZRD', 'DZRDP', 'EELT',
'ELTZ', 'ENPG', 'ENRU', 'ETLN', 'FEES', 'FESH', 'FIVE', 'FIXP', 'FLOT', 'GAZA', 'GAZAP', 'GAZP',
'GCHE', 'GEMA', 'GEMC', 'GLTR', 'GMKN', 'GTRK', 'HHRU', 'HIMCP', 'HMSG', 'HYDR', 'IGST', 'IGSTP',
'INGR', 'IRAO', 'IRGZ', 'IRKT', 'ISKJ', 'JNOS', 'JNOSP', 'KAZT', 'KAZTP', 'KBSB', 'KCHE',
'KCHEP', 'KGKC', 'KGKCP', 'KLSB', 'KMAZ', 'KMEZ', 'KOGK', 'KRKN', 'KRKNP', 'KRKOP', 'KROT',
'KROTP', 'KRSB', 'KRSBP', 'KTSB', 'KTSBP', 'KUBE', 'KUZB', 'KZOS', 'KZOSP', 'LENT', 'LIFE',
'LKOH', 'LNZL', 'LNZLP', 'LPSB', 'LSNG', 'LSNGP', 'LSRG', 'LVHK', 'MAGE', 'MAGEP', 'MAGN',
'MDMG', 'MFGS', 'MFGSP', 'MGNT', 'MGNZ', 'MGTS', 'MGTSP', 'MISB', 'MISBP', 'MOEX', 'MRKC',
'MRKK', 'MRKP', 'MRKS', 'MRKU', 'MRKV', 'MRKY', 'MRKZ', 'MRSB', 'MSNG', 'MSRS', 'MSTT', 'MTLR',
'MTLRP', 'MTSS', 'MVID', 'NAUK', 'NFAZ', 'NKHP', 'NKNC', 'NKNCP', 'NKSH', 'NLMK', 'NMTP', 'NNSB',
'NNSBP', 'NSVZ', 'NVTK', 'OGKB', 'OKEY', 'OMZZP', 'OZON', 'PAZA', 'PHOR', 'PIKK', 'PLZL', 'PMSB',
'PMSBP', 'POGR', 'POLY', 'POSI', 'PRMB', 'QIWI', 'RASP', 'RAVN', 'RBCM', 'RDRB', 'RENI', 'RGSS',
'RKKE', 'RNFT', 'ROLO', 'ROSB', 'ROSN', 'ROST', 'RSTI', 'RSTIP', 'RTGZ', 'RTKM', 'RTKMP', 'RTSB',
'RTSBP', 'RUAL', 'RUGR', 'RUSI', 'RZSB', 'SAGO', 'SAGOP', 'SARE', 'SAREP', 'SBER', 'SBERP',
'SELG', 'SFIN', 'SFTL', 'SGZH', 'SIBN', 'SLEN', 'SMLT', 'SNGS', 'SNGSP', 'SPBE', 'STSB', 'STSBP',
'SVAV', 'SVET', 'TASB', 'TASBP', 'TATN', 'TATNP', 'TCSG', 'TGKA', 'TGKB', 'TGKBP', 'TGKD',
'TGKDP', 'TGKN', 'TNSE', 'TORS', 'TORSP', 'TRMK', 'TRNFP', 'TTLK', 'TUZA', 'UCSS', 'UKUZ',
'UNAC', 'UNKL', 'UPRO', 'URKZ', 'USBN', 'UTAR', 'VEON-RX', 'VGSB', 'VGSBP', 'VJGZ', 'VJGZP',
'VKCO', 'VLHZ', 'VRSB', 'VRSBP', 'VSMO', 'VSYD', 'VSYDP', 'VTBR', 'WTCM', 'WTCMP', 'YAKG',
'YKEN', 'YKENP', 'YNDX', 'YRSB', 'YRSBP', 'ZILL', 'ZVEZ']
classSecurities = ['ABRD', 'ACKO', 'AFKS', 'AFLT', 'AGRO', 'AKRN', 'ALRS', 'AMEZ', 'APTK', 'AQUA', 'ARSA', 'ASSB', 'AVAN', 'BANE',
'BANEP', 'BELU', 'BISV', 'BISVP', 'BLNG', 'BRZL', 'BSPB', 'BSPBP', 'CBOM', 'CHGZ', 'CHKZ', 'CHMF', 'CHMK', 'CIAN',
'CNTL', 'CNTLP', 'DERZP', 'DIOD', 'DSKY', 'DVEC', 'DZRD', 'DZRDP', 'EELT', 'ELTZ', 'EM44', 'ENPG', 'ENRU', 'ETLN',
'FEES', 'FESH', 'FIVE', 'FIXP', 'FLOT', 'GAZA', 'GAZAP', 'GAZC', 'GAZP', 'GAZS', 'GAZT', 'GCHE', 'GEMA', 'GEMC',
'GLTR', 'GMKN', 'GTRK', 'GTSS', 'HHRU', 'HIMC', 'HIMCP', 'HMSG', 'HYDR', 'IGST', 'IGSTP', 'INGR', 'IRAO', 'IRGZ',
'IRKT', 'ISKJ', 'JNOS', 'JNOSP', 'KAZT', 'KAZTP', 'KBSB', 'KCHE', 'KCHEP', 'KGKC', 'KGKCP', 'KLSB', 'KMAZ', 'KMEZ',
'KMTZ', 'KOGK', 'KRKN', 'KRKNP', 'KRKO', 'KRKOP', 'KROT', 'KROTP', 'KRSB', 'KRSBP', 'KSGR', 'KTSB', 'KTSBP',
'KUBE', 'KUZB', 'KZMS', 'KZOS', 'KZOSP', 'LENT', 'LIFE', 'LKOH', 'LNZL', 'LNZLP', 'LPSB', 'LSNG', 'LSNGP', 'LSRG',
'LVHK', 'MAGE', 'MAGEP', 'MAGN', 'MDMG', 'MFGS', 'MFGSP', 'MFON', 'MGNT', 'MGNZ', 'MGTS', 'MGTSP', 'MISB', 'MISBP',
'MOEX', 'MORI', 'MRKC', 'MRKK', 'MRKP', 'MRKS', 'MRKU', 'MRKV', 'MRKY', 'MRKZ', 'MRSB', 'MSNG', 'MSRS', 'MSTT',
'MTLR', 'MTLRP', 'MTSS', 'MVID', 'NAUK', 'NFAZ', 'NKHP', 'NKNC', 'NKNCP', 'NKSH', 'NLMK', 'NMTP', 'NNSB', 'NNSBP',
'NPOF', 'NSVZ', 'NVTK', 'OGKB', 'OKEY', 'OMZZP', 'OZON', 'PAZA', 'PHOR', 'PIKK', 'PLZL', 'PMSB', 'PMSBP', 'POGR',
'POLY', 'POSI', 'PRMB', 'QIWI', 'RASP', 'RAVN', 'RBCM', 'RDRB', 'RENI', 'RGSS', 'RKKE', 'RNFT', 'ROLO', 'ROSB',
'ROSN', 'ROST', 'RSTI', 'RSTIP', 'RTGZ', 'RTKM', 'RTKMP', 'RTSB', 'RTSBP', 'RUAL', 'RUGR', 'RUSI', 'RUSP', 'RZSB',
'SAGO', 'SAGOP', 'SARE', 'SAREP', 'SBER', 'SBERP', 'SELG', 'SFIN', 'SFTL', 'SGZH', 'SIBN', 'SLEN', 'SMLT', 'SNGS',
'SNGSP', 'SPBE', 'STSB', 'STSBP', 'SVAV', 'SVET', 'TASB', 'TASBP', 'TATN', 'TATNP', 'TCSG', 'TGKA', 'TGKB',
'TGKBP', 'TGKD', 'TGKDP', 'TGKN', 'TNSE', 'TORS', 'TORSP', 'TRCN', 'TRFM', 'TRMK', 'TRNFP', 'TTLK', 'TUZA', 'UCSS',
'UKUZ', 'UNAC', 'UNKL', 'UPRO', 'URKA', 'URKZ', 'USBN', 'UTAR', 'VEON-RX', 'VGSB', 'VGSBP', 'VJGZ', 'VJGZP',
'VKCO', 'VLHZ', 'VRSB', 'VRSBP', 'VSMO', 'VSYD', 'VSYDP', 'VTBR', 'WTCM', 'WTCMP', 'YAKG', 'YKEN', 'YKENP', 'YNDX',
'YRSB', 'YRSBP', 'ZILL', 'ZVEZ']

prefix = classCode + '.'
timeframe = "W1"
how_many_bars = 50000
how_many_bars = 70000

classSecurities_ok = []

Expand All @@ -85,7 +58,7 @@
_ticker = classCode + '.' + ticker
#data = load_data.GetShareDataFromQuik(qpProvider, _ticker, timeframe, utc_till, how_many_bars, remove_last_bar=False, upper_heading=False)
#print(data)
load_data.ExportToCsvFromQuik(qpProvider, _ticker, timeframe, utc_till, how_many_bars, remove_last_bar=False, export_dir='csv_quik_fix_w', prefix='', upper_heading=False)
load_data.ExportToCsvFromQuik(qpProvider, _ticker, timeframe, utc_till, how_many_bars, remove_last_bar=False, export_dir=f'csv_quik_{timeframe}', prefix='', upper_heading=False)
# create CSV file
# load_data.ExportToCsvFromMetatrader(ticker=ticker, timeframe=timeframe, utc_till=utc_till,
# how_many_bars=how_many_bars, remove_last_bar=False,
Expand All @@ -97,3 +70,4 @@

print("\nDone.\n", classSecurities_ok)

qpProvider.CloseConnectionAndThread() # Закрытие соединения с Quik

0 comments on commit 331bc6d

Please sign in to comment.