Стратегии
Точный перенос стратегии Oil Money от je-suis-tm: 50-дневный OLS для XOP на USO, условие валидности R2>0.7, LONG при закрытии выше подобранного+2 сигма / SHORT ниже подобранного-2 сигма, выход по счётчику через 10 баров, симметричный стоп 3.7% (XOP.USEQ торгуется, USO.USEQ регрессор, 1-DAY, лонг-шорт, неизменные параметры по умолчанию)
Итог: Отменено
OilMoneyXopUsoRegressionBreakout
Сводка по итогам
Эта стратегия переносит правило пробоя остатка Oil Money на XOP и USO с неизменными исходными параметрами; после 2 итераций она воспроизвела 144 сделок предварительного исследования. Результат на всей истории был слабым: +21.3%, коэффициент Шарпа 0.139, PF 1.053, просадка 35.4% выше заранее установленного лимита 30%. Вневыборочные данные дали отрицательный результат: коэффициент Шарпа отложенной выборки -0.37, около 27% потеряно за 2025-26, а сигнал IC неотличим от шума. Аналитик отказался от этой операционализации как от premise_falsified, не отвергая исходную версию автора на NOKJPY/Brent.
Гипотеза
Пользователь запросил точный перенос, поэтому все параметры по умолчанию зафиксированы, а набор настраиваемых параметров пуст. Адаптированы только инструмент и единицы стопа; обоснование приведено выше. Этот выбор заполняет недостаточно представленные категории: площадка USEQ с 6%, структура сигналов для пар/нескольких инструментов, лонг-шорт при ограничении 17% против 55% только для лонга, а также актив (XOP/USO) практически без истории в корпусе. Он не похож на перечисленные неудачные стратегии: здесь нет Dual Thrust, z-score, RSI2 или логики Черепах, а сигнал основан на проверке валидности межрыночной регрессии. Порог просадки установлен на 30%, поскольку для одиночной позиции 1x в ETF с годовой волатильностью около 40% нужен реалистичный уровень.
Реализация
Точный перенос стратегии Oil Money от je-suis-tm на XOP.USEQ относительно USO.USEQ с барами по 1 дней. Пока позиция не открыта и модель ещё не обучена, подбирается 50-барная OLS для XOP на USO по предыдущим барам; модель принимается только если R2 > 0.7. Затем a, b и стандартное отклонение остатков для генеральной совокупности фиксируются. Открывается LONG, если закрытие XOP выше подобранного значения плюс 2 сигма, и SHORT, если оно ниже подобранного значения минус 2 сигма; оба значения рассчитываются по текущему закрытию USO. Позиция закрывается по правилу времени со счётчиком в 10 баров (12-й бар после входа) или при симметричном движении 3.7% от закрытия бара сигнала; после каждого выхода модель подбирается заново. Рыночные заявки исполняются на открытии следующей сессии.
Результаты верификации
Возвращать 1 из min_bars_required(), поскольку стратегия сама проверяет условие len(_pairs) >= train_len. Другой вариант — заполнить _pairs выровненной историей, уже находящейся в self._bars и self._extra_bars[x], при первом вызове.
min_bars_required() возвращает train_len+1 = 51. Базовый шаблон пропускает calculate_signal, пока не накоплено 51 баров основного ряда, а _pairs заполняется только внутри calculate_signal. Поэтому первые 50 баров отбрасываются, а первая подгонка OLS происходит примерно на баре 101, а не на баре 51, как в исходнике (`for i in range(train_len, len(df))`). Правила торговли не меняются, но фактический период прогрева составляет около 100 баров. Это превышает установленное контрактом значение оценки warmup_bars=60, поэтому примерно первые 40 баров каждого окна reset_with_warmup не могут торговать. Такая же задержка возникает после каждого перезапуска реальной или бумажной торговли.
Изменения не нужны. Проверь, что в полном бэктесте entry_not_filled == 0 и dropped_entry_inflight == 0.
Сверка фиктивного входа — дополнение, которого нет в исходнике. Если входящий ордер отклонён, на следующем выровненном баре holding, trained и counter сбрасываются; этот бар считается баром выхода (без повторной подгонки и входа). Это разумный учёт исполнения. В бэктесте TradeTick на следующем открытии исполняет ордер до запуска on_bar бара N+1 (src/backtesting/next_open.py), поэтому такой случай должен возникать только при реальном отказе. Следи за entry_diag.entry_not_filled: ненулевое значение означает, что размер позиции всё ещё упирается в проверку маржи.
Обзор бэктеста
- Шарп
- 0,14
- Общая доходность
- 21,34%
- Максимальная просадка
- 35,41%
- Всего сделок
- 144
- Доля прибыльных
- 52,1%
- Профит-фактор
- 1,05
Предыдущее исправление реализации сработало. Теперь стратегия торгует на всей истории 2006-2026 (годовые доходности рассчитаны для каждого года): 144 закрытых сделок (80 длинных, 64 коротких). Это совпадает с числом 144 в предварительном расчёте руководителя исследования, значит, машина состояний реализована согласно описанию. entry_not_filled и denied_margin составляют по 5 и корректно исключены.
Экономические показатели превышают минимальный порог USEQ на надёжной выборке: avg_trade_return_pct составляет 0.302% при минимуме 0.05% (предпочтительно 0.10%). Ожидаемая прибыль — +$148 на сделку, PF 1.053, общая доходность +21.3% после моделирования воздействия в размере $9.1 тыс. и учёта стоимости займа $751. Ошибок учёта нет: издержки включены в движок, величина остатков составляет около 0.
end_unrealized_pct составляет 0, поэтому заголовочный показатель полностью реализован. Размер позиции — около 94% капитала, как предусмотрено контрактом.
Преимущество очень мало и статистически неразличимо. Коэффициент Шарпа — 0.139 (95% CI -0.31 до 0.57), PSR составляет 0.60, а IC исполненных сигналов — -0.034 (t = -0.7). PF от 1.053 намного ниже минимального уровня качества 1.3.
Максимальная просадка составляет 35.4% при заранее зарегистрированном ограничении контракта 30%; длительность просадки — 3,506 дней. В терциле с высокой волатильностью убыток составляет 25.3%. 2025 (-18.4%) и 2026 YTD (-9.5%) — худшие годы, поэтому опасения QA по поводу недавнего рыночного режима отчасти подтверждаются на полной истории. На уровне отдельных сделок полная история этого не подтверждает: здесь +0.30% против -0.167% в коротком тестовом периоде.
Смоделированное рыночное воздействие составляет долю 29% от валовой прибыли. Ёмкость — около $1.18 млн.
Исполнение на следующем открытии ухудшает преимущество по сравнению с исполнением по тому же закрытию, что и в источнике. В предварительном исследовании прибыль на сделку составляла +0.38% при PF 1.16 без издержек; в этом запуске — +0.30% при PF 1.05. Это согласуется с потерей части прибыли за ночь при входе на пробое. Этот механизм отдельно не проверялся.
QA спросил об обратном сплите акций компании USO 2020. Проверка входных данных не выявила пропущенных или некорректных баров; регрессия повторно подгоняется на скользящем окне из 50 баров, но я независимо не подтвердил, что ряд USO скорректирован на сплит по 2020-04.
Анализ
Реализация точная. Число закрытых сделок — 144 (80 длинных, 64 коротких) — точно совпадает с числом 144 в предварительном исследовании руководителя исследования. Учёт корректен, end_unrealized_pct составляет 0, признаков артефакта нет.
Порог комиссии пройден: avg_trade_return_pct составляет 0.302% при пороге USEQ +0.05% (предпочтительно 0.10%); издержки не являются причиной неудачи.
holding_threshold, band_sigma, кредитное плечо и буферы размера позиции находятся на широких плато при анализе чувствительности.
На истории длиной 20 лет преимущества нет. Коэффициент Шарпа за весь исторический период составляет 0.139 (95% CI -0.31–0.57), а PF равен 1.053. Коэффициент прибыли равен 0.97 при доле прибыльных сделок 52%, что означает практически нулевое математическое ожидание. Фактор восстановления равен 0.60, а коэффициент Кальмара — 0.027.
Максимальная просадка составляет 35.4%, что выше заранее зарегистрированного лимита 30%; просадка длилась 3,506 дней. Два последних обучающих окна walk-forward-анализа отклонены из-за нарушения ограничения 30% DD (34.7% и 35.4%), поэтому для последнего окна нет допустимого кандидата. Результат — insufficient_candidate_coverage (отклонено).
Внешние коэффициенты Шарпа walk-forward-анализа OOS: -0.09, -0.41, -0.04 и +0.74, затем два окна с нулевым результатом. Положительный результат получен лишь в 1 из 4 оценённых окон.
Отложенная выборка (2022-09-18 — 2026-10-09, 1,482 дней, 32 сделок; статистическая мощность достаточна) показала коэффициент Шарпа -0.37 и DD 29.4%. 2025 составляет -18.4%, а 2026 — -9.5% YTD.
IC исполненного прогноза составляет -0.034 (t = -0.7, n = 420), поэтому сигнал пробоя регрессионного остатка не несёт информации.
Стратегия убыточна в терциле повышенной волатильности (коэффициент Шарпа -0.14, -25.3%). Самый тяжёлый стрессовый период — тарифный шок 2025 при -13.2%.
Смоделированное рыночное воздействие составляет долю 29% от валовой прибыли.
Анализ чувствительности выявил резкие провалы для train_len (25 и 63 отрицательны; 45 и 51 близки к нулю) и stop_fraction. Базовый вариант опирается на шум, а не на устойчивое плато.
Заранее зарегистрированные прогнозы: выполнено 3 из 6. Доходность (21% против 40%), PF (1.05 против 1.10) и DD (35% против 30%) не оправдались.
только рекомендательный характер
История итераций
Возвращать 1 (или небольшое число) из min_bars_required(), поскольку calculate_signal уже проверяет условие len(self._pairs) >= train_len.
min_bars_required() возвращает train_len+1 = 51. Базовый шаблон полностью пропускает calculate_signal, пока не накоплено 51 баров основного ряда, поэтому _pairs начинает заполняться лишь на баре 51, а первая подгонка OLS происходит примерно на баре 101. Фактический прогрев занимает около 100 сессий, а не 50, как в исходнике. Это не меняет логику торговли; торговля просто начинается позже.
При необходимости сверяй _holding с cache.positions_open() в начале calculate_signal.
_holding задаётся в calculate_signal до появления заявки. Если базовая система отклонит вход (размер 0, минимальный номинал или заявка в обработке), внутреннее состояние будет указывать на открытую позицию, которой в действительности нет. Затем модель останется зафиксированной до фантомного выхода по времени или стопу примерно через 12 баров. При капитале 0.95x и сумме свыше $100 ETF такое практически никогда не случается.
Ничего не требуется; это соответствует источнику.
Стоп и проверка времени выполняются только по дневному закрытию; внутрибара стопа нет. Это соответствует источнику (стоп по закрытию), поэтому перенос точный, однако при гэпе стоп 3.7% может быть превышен.
Сводка по итогам
Устранить минимальную комиссию за сделку недостаточно: пробой регрессионного остатка, сигнал которого не содержит измеримой информации (IC близко к нулю, PF около 1.05), не выдержит проверку вне выборки или ограничения по просадке.
По итогам проверки бэктеста оптимизация была одобрена, однако затем аналитик отказался от неё, заявив, что premise_falsified. После учёта издержек преимущества не было, IC сигнала оказался -0.034 (t=-0.7), отложенная выборка дала отрицательный результат, а просадка превысила заранее зарегистрированный предел 30%, поэтому допустимых кандидатов не осталось (insufficient_candidate_coverage). Все параметры были зафиксированы контрактом, поэтому перебирать их было невозможно.
Точный перенос стратегии «Oil Money» от je-suis-tm: XOP регрессируется на USO вместо NOKJPY на Brent; модель 50-дневная, OLS, используется только при R2 > 0.7. Длинная позиция открывается, когда закрытие XOP выше подогнанного значения на +2 сигма, короткая — ниже подогнанного значения на -2 сигма; выход — по счётчику 10 баров и стопу 3.7%.
За период 2006-2026 бэктест дал 144 сделок (80 длинных, 64 коротких), общую доходность +21.3%, коэффициент Шарпа 0.139 (CI -0.31 до 0.57), фактор прибыли 1.053, avg_trade_return_pct 0.302% и максимальную просадку 35.4%. На отложенной выборке (2022-09 — 2026-10, 32 сделок) коэффициент Шарпа составил -0.37; положительный результат был только в 1 из 4 оценённых окон OOS walk-forward-анализа.
Анализ
Oil Money Trading backtest
Stratmill — это инструмент для исследований и бумажной торговли, а не финансовая консультация или брокер. Результаты бэктестов и бумажной торговли являются гипотетическими. Торговля сопряжена с риском убытков.