1. Что было сделано?
Запущено 5 разных стратегий.
Прошло 4 недели.
2. В каком состоянии сейчас?
По стратегии 1 все ок, доход на данный момент 33.7% Подробности здесь
По стратегии 2 все ок, доход на данный момент 42.3% Подробности здесь
Приветствуем наших постоянных читателей и только вошедших, новых подписчиков. Надеемся, что здесь вы найдете что-то полезное для себя или уже нашли и следите за обновлениями)
Мы решили выпустить серию статей, посвященных объемному анализу и свечным паттернам.
У большинства трейдеров сформировались уже свои ассоциации при виде той или иной свечи. Кто-то определенные ситуации трактует как разворот рынка, другие же наоборот предполагают продолжение тенденции. Смысл здесь кроется больше в «предыстории» этого движения, а не в самих свечах. Давайте рассмотрим теорию на практике, на конкретных примерах.
В качестве примера возьмем большое тело свечи с крупным объемом(рисунок выше). Следом за ней идет свеча в обратную сторону, но по размеру больше, чем первая. То есть если закрытие второй ниже, чем открытие предыдущей на умеренном объеме – следом рынок развернется и пойдет в другую сторону. А теперь проверим частоту таких случаев, и приводят ли они к профиту (и как часто это происходит).
# В КВИКе запускаем луа-скрипт QuikLuaPython.lua import socket import threading from datetime import datetime, timezone import pandas as pd import finplot as fplt fplt.display_timezone = timezone.utc class DeltaBar(): def __init__(self): self.df = pd.DataFrame(columns='date_time open high low close delta delta_time_sec'.split(' ')) self.df.loc[len(self.df)] = [0, 0, 0, 0, 0, 0, 0] def parser(self, parse): if parse[0] == '1' and parse[1] == 'RIH1': if abs(self.df.iloc[len(self.df) - 1]['delta']) >= 500: self.df.loc[len(self.df)] = [0, 0, 0, 0, 0, 0, 0] # Добавляем строку в DF self.df.iloc[len(self.df) - 1]['close'] = float(parse[4]) # Записываем последнюю цену как цену close бара if self.df.iloc[len(self.df) - 1]['date_time'] == 0: self.df.iloc[len(self.df) - 1]['date_time'] = \ datetime.strptime(f'{parse[7]} {parse[8][0:-1]}', "%d.%m.%Y %H:%M:%S.%f").replace(microsecond=0) if self.df.iloc[len(self.df) - 1]['open'] == 0: self.df.iloc[len(self.df) - 1]['open'] = float(parse[4]) if float(parse[4]) > self.df.iloc[len(self.df) - 1]['high']: self.df.iloc[len(self.df) - 1]['high'] = float(parse[4]) if (float(parse[4]) < self.df.iloc[len(self.df) - 1]['low']) or \ (self.df.iloc[len(self.df) - 1]['low'] == 0): self.df.iloc[len(self.df) - 1]['low'] = float(parse[4]) if parse[5] == '1026': self.df.iloc[len(self.df) - 1]['delta'] += float(parse[6]) if parse[5] == '1025': self.df.iloc[len(self.df) - 1]['delta'] -= float(parse[6]) self.df.iloc[len(self.df) - 1]['delta_time_sec'] = \ datetime.strptime(f'{parse[7]} {parse[8][0:-1]}', "%d.%m.%Y %H:%M:%S.%f") - \ self.df.iloc[len(self.df) - 1]['date_time'] self.df.iloc[len(self.df) - 1]['delta_time_sec'] = self.df.iloc[len(self.df) - 1]['delta_time_sec'].seconds def service(): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(('127.0.0.1', 3587)) # Хост-этот компьютер, порт - 3587 while True: res = sock.recv(2048).decode('utf-8') if res == '<qstp>\n': # строка приходит от клиента при остановке луа-скрипта в КВИКе break else: delta_bar.parser(res.split(' ')) # Здесь вызываете свой парсер. Для примера функция: parser (parse) sock.close() def update(): df = delta_bar.df # Меняем индекс и делаем его типом datetime df = df.set_index(pd.to_datetime(df['date_time'], format='%Y-%m-%d %H:%M:%S')) # print(delta_bar.df) # pick columns for our three data sources: candlesticks and TD candlesticks = df['open close high low'.split()] volumes = df['open close delta_time_sec'.split()] if not plots: # first time we create the plots global ax plots.append(fplt.candlestick_ochl(candlesticks)) plots.append(fplt.volume_ocv(volumes, ax=ax.overlay())) else: # every time after we just update the data sources on each plot plots[0].update_data(candlesticks) plots[1].update_data(volumes) if __name__ == '__main__': delta_bar = DeltaBar() # Запускаем сервер в своем потоке t = threading.Thread(name='service', target=service) t.start() plots = [] ax = fplt.create_plot('RIH1', init_zoom_periods=100, maximize=False) update() fplt.timer_callback(update, 2.0) # update (using synchronous rest call) every N seconds fplt.show()
Приветствуем Всех!
Кто торгует через TSLab, знают о ситуациях в «реверсных» алгоритмах, когда необходимо переворачивать позу. Сначала выставляется закрытие для текущей позиции, далее открытие для новой. В большинстве случаев, конечно это происходит крайне быстро и без проблемно, но любая транзакция имеет задержки, пусть 100-300мс но все же задержки есть. Этого не избежать в принципе никак. Но можно перестроить алгоритм, таким образом, чтобы вместо закрытий позиций, были просто «задвоеные» заявки. То есть получается, открыли лонг, далее например открываем шорт +1 к лонгу.
В итоге получим просто перевесы в размере позиции, то есть лонгов 144 шортов 145, в итоге текущая позиция просто 1лот шорт. Это слегка не привычно с точки зрения восприятия, но главное избегаем двух транзакций!
Скрипт построен на фьючерсе ртс, индикаторов в принципе нет, простенький паттерн используется для демонстрации системы.
Так выглядит график при таком «фокусе»
Доброго времени суток, зашедшие впервые и уже постоянные читатели нашего блога!
Многие трейдеры как опытные, так и начинающие проходят через определенный этап – пробы новых алгоритмов. А что если открыть шорт по ртс, а по сберу лонг? И закрыть позиции только в том случае, когда они обе дают нам плюс? Подобный пример мы и разберем в сегодняшней статье.
Итак, открываем позицию по РТС в лонг, если текущий бар выше, чем каждый из предыдущих 10 баров (пример без глубокого смысла, берем за отправную точку). Затем ставим тейк профит в размере 2,5% и стоп лосс 1% от цены входа. Логика агоритма достаточно проста и не содержит скрытых смыслов. Но если вы делаете более «умную» точку входа, то, теоритически, улучшаете показатели. Отрезок 2018 года был выбран нами специально, так как он практически весь был в боковике. При этом график дохода предсказуемо плох.
Думаю, что каждый трейдер стремится не совершать сделок во время боковика и открывать максимально возможное количество позиций во время тренда. Базовая торговая идея предлагает компромисс. Он звучит так: минимизировать сумму убытков во время боковика и максимизировать сумму доходов на тренде.
В период с 26 января по 9 февраля на рынке Si было несколько периодов и боковика, и тренда. ТС «Парус», которая торгуется на «Полигоне для новичка», использует алгоритм, построенный на базовой торговой идее. В данном видео я рассказываю, как «Парус» работал на вышеуказанном периоде, и помогла ли ему базовая торговая идея.
Про то, что такое «Полигон для новичка», можно узнать здесь smart-lab.ru/blog/360646.php
П.С. На всякий случай, моя книга «Восемь правил выживания на рынке акций», см. здесь author.today/work/104250
Всем добрый вечер!
В последнее время на форуме было опубликовано несколько статей по поводу тестирования алгоритмических стратегий, приблизительно следующего содержания — «На тестах все хорошо и алгоритм дает прибыль +100%, в реальной жизни все плохо — и алгоритм дает убытки -100%».В этом посте я попытаюсь вставить свои «пять копеек», почему так случается. С торговлей на бирже знаком с 1994 года. Не скажу, что весь этот опыт был удачный, скорее совсем наоборот и поэтому с 2016 года занимаюсь разработкой алгоритмических стратегий, ну или по простому — пишу торговый собственный робот. В реальных торгах участвую, но только с помощью собственного робота. Разработка роботов — это не бизнес, а скорее хобби, пишу для себя. Торгую на ММВБ через Quik. Робот написан на C#, для тестирования использовал данные с сайтов finam и pitrading (покупал).
Так как я сам разработчик кода, то мне легко внести небольшие коррекции в свой же алгоритм и провести небольшой эксперимент. Я взял исторические минутные данные (OHLC) по трем инструментам — Apple, AUD/USD и XAUG/ USD за последние 4 года и рассмотрел три варианта заключения сделок при тестировании: