Сначала я пытался бэктестить системы в TradingView и этого было достаточно для быстрой оценки торговых гипотез, но оказалось, что мало просто знать, где купить и где продать. Не менее важно понимать,
сколько купить или продать и для этого нужны другие инструменты.
Зачем Python?
Лично мне он показался удобнее. Например, можно быстро подключить telebot и система начнёт отправлять сигналы прямо в телегу на все девайсы. Работать со скриптами можно даже на айпаде где-нибудь в дороге, тоже плюс.
Самая простая система, которую можно потестить это пересечение двух скользящих средних: если быстрая SMA пересекает медленную вверх, то покупаем, а если вниз, то закрываем открытую позицию, шортить рынок не будем. Комиссии, проскальзывание и прочие расходы пока не учитываем, нужно начать с какой-то основы.
Что потребуется?
— backtrader для логики торговой системы
— quantstats для формирования отчёта
— Jupyter Notebook, если нужно удобнее редактировать код
— Сам Python и установщик пакетов pip
Сам код достаточно простой:
import datetime
import webbrowser
import backtrader as bt
import quantstats as qs
import yfinance as yf
class SmaCross(bt.SignalStrategy):
params = dict(
pfast=50, # период быстрой средней, 50 свечей
pslow=200 # 200 свечей для медленной средней
)
def __init__(self):
sma1, sma2 = bt.ind.SMA(period=self.p.pfast), bt.ind.SMA(period=self.p.pslow) # используем простые скользящие средние
self.crossover = bt.ind.CrossOver(sma1, sma2)
def next(self):
if not self.position: # если позиция не открыта системой
if self.crossover > 0: # если быстрая SMA пересекает медленную вверх
self.buy() # открываем длинную позицию
elif self.crossover < 0: # во всех остальных случаях закрываем открытую позицию
self.close()
data = bt.feeds.PandasData(dataname=yf.download('MSFT', '2007-02-02', '2021-09-01', auto_adjust=True)) # в качестве примера берём MSFT, 2008 год тоже торгуем
cerebro = bt.Cerebro()
cerebro.broker.setcash(10000) # начальный депозит 10 000 денег
cerebro.addsizer(bt.sizers.FixedSize,stake = 100) # размер позиции 100 лотов
cerebro.adddata(data)
cerebro.addstrategy(SmaCross)
cerebro.addanalyzer(bt.analyzers.PyFolio, _name='PyFolio') # PyFolio, но quantstats его тоже отрендерит
results = cerebro.run()
strat = results[0]
portfolio_stats = strat.analyzers.getbyname('PyFolio')
returns, positions, transactions, gross_lev = portfolio_stats.get_pf_items()
returns.index = returns.index.tz_convert(None)
qs.reports.html(returns, 'MSFT', output='stats.html', title='SMA Cross') # формируем репорт в quantstats, вместо бенчмарка SPY используем buy&hold MSFT
webbrowser.open('stats.html') # рендерим репорт в html и открываем в новой вкладке
В результате quantstats должен сгенерировать примерно такой отчёт:

MSFT это трендовый инструмент и система на основе скользящих средних будет иметь положительное матожидание, однако она существенно проиграет Buy & Hold, поскольку средние отстают от рынка. Такая система также 83% времени находится в рынке, но при этом её максимальная просадка составляет 19.45% и это заметно ниже, чем buy & hold, который даёт просадку до 57.94%. Возможно, система могла бы использовать кредитное плечо для повышения доходности.
Диаграммы финансовых результатов явно указывают на необходимость сокращения убытков:

Данные берутся с 2007 года, но система начинает торговать только в 2009:

Теперь у нас есть аналог «Hello, world!», только для алготрейдинга и в нём уже есть что улучшить. Можно ещё отрендерить свечной график backtrader со сделками, но Jupyter это не поддерживает:
cerebro.plot(style='candlestick')
А если учитывать, то на длинной истории торгов возникают неприемлемо большие интервалы без прибыли. И от таких систем мне не нужны никакие сигналы ни на какие девайсы.
Для таких результатов вполне хватает программы WealthLab со скриптами на C#.