Сначала я пытался бэктестить системы в 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')
этот пример продавай в мае и уходи.
он работает).
конечно не 100% в год.
но альфа есть до сих пор.
и есть причина почему он продолжит работать.
и есть экономическая причина почему продолжит в будущем.
внешняя относительно рынков.
хотя конечно 100% в год не дает )
хорошо затыкает рот тем кто говорит что алго не работает в принципе.
потому что будущее не определено.
Сентябрь вон под «гоу эвэй» куда больше подходил и подходит, однако о нём таких баек выдумывать уже не стали.
продавая 1 мая и покупая 1 октября вы прямо в 21 году выкинули 2 убыточных месяца.
и оставили только прибыльные.
и при этом говорите что не работает.
как так?
цель всех алгоримов отдать риск и взять ревард.
вот стратегия отдает риск.
Это даже не оспаривая ваше 1 октября, ибо это лишь ваша натяжка постфактум (да ещё лишь этого конкретного одного года). Т.к. в оригинале сентябрь в перерыв отнюдь не включается.
но цель отдать риск и взять ревард.
а не бороться с минусом и принимать риски.
даже тот же етф на sp500 имеет просадку историческую 51%
что очень много.
по этому его приходится разбавлять облигациями чуть не на 50%.
облигациями которые в среднем НЕ ПОКРЫВАЮТ инфляцию.
а просадка по этому алгоритму меньше.
а значит до тех-же рисков разбавлять планово-убыточными облигациями надо меньше.
+ вы 5 месяцев не в риске.
и цена этих денег тоже 0.
потому что вы можете собрать из них синтетику и покрыть инфляцию.
(почти)
ну и так далее.
это работающий пример.
который работает.
но 100% годовых не приносит.
свою функцию ПРИМЕРА — тыкать носом тем кто говорит что алго не работает потому что будущее не определено он выполняет.
В том и дело, что как раз НЕ выполняет. Совокупный плюс за оригинальные 4 мес(ибо в оригинале как раз май+лето) с лихвой перекрывает историческую среднегодовую инфляцию в долларе(она чуть более 2% годовых) за этот же срок. Что показывает, что регулярный ежегодный 4х месячный выход из акций был нецелесообразен, несмотря на опис. вами волу. Взятую, как я понял, лишь от одного 2008го.
Вообще, перед тем как соберетесь таки кого-то высокомерно «тыкать носом», хотя бы сами разберитесь с вопросом, а то тыкать начнут уже вас 😉
Удачи!
для того чтобы ткнуть носом нужен 1 Любой! пример.
(для доказательства существования нужно любой пример на выбор того кто доказывает существование)
я его привел.
это не такой пример как думал Дмитрий — значит он не подходит?
(«продавай в мае и уходит » я нигде не сказал когда приходить, вы придумали это за меня.)
Показывать что алго работает: берите и получайте доход.
Уменьшайте риски.
(а уменьшить риск важнее чем получить больше доход)
Вот вам базовый пример.
Вызывает у людей буквально ненависть!.
зато торговать руками как зомби!
буквально как зомби.
это то что нужно? ).
Даже отдельный май ПЛЮСОВОЙ — что прекрасно видно из обоих таблиц. Это притом, что за эти полвека в США было аж 3 мощнейших кризиса на фонде. Куда как тяжелее всяких короновирусов.
А про руки вообще не ко мне. Я исключительно фундаменталист, да ещё и долгосрочник, живущий от дохода с инвестпортфеля. Над сливами типичного трейдунья могу лишь недоумевать, а уж никак не самозабвенно «торговать руками».
просто вокруг прибыльных идей много лжи.
никому не интересно чтобы прибыльные и простые идеи попадали в общество.
А если учитывать, то на длинной истории торгов возникают неприемлемо большие интервалы без прибыли. И от таких систем мне не нужны никакие сигналы ни на какие девайсы.
Для таких результатов вполне хватает программы WealthLab со скриптами на C#.
в конце вы получаете алго который стоит вам примерно 100к в год лицензии.
чтобы просто работать.
один коннектор стоит примерно 50к в год.
к одному брокеру.
а брокеров как минимум 2.
потому что нужно два — для рискменеджмента.
плюс если вы торгуете долго у вас всегда несколько разных счетов.
иис, жены, брата, подруги друга.
а там 50к за счет! у одного брокера.
Коннекторы — отдельный вопрос.
и не только том.
C#
пишу )
а вот идеи тестирую на pine и python
потому что пишется тест быстрее в разы.
[*********************100%***********************] 1 of 1 completed
Traceback (most recent call last):
File «C:\Users\cloud\PycharmProjects\MyTradeBot\MyBot.py», line 40, in <module>
qs.reports.html(returns, 'MSFT', output='stats.html', title='SMA Cross') # формируем репорт в quantstats, вместо бенчмарка SPY используем buy&hold MSFT
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\quantstats\reports.py», line 87, in html
benchmark = _utils._prepare_benchmark(benchmark, returns.index, rf)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\quantstats\utils.py», line 269, in _prepare_benchmark
benchmark = benchmark_prices.reindex(new_index, method='bfill') \
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\pandas\core\series.py», line 5094, in reindex
return super().reindex(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\pandas\core\generic.py», line 5289, in reindex
return self._reindex_axes(
^^^^^^^^^^^^^^^^^^^
File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\pandas\core\generic.py», line 5304, in _reindex_axes
new_index, indexer = ax.reindex(
^^^^^^^^^^^
File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\pandas\core\indexes\base.py», line 4412, in reindex
indexer = self.get_indexer(
^^^^^^^^^^^^^^^^^
File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\pandas\core\indexes\base.py», line 3912, in get_indexer
return self._get_indexer_non_comparable(target, method=method, unique=True)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\pandas\core\indexes\base.py», line 6182, in _get_indexer_non_comparable
raise TypeError(f«Cannot compare dtypes {self.dtype} and {other.dtype}»)
TypeError: Cannot compare dtypes datetime64[ns, America/New_York] and datetime64[ns]
Process finished with exit code 1