
К сожалению, в торговой системе QUIK отсутствует тестировщик стратегий, наподобие Metatrader. Поэтому приходится искать отдельную программу. Конечно, платные типа Amibroker, WealthLab очень даже удобны… но цена. Да и месяца триала не хватит для того чтобы понять, стоит продолжать торговать на рынках или найти новое увлечение.
Потому пошел на Гитхаб и стал серфить опенсоурсные и бесплатные аналоги тестеров стратегий. Их вполне хватает там. Некоторые сразу не пошли/не понравились, кое-что решил оставил на будущее ознакомление, а пока решил разобраться с Бэктрейдером на Питоне https://github.com/mementum/backtrader
Завелся сразу, правда из-за новой версии matplotlib отказался выводить графики (импорт warnings), но быстро нашлось решение. Обильная документация на английском языке, большое сообщество — все это убедило в долговечности проекта и что стоит потратить силы на его изучение.
Для ознакомления вполне хватит поставщиков или демо файлов в поставке. Но захотелось быть ближе к реальности и использовать котировки из QUIK. Оказалось не сложно, если использовать формат csv, который можно получить с помощью QMinEditor. Написал скрипт quikcsv.py, поместил его в каталог \backtrader\feeds. Для теста использовал учебный пример с небольшой модификацией testQuik.py чтобы увидеть что импортируется (в моем случае TQBR_VTBR_15).
Итак, с помощью QMinEditor создаем желаемый архив с котировками (сразу возникает мысль, что со временем придется написать скрипт для «живого» импорта либо с помощью LUA либо сразу с файлов DAT, правда последнее не рекомендуется разработчиками Arqatech).
И результат работы
Не смотрите на разные тикеры, делал скрины в разное время.
Сами скрипты:
quikcsv.py
#!/usr/bin/env python # -*- coding: utf-8; py-indent-offset:4 -*- ############################################################################### # # Copyright (C) 2015-2020 Daniel Rodriguez # Copyright (C) 2015-2020 Daniel Rodriguez # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################### from __future__ import (absolute_import, division, print_function, unicode_literals) from . import GenericCSVData class QUIKCSVData(GenericCSVData): ''' Парсит CSV подготовленный QMinEditor ''' params = ( ('dtformat', '%Y%m%d'), ('tmformat', '%H%M%S'), ('datetime', 2), ('time', 3), ('open', 4), ('high', 5), ('low', 6), ('close', 7), ('volume', 8), ('openinterest',-1), )
testQuik.py
from __future__ import (absolute_import, division, print_function, unicode_literals) import datetime # For datetime objects import os.path # To manage paths import sys # To find out the script name (in argv[0]) # Import the backtrader platform import backtrader as bt import backtrader.feeds.quikcsv as quikcsv # Create a Stratey class TestStrategy(bt.Strategy): def __init__(self): # Keep a reference to the "close"... line in the data[0] dataseries self.O = self.datas[0].open self.H = self.datas[0].high self.L = self.datas[0].low self.C = self.datas[0].close self.V= self.datas[0].volume def next(self): print('%s O %.6f, H %.6f, L %.6f, C %.6f, V %.6f' % (bt.num2date(self.datas[0].datetime[0]).strftime("%Y-%m-%d %H:%M"), self.O[0],self.H[0],self.L[0],self.C[0],self.V[0])) if __name__ == '__main__': # Create a cerebro entity cerebro = bt.Cerebro() # Add a strategy cerebro.addstrategy(TestStrategy) # Datas are in a subfolder of the samples. Need to find where the script is # because it could have been called from anywhere modpath = os.path.dirname(os.path.abspath(sys.argv[0])) print (modpath) datapath = os.path.join(modpath, 'datas/TQBR_VTBR_15.txt') # Create a Data Feed data = quikcsv.QUIKCSVData( dataname=datapath, # Do not pass values before this date #fromdate=datetime.datetime(2000, 1, 1), # Do not pass values before this date #todate=datetime.datetime(2000, 12, 31), # Do not pass values after this date reverse=False) # Add the Data Feed to Cerebro cerebro.adddata(data) # Set our desired cash start cerebro.broker.setcash(100000.0) # Print out the starting conditions print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) # Run over everything cerebro.run() # Print out the final result print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())