Перейти к содержимому
Все стратегии

Стратегии

Точная адаптация je-suis-tm 'RSI Pattern Recognition': только короткая позиция по фигуре «голова и плечи» на дневных закрытиях (25-барное окно); выход, когда RSI(14) растёт более чем на 4 пунктов или после 5 дней удержания, на F.USEQ (FCAU-аналог US, автопроизводитель)

Итог: Отменено

RsiHeadShouldersShortPortF

Сводка по итогам

RsiHeadShouldersShortPortF перенёс на Ford ценовой детектор коротких позиций по фигуре «голова и плечи» из кода je-suis-tm; выход по RSI/времени и исполнение на открытии следующей сессии. Проведено две итерации. Бэктест дал 197 закрытых коротких позиций, чистую доходность -89.25% и коэффициент Шарпа -0.335. Убытки возникали до издержек и во всех режимах волатильности, поэтому проверка бэктеста завершилась отказом до оптимизации и последующих проверок.

Гипотеза

Точный перенос функции pattern_recognition() из открытого исходного кода «RSI Pattern Recognition backtest.py» (репозиторий quant-trading, Apache-2.0; авторство: je-suis-tm). В файле две функции сигналов. Эта гипотеза проверяет функцию pattern_recognition() из заголовка: детектор фигуры «голова и плечи» TOP, который SHORTS, с выходом на основе RSI. Другая функция, signal_generation(), — обычный сигнал состояния перекупленности/перепроданности RSI 30/70; main() только строит по нему график, он NOT часть этого……Показать большеСвернуть

Точный перенос функции pattern_recognition() из открытого исходного кода «RSI Pattern Recognition backtest.py» (репозиторий quant-trading, Apache-2.0; авторство: je-suis-tm). В файле две функции сигналов. Эта гипотеза проверяет функцию pattern_recognition() из заголовка: детектор фигуры «голова и плечи» TOP, который SHORTS, с выходом на основе RSI. Другая функция, signal_generation(), — обычный сигнал состояния перекупленности/перепроданности RSI 30/70; main() только строит по нему график, он NOT часть этого переноса. В комментариях к коду сказано, что паттерн определяется на RSI, но код на самом деле ищет его в ценовом ряду CLOSE и использует RSI только для выхода. Перенос следует коду: ценовые точки и выход RSI. На графике автора (S6) значения RSI нанесены в координатах ценовых точек. На иллюстрации TradingView в S2 показан медвежий разворотный свинг Уайлдера RSI: вершина A >70, откат B, более низкая вершина C <70, пробой уровня B вниз (D); это та же группа разворотных фигур на вершине. Остальные иллюстрации — общие примеры скользящих средних и настроек RSI; новых правил они не добавляют. Страницу Investopedia о фигуре «голова и плечи» (S4) и скрипт статистики Heikin-Ashi (S7) FAILED загрузить не удалось, поэтому их не читали. INDICATOR: Уайлдер RSI с запаздыванием=14 на дневных ценах закрытия. delta=Close.diff(), up=max(delta,0), down=max(-delta,0). Каждое плечо сглаживается функцией smma(x,n): out[0]=x[0], out[t]=(out[t-1]*(n-1)+x[t])/n. RS=smma(up)/smma(down), RSI=100-100/(1+RS). Начальное значение отличается от TradingView только в период разогрева. PATTERN SCAN (точная логика кода, проверяется при каждом дневном закрытии i, когда позиция не открыта; период=25): см. entry_logic. ADAPTATIONS (только площадка/инструмент): (1) В исходнике delta=0.2 задана в абсолютных долларах для FCAU, торговавшейся примерно по $7-18 (средняя цена около $11) за 2016-2017, поэтому 0.2 составляет примерно 1.8% цены. История F.USEQ с поправкой на дробление акций охватывает очень разные уровни цен, поэтому delta задана в масштабно-независимом виде: delta = delta_pct x Close[i], базовое значение delta_pct=0.018. Пороговые значения для головы и плеча остаются равны 1.1 x delta, как в исходнике. (2) Инструмент: FCAU снят с торгов (теперь Stellantis, которой нет в нашем наборе). Ближайший поддерживаемый аналог — F.USEQ (Ford): автопроизводитель с листингом на US, сопоставимым уровнем цены и многолетней историей дневных данных на площадке без комиссий USEQ, где разрешены короткие продажи с маржой Reg-T. (3) Исполнение: в исходнике сделки совершаются при закрытии бара. На USEQ решение, принятое при дневном закрытии, исполняется на открытии следующей сессии NEXT (реестр next_open_fill; same_close_fill не поддерживается); эта замена указана здесь. (4) Размер позиции: в исходнике его нет — только сигналы. Настройка платформы по умолчанию: номинал короткой позиции при входе равен 100% капитала счёта (1x, в пределах лимита Reg-T 2x), одна позиция одновременно, целое число акций. Стратегия работает только в шорт; сигнал исходника «LONG» означает только закрытие короткой позиции.

negative_expectancy: адаптация для дневного F.USEQ с порогом, независимым от масштаба, и исполнением на открытии следующей сессии существенно убыточна на 197 закрытых коротких позициях за период 1973–2026, включая результат до издержек. Базовый результат не даёт экономических оснований для двухчасового поиска параметров. Отклонена эта адаптированная реализация, а не пример FCAU автора, неудачные колебания RSI или стратегии «голова и плечи» в целом.

Реализация

Точная адаптация je-suis-tm pattern_recognition(): фигура «голова и плечи» определяется на дневных закрытиях за 25 баров (дельта = 1.8% цены, дельта головы/плеча 1.1x); открывается короткая позиция по F.USEQ. Позиция закрывается, когда значение Wilder RSI(14) превышает значение на входе более чем на 4 пунктов или после более чем 5 дней удержания.

Итерация 2 устраняет критический дефект QA. В заявке указывался размер ровно 100% от капитала. Решение принималось на закрытии, а исполнение происходило на открытии следующей сессии, поэтому гэп привел к исполнению сверх лимита начальной маржи. В первой короткой позиции было отказано, а зависшая запись о входе в обработке блокировала все последующие входы, поэтому сделок не было. Теперь position_size умножается на буфер margin_buffer (0.95, новый параметр исполнения, не подбиравшийся в ходе настройки). position_notional_pct_equity остается фиксированным на уровне 1.0. Буфер компенсирует ночные гэпы величиной до примерно 5%. Сканирование паттернов, RSI и логика выхода не изменены. Необязательная рекомендация QA по разогреву не применяется: она влияет только на инициализацию RSI во время разогрева, а разогрев оценки длительностью 250 баров это покрывает.

Результаты верификации

Для точного совпадения начальной обработки истории позволь calculate_signal обрабатывать бары с самого начала и сохрани условие допуска из исходника в should_enter.

Среда пропускает calculate_signal, пока не достигнуто min_bars_required. Поэтому инициализация RSI начинается на 40-м полученном баре, а не на первом, и closes_seen откладывает возможность входа до 79-го бара. Это отличается от начальной обработки истории в исходнике, хотя заданный период разогрева оценки в 250 баров значительно уменьшает различие RSI.

Проверь, что отклонённый вход сбрасывает состояние ожидающего ордера в среде, чтобы последующие сигналы могли допускаться.

Буфер размера позиции 0.95 дает запас для исполнения, но не может гарантировать принятие заявки после каждого ночного гэпа. Восходящий гэп более чем примерно на 5.26% все еще может превысить заданный лимит начальной маржи 1x.

На тестовом отрезке получено 21 закрытых коротких позиций, средняя доходность -1.932% и фактор прибыли 0.376. Анализ полной истории должен оценить фигуру и выход RSI; эти результаты не доказывают дефект корректности.

Обзор бэктеста

Шарп
-0,33
Общая доходность
-89,25%
Максимальная просадка
90,17%
Всего сделок
197
Доля прибыльных
38,6%
Профит-фактор
0,53

Все 197 закрытых сделок — SHORT, что соответствует заявленному направлению; среднее удержание — около шести календарных дней.

Аудит входных данных пройден, учет сходится, открытых позиций не осталось.

Экономическое опасение QA подтверждается: чистая средняя доходность сделки составляет -0.817% против порогового ориентира USEQ в +0.05%, значение PF — 0.534, коэффициент Шарпа — -0.335.

Убытки возникли до издержек: цены входа и выхода в записях сделок дают совокупный результат по цене около -$77,439 и среднюю доходность по цене -0.724% до учёта смоделированных издержек.

Все три режима волатильности убыточны. Общая доходность — -89.25%; просадка — 90.17%. Зафиксировано отрицательное математическое ожидание; отказ основан не на одной лишь просадке.

Доходность стратегии «купи и держи» составила +563.24%; на выборочных точках кривая показывает просадку около 95.10%. Этот лонговый бенчмарк дан для контекста стратегии только с короткими позициями; отказ основан на абсолютных убытках.

Указанные средний размер позиции и число баров удержания требуют отдельной проверки отчётности; отрицательная доходность по цене сама по себе подтверждает этот вердикт.

История итераций

Проверка не пройдена (уровень 4 — проверка QA) [класс=code_defect]: - [edge_concern] Только рекомендация. У источника нет стопа: короткая позиция с номиналом 100% капитала в одной акции, удерживаемая до 6 сессий, несёт риск гэпа вверх относительно лимита контракта по максимальной просадке 30%. Совпадения группируются в последовательные дни (например, с 2022-08-26 по 2022-09-09 и с 2023-02-13 по 02-17), поэтому независимых сигналов меньше, чем совпадений. Грубая оценка — около 370 совпавших дней по F с 1972 по……Показать большеСвернуть

Проверка не пройдена (уровень 4 — проверка QA) [класс=code_defect]: - [edge_concern] Только рекомендация. У источника нет стопа: короткая позиция с номиналом 100% капитала в одной акции, удерживаемая до 6 сессий, несёт риск гэпа вверх относительно лимита контракта по максимальной просадке 30%. Совпадения группируются в последовательные дни (например, с 2022-08-26 по 2022-09-09 и с 2023-02-13 по 02-17), поэтому независимых сигналов меньше, чем совпадений. Грубая оценка — около 370 совпавших дней по F с 1972 по 2026, или около 7 в год. Стоимость займа по F невелика (F — ликвидная акция). Нижняя граница спреда USEQ (~0.05%) несущественна для удержания в течение нескольких дней. - [critical] Стратегия не может торговать: position_size() запрашивает ровно 100% капитала в номинале при 1x (int(equity * 1.0 * 1.0 / close)), без запаса. При первом полном совпадении базовая проверка маржи отклоняет SELL. Я воспроизвёл это, запустив BacktestRunner на дневных данных F.USEQ с 2019-01-01 по 2026-10-01 с поставленной конфигурацией. Проблема не в поиске фигуры: автономный повторный запуск _scan по закрытиям F находит 54 совпавших дней начиная с 2020-03. В запуске entry_diag показывает entry_signaled=57, entries_submitted=57, denied_margin=1, dropped_entry_inflight=56, сделок нет. Причина: refuse_over_margin отклоняет первую короткую позицию. Базовый шаблон уже записал ордер как выполняющийся вход, а отклонённый ордер никогда не закрывается. Поэтому _entry_order_inflight() навсегда остаётся True и блокирует все последующие входы ('Blocked stacked entry ... still in flight'). Это объясняет ноль сделок в песочнице, результат которой назвали «неопределённым». Запуск на полной истории так же заблокируется при первом совпадении в 1972 и не даст сделок. (строка 193) — исправление: оставь запас маржи в position_size(), чтобы ордер прошёл проверку начальной маржи; например, shares = int(equity * notional_pct * lev * 0.97 / price) либо рассчитай размер по лимиту маржи. Это буфер размера позиции, а не изменение зафиксированной доли номинала: около 97-98% капитала по-прежнему составляет запрошенную контрактом короткую позицию на 1x капитала с плечом 100%. Запусти повторно и проверь, что entry_diag.denied_margin == 0 и появляются короткие сделки. (Примечание оператора/платформы, не исправление разработчика: базовый шаблон записывает вход в _inflight_entries до того, как refuse_over_margin сможет его отклонить. Один отклонённый ордер навсегда блокирует все последующие входы по этому инструменту. Это требует отдельного исправления в base_template.py.) - [warning] Базовый шаблон вызывает calculate_signal только при len(self._bars) >= min_bars_required() (40). Поэтому инкрементальный RSI инициализируется на баре 40, а не на первом закрытии, как в исходнике; closes_seen блокирует входы ещё на 40 баров, так что для входа нужно около 80 баров. Это влияет только на разогрев: сглаживание Wilder сходится, а оценка использует 250 баров разогрева. Несоответствия правил нет. (строка 66) — исправление: необязательно возвращай небольшое значение min_bars_required (например, 2) и сохрани условие closes_seen, чтобы состояние RSI начиналось с первого бара, как в исходнике. - [warning] should_exit() рассчитывает выход на основе entry_rsi = RSI на сигнальном баре, тогда как исполнение происходит на открытии следующей сессии. В источнике то же правило (используется RSI на сигнальном баре), а исполнение на следующем открытии — раскрытое вынужденное отклонение. Отмечено только для ясности. (строка 176) — исправление: не требуется.

Оставь запас маржи в position_size(), чтобы ордер прошёл проверку начальной маржи; например, shares = int(equity * notional_pct * lev * 0.97 / price) либо рассчитай размер по лимиту маржи. Это буфер размера позиции, а не изменение зафиксированной доли номинала: около 97-98% капитала по-прежнему составляет запрошенную контрактом короткую позицию на 1x капитала с плечом 100%. Запусти повторно и проверь, что entry_diag.denied_margin == 0 и появляются короткие сделки. (Примечание оператора/платформы, не исправление разработчика: базовый шаблон записывает вход в _inflight_entries до того, как refuse_over_margin сможет его отклонить. Один отклонённый ордер навсегда блокирует все последующие входы по этому инструменту. Это требует отдельного исправления в base_template.py.)

Стратегия не может торговать: position_size() запрашивает ровно 100% капитала в номинале при 1x (int(equity * 1.0 * 1.0 / close)), без запаса. При первом полном совпадении базовая проверка маржи отклоняет SELL. Я воспроизвёл это, запустив BacktestRunner на дневных данных F.USEQ с 2019-01-01 по 2026-10-01 с поставленной конфигурацией. Проблема не в поиске фигуры: автономный повторный запуск _scan по закрытиям F находит 54 совпавших дней начиная с 2020-03. В запуске entry_diag показывает entry_signaled=57, entries_submitted=57, denied_margin=1, dropped_entry_inflight=56, сделок нет. Причина: refuse_over_margin отклоняет первую короткую позицию. Базовый шаблон уже записал ордер как выполняющийся вход, а отклонённый ордер никогда не закрывается. Поэтому _entry_order_inflight() навсегда остаётся True и блокирует все последующие входы ('Blocked stacked entry ... still in flight'). Это объясняет ноль сделок в песочнице, результат которой назвали «неопределённым». Запуск на полной истории так же заблокируется при первом совпадении в 1972 и не даст сделок.

Необязательно: возвращай небольшое значение min_bars_required (например, 2) и сохрани условие closes_seen, чтобы состояние RSI начиналось с первого бара, как в исходнике.

Базовый шаблон вызывает calculate_signal только при len(self._bars) >= min_bars_required() (40). Поэтому инкрементальный RSI инициализируется на баре 40, а не на первом закрытии, как в исходнике; closes_seen блокирует входы ещё на 40 баров, так что для входа нужно около 80 баров. Это влияет только на разогрев: сглаживание Wilder сходится, а оценка использует 250 баров разогрева. Несоответствия правил нет.

Изменения не требуются.

should_exit() определяет выход на основе entry_rsi = RSI на сигнальном баре, а исполнение происходит на открытии следующей сессии. В исходном варианте делается то же самое (используется RSI на сигнальном баре), а исполнение на следующем открытии является раскрытым вынужденным отклонением. Отмечено только для ясности.

Сводка по итогам

Эта адаптированная реализация для Ford не имела исходного экономического обоснования для оптимизации параметров; ее отклонение не доказывает, что пример автора FCAU или более широкое семейство паттернов не работает.

По итогам проверки бэктеста принято решение отказаться: математическое ожидание было отрицательным ещё до учёта смоделированных издержек, а все три режима волатильности дали убыток. Оптимизация, анализ после оптимизации и оценка риска не проводились.

Открывались короткие позиции по Ford при вершинах «голова и плечи» на дневных закрытиях, с ценовым окном 25 баров, RSI(14), выходом по времени, порогами без привязки к масштабу и исполнением на открытии следующей сессии.

По 197 закрытым коротким позициям за период 1973–2026 чистая доходность составила -89.25%, коэффициент Шарпа — -0.335, а максимальная просадка — 90.17%. Средняя чистая доходность сделки составила -0.817%, доля прибыльных сделок — 38.58%, а фактор прибыли — 0.534.

Анализ

RSI Pattern Recognition: бэктест

Анализ

RSI%20Pattern%20Recognition%20backtest.py

Индекс относительной силы (RSI)

Скользящая средняя — Википедия

Bollinger%20Bands%20Pattern%20Recognition%20backtest.py

rsi%20head-shoulder%20pattern.png

Stratmill — это инструмент для исследований и бумажной торговли, а не финансовая консультация или брокер. Результаты бэктестов и бумажной торговли являются гипотетическими. Торговля сопряжена с риском убытков.