Импульс отраслевого фактора с коротким лагом: временной знак доходности спреда каждого сектора к SPY за последний месяц, длинно-короткий портфель с хеджем SPY (9 SPDR секторов + SPY, USEQ 1-DAY, ребалансировка каждые 21 сессий)
Итог: Отменено
IndustryFactorShortLagMomentumSpyHedged
Сводка по итогам
Стратегия IndustryFactorShortLagMomentumSpyHedged проверяла, продолжают ли отраслевые факторы (сектор ETF минус SPY) двигаться в том же направлении с лагом в один месяц. Использовался нейтральный к бете портфель с хеджем SPY, фиксированной валовой экспозицией 0.9 на сторону и стопом 8% на уровне портфеля. После 3 итераций полный бэктест всё ещё не удалось запустить: в XLK.USEQ дневных барах отсутствовали 1490 ожидаемых баров, включая запрошенные границы. Конвейер остановил запуск из-за сбоя данных, а не оценки стратегии; этапы проверки бэктеста, аналитики и риска не выполнялись. Гипотеза остаётся непроверенной; к ней можно вернуться после устранения пробела в данных XLK.
Источник: Falck и др., «Is Factor Momentum More than Stock Momentum?» (arXiv 2009.04824, 2020), аннотация. Проверяемое утверждение авторов: импульс факторов существует и во временном ряду, и в поперечном срезе. Также утверждается, что после учета импульса акций значимые коэффициенты Шарпа сохраняются только у реализаций, учитывающих LAST MONTH доходности факторов. Доходности отдельных акций обращаются к среднему на коротких лагах, а доходности факторов продолжают движение на всех лагах. На наших площадках нет ETF……Показать большеСвернуть
Источник: Falck и др., «Is Factor Momentum More than Stock Momentum?» (arXiv 2009.04824, 2020), аннотация. Проверяемое утверждение авторов: импульс факторов существует и во временном ряду, и в поперечном срезе. Также утверждается, что после учета импульса акций значимые коэффициенты Шарпа сохраняются только у реализаций, учитывающих LAST MONTH доходности факторов. Доходности отдельных акций обращаются к среднему на коротких лагах, а доходности факторов продолжают движение на всех лагах. На наших площадках нет ETF на факторы аномалий; мы проверили каталог, и все MTUM/QUAL/USMV/VLUE/IWD/IWF/RSP отсутствуют. Поэтому используем класс факторов, который можем честно построить по имеющимся данным: отраслевые факторы, каждый из которых определяется как доходность сектора ETF за вычетом доходности SPY. Девять исходных Select Sector SPDR (XLK, XLF, XLE, XLV, XLP, XLU, XLI, XLY, XLB) имеют USEQ баров 1-DAY с Dec-1998, то есть данные примерно за 27 лет. XLRE и XLC исключены из-за слишком короткой истории. На каждой 21-й сессии (считаем по барам, а не календарным датам) рассчитываем доходность каждого спреда за предыдущие 21 сессий: f_i = ln(P_i,t/P_i,t-21) - ln(SPY_t/SPY_t-21). Режим временного ряда: держать сектор i с весом sign(f_i)/9 x gross_fraction, а SPY — с весом, равным минус сумме весов секторов. Таким образом, позиция SPY нейтрализует рынок, и книга представляет собой чистую ставку на продолжение движения отраслевых факторов. Удерживать позиции 21 сессий, затем пересчитать. В аннотации также проверяется вариант поперечного среза: длинные позиции в верхних 3 спредах и короткие в нижних 3 по показателю f_i, с равными весами; позиция SPY нейтрализует остаток. Это один категориальный переключатель, поскольку обе реализации взяты из источника; дополнительных степеней свободы нет. Вселенная фиксирована: 10 инструментов, в пределах лимита примерно в 10 инструментов из урока L173; поэтому вычисления при каждой ребалансировке тривиальны (10 логарифмических доходностей). Отличие от LargeSmallCapMonthlyMomentumSpread в конвейере: там используется один спред размера компаний. Здесь книга из девяти отраслевых факторов, а конкретное утверждение статьи касается лага в 1 месяцев, когда разворот доходности акций и продолжение движения факторов действуют в противоположных направлениях. Что нужно подтвердить по полной статье: (1) окно формирования длиной 1 месяцев и месячный период удержания, здесь они предполагаются исходя из слов «доходности за последний месяц»; (2) ведут ли отраслевые факторы себя подобно их 72 факторам аномалий (Moskowitz-Grinblatt 1999 и Arnott и др. 2021 сообщают о таком же продолжении движения отраслевых факторов и факторов на коротких лагах); (3) пропускаются ли дни между формированием и удержанием (мы не пропускаем). Размер позиций: gross_fraction составляет FIXED при доле капитала 0.9 на каждую сторону; настройка кредитного плеча и параметр покупательной способности отсутствуют. Недавно стратегия SPY провалилась, поскольку ее коэффициент Шарпа менялся с размером позиции; в этой конструкции буфер маржи вообще не используется. Рыночная бета нетто составляет примерно 0 по определению. Правило стопа: катастрофический стоп на уровне всей книги закрывает все позиции, если убыток книги от капитала на последней ребалансировке достигает 8%; книга формируется заново при следующей плановой ребалансировке.
Это исходный материал типа (a)/(b): в аннотации сформулировано проверяемое правило (импульс фактора, направленный и поперечный срез, преимущество сосредоточено в последнем месяце). USEQ охватывает лишь 4.9% корпуса, против 63% у BINANCE. Портфель длинно-короткий (эта доля — 15.7% против целевого значения длинной позиции не более 55%) и нейтрален к рынку. В нём фиксировано 10 инструментов на L173, доступны десятилетия дневной истории, комиссии почти нулевые. Факторных ETF в каталоге нет, поэтому мы используем отраслевые факторы (сектор минус SPY) — наиболее близкий добросовестный заместитель. Настраиваются лишь две степени свободы, обе обоснованы источником: окно формирования около одного месяца и реализация через временной ряд или поперечный срез. Валовая экспозиция фиксирована, поэтому оптимизатор не может повысить коэффициент Шарпа за счёт плеча.
negative_expectancy / premise_falsified в первом отчёте с измерениями. Код: no_edge (а не fee_edge, поскольку валовое преимущество само отрицательное). Тест длился 25 лет (1999-2024) на 9 спредах «сектор минус SPY» по SPDR в режиме знака временного ряда. Результаты: 1478 лотов, avg_trade_return_pct -0.351% при минимуме USEQ в 0.05% (около 0.10% для двусторонней хеджированной книги), PF 0.959, коэффициент Шарпа -0.05 с интервалом CI [-0.41, +0.29], общая доходность -20.3%, максимальная просадка 34.5% при заранее……Показать большеСвернуть
negative_expectancy / premise_falsified в первом отчёте с измерениями. Код: no_edge (а не fee_edge, поскольку валовое преимущество само отрицательное). Тест длился 25 лет (1999-2024) на 9 спредах «сектор минус SPY» по SPDR в режиме знака временного ряда. Результаты: 1478 лотов, avg_trade_return_pct -0.351% при минимуме USEQ в 0.05% (около 0.10% для двусторонней хеджированной книги), PF 0.959, коэффициент Шарпа -0.05 с интервалом CI [-0.41, +0.29], общая доходность -20.3%, максимальная просадка 34.5% при заранее зарегистрированном пороге 20%. Даже если добавить затраты на заём (6.0%) и влияние на цену (7.3k), валовая доходность всё ещё составляет около -7%. Значение IC у исполненного сигнала равно -0.011 (t = -0.19), поэтому продолжение отраслевого фактора на горизонте 1 месяцев отсутствует для ликвидных секторов SPDR. Опасения QA относительно преимущества подтвердились; на полной истории результат хуже, чем за 1653 дней песочницы (коэффициент Шарпа 0.18). Бенчмарк: рыночно-нейтральный, поэтому стратегия «купи и держи» несопоставима. Единственный непроверенный параметр — категориальный режим cross_sectional, ранжирующий те же спреды 9. Поскольку сигнал временного ряда показывает нулевое значение IC, оптимизация в течение 2 часов не оправдана. Если в исследовании снова предложат импульс факторов, понадобятся фактические доходности аномальных факторов (например, портфели Кена Френча), а не отраслевые ETF.
Реализация
Портфель торгует девятью отраслевыми факторами — спредами сектора к SPY (XLK, XLF, XLE, XLV, XLP, XLU, XLI, XLY, XLB против SPY) — на дневных барах USEQ. Каждый фактор — это логарифмическая доходность сектора за последние lookback_days синхронизированных сессий за вычетом доходности SPY за тот же период. В режиме time_series портфель держит сектор i с весом sign(f_i)*0.9/9 капитала по рыночной оценке, а позицию SPY — с весом, равным минус сумме весов секторов, что делает его нейтральным к рынку. В режиме……Показать большеСвернуть
Портфель торгует девятью отраслевыми факторами — спредами сектора к SPY (XLK, XLF, XLE, XLV, XLP, XLU, XLI, XLY, XLB против SPY) — на дневных барах USEQ. Каждый фактор — это логарифмическая доходность сектора за последние lookback_days синхронизированных сессий за вычетом доходности SPY за тот же период. В режиме time_series портфель держит сектор i с весом sign(f_i)*0.9/9 капитала по рыночной оценке, а позицию SPY — с весом, равным минус сумме весов секторов, что делает его нейтральным к рынку. В режиме cross_sectional портфель открывает длинные позиции по 3 верхним спредам и короткие по 3 нижним, на 0.9/3 каждый; SPY хеджирует остаток. Портфель ребалансируется раз за календарный интервал в rebalance_bars рабочих дней: (days_since_epoch*5//7)//21. Это привязывает периодичность к временной метке бара, обеспечивая работу после перезапуска. Интервал лишь приближённо соответствует 21 торговым сессиям: праздники сдвигают его примерно на 1 сессию в месяц, поэтому окна формирования и удержания точно не совпадают. Стоп портфеля закрывает все позиции, если капитал по рыночной оценке (остаток плюс нереализованный PnL всех позиций по последней цене закрытия) падает на 8% ниже капитала на последней ребалансировке. При следующей ребалансировке портфель формируется заново.
Итерация 3 устраняет замечания QA. (1) Критично: стоп портфеля и размер позиций при ребалансировке рассчитывались по реализованному остатку денежных средств, из-за чего стоп не работал. Теперь для расчёта используется _mtm_equity(): остаток на счёте плюс сумма (last_close - avg_px_open) * signed_qty по всем открытым позициям. На маржинальном счёте USEQ остаток не включает нереализованный PnL, поэтому это фактическая стоимость портфеля; просадка 8% по рыночной оценке внутри периода удержания теперь приводит к……Показать большеСвернуть
Итерация 3 устраняет замечания QA. (1) Критично: стоп портфеля и размер позиций при ребалансировке рассчитывались по реализованному остатку денежных средств, из-за чего стоп не работал. Теперь для расчёта используется _mtm_equity(): остаток на счёте плюс сумма (last_close - avg_px_open) * signed_qty по всем открытым позициям. На маржинальном счёте USEQ остаток не включает нереализованный PnL, поэтому это фактическая стоимость портфеля; просадка 8% по рыночной оценке внутри периода удержания теперь приводит к закрытию всех позиций. (2) Предупреждение: если знак позиции сохраняется, а изменение её размера превышает $500, _reconcile теперь отправляет только разницу (want - have) по неттированной позиции. Полное закрытие и открытие происходят только при смене знака или обнулении позиции. Это примерно вдвое снижает оборот и спредовые издержки и издержки воздействия на рынок по хеджу SPY и секторам с неизменным знаком. (3) Приближение календарного интервала теперь описано в комментарии кода и описании. Сигнал, набор инструментов, фиксированные параметры и настраиваемые диапазоны (режим, lookback_days 15-30) не изменились. Оговорка по реестру: корректировки разницы масштабируют неттированный лот, поэтому одна закрытая позиция может охватывать несколько ребалансировок (урок L175); показатели на сделку описывают лоты, а не ребалансировки.
Результаты верификации
В текущем виде допустимо. Для точного совпадения рассчитывай интервал по индексу сессии из календаря XNYS (src/data/market_calendar.py), примененному к bar.ts_init.
В гипотезе ребалансировка каждые 21 сессий отсчитывается по барам. В коде вместо этого используется привязанный к календарю интервал (days_since_epoch*5//7)//21. Проверка 20 требует календарной привязки, и разработчик задокументировал это приближение. Из-за праздников интервал сдвигается примерно на 1 сессию в месяц, поэтому окно формирования длиной 21 строк и период удержания не совпадают точно.
В полном бэктесте проверьте наличие событий OrderDenied по хеджирующей позиции SPY. Если они есть, установите config.leverage равным 2.0; параметр не влияет на размер позиций, только если `leverage` остаётся равным 1.0.
Валовая номинальная позиция достигает 1.8x капитала: 0.9 длинная плюс 0.9 короткая в обоих режимах либо хедж SPY на уровне -0.9, когда у всех секторов один знак. config.leverage равен 1.0. Это соответствует гипотезе («0.9 капитала на каждую сторону») и не превышает Reg-T 2x. Однако если маржинальная модель движка на default_leverage 1.0 отклонит последующие позиции, портфель останется частично без хеджа. Сбалансированный реестр 181 длинных / 181 коротких позиций в песочнице указывает, что сделки исполнились.
Когда аналитик сравнивает доходность на сделку с порогом издержек, следует использовать исполнения и оборот, а не закрытые лоты.
Позиции неттируются, а при ребалансировке с тем же знаком торгуется только разница, поэтому одна закрытая позиция может охватывать несколько ребалансировок. total_trades (362 закрытых лотов) — это не число сделок на каждую ребалансировку. 916 исполнений примерно за 54 ребалансировок × 10 торговых компонентов соответствует конструкции, поэтому число записей в реестре не занижено (L133 не срабатывает), но экономика на сделку описывает лоты.
Неоптимизированная проверка в среде-песочнице длилась 1653 дней и принесла +8.3%; коэффициент Шарпа составил 0.18, PF 1.086 и avg_trade_return_pct 0.107% по 362 неттированным лотам. Издержки влияния на цену составили 11.2% от валового результата, а стоимость заимствования — 1.83% капитала, поэтому издержки поглотили большую часть валового преимущества. Спред продолжения отраслевого импульса на ликвидных SPDR за 1 месяцев невелик. Сначала проверьте, сохранится ли чистый коэффициент Шарпа после учёта стоимости заимствования и влияния на цену за всю 27-летнюю историю, а также проверьте режим обычной волатильности, в котором проверка в среде-песочнице принесла убыток 5.9%.
Обзор бэктеста
Шарп
-0,05
Общая доходность
-20,31%
Максимальная просадка
34,47%
Всего сделок
1478
Доля прибыльных
45,9%
Профит-фактор
0,96
Реализация соответствует гипотезе. Портфель держит 9 спредов секторов к SPY, использует хедж SPY, ребалансируется раз в месяц и имеет сбалансированные длинные и короткие позиции (739/739). Бары синхронизированы, капитал оценивается по рынку.
Выборка большая и надёжная: 1478 закрытых лотов и 6,275 эффективных дневных наблюдений за период с 1999 по 2024; учётные данные сверены.
Отрицательное математическое ожидание на большой выборке. Коэффициент Шарпа — -0.05 (95% CI -0.41 до +0.29), PF равен 0.96, avg_trade_return_pct равен -0.35% при минимуме USEQ в 0.05% (около 0.10% для двустороннего хеджированного портфеля), а общая доходность — -20.3%. Согласно уроку L141, отрицательный коэффициент Шарпа более чем на 100 сделках — это завершённое измерение.
Преимущество отрицательное ещё до учёта издержек. Даже если вернуть затраты на заём (5.97%) и рыночное воздействие (около 7.3%), валовая доходность останется примерно -7%, так что её погубили не комиссии.
Исполненный прогноз не несёт информации: IC равен -0.011 (t = -0.19) на 299 неперекрывающихся метках длиной 21 дней, вердикт исследования сигнала — rejected_no_information.
Максимальная просадка — 34.5% (заранее зарегистрированное ограничение: 20%); портфель оставался ниже максимума около 24 лет. Он принёс убыток в обычном режиме (-5.1%) и в стрессовом режиме (-19.3%). По календарным годам 11 положительных и 14 отрицательных.
Сопоставление с ориентиром не имеет смысла: стратегия нейтральна к рынку, бета составляет примерно 0 по определению. Оценка только по абсолютным показателям.
История итераций
Проверка не пройдена (уровень 1.5 — согласованность гипотезы и конфигурации) [класс=hypothesis_mismatch]:
- optimization_plan фиксирует плечо на уровне 1.0
Проверка не пройдена (уровень 4 — проверка QA) [класс=code_defect]: - [edge_concern] Тест среды песочницы вернул +10% примерно за 1650 сессий; коэффициент Шарпа составил 0.21, а его CI — [-0.59, 0.95]. PF составил 1.08 на 553 закрытых лотах. В спокойном и стрессовом режимах результат был положительным, но в обычном — отрицательным. impact_cost_pct составляет 11.5% от валового показателя, а стоимость заимствования — 1.8%. Преимущество невелико и чувствительно к издержкам. Часть оборота возникает из-за закрытия……Показать большеСвернуть
Проверка не пройдена (уровень 4 — проверка QA) [класс=code_defect]:
- [edge_concern] Тест среды песочницы вернул +10% примерно за 1650 сессий; коэффициент Шарпа составил 0.21, а его CI — [-0.59, 0.95]. PF составил 1.08 на 553 закрытых лотах. В спокойном и стрессовом режимах результат был положительным, но в обычном — отрицательным. impact_cost_pct составляет 11.5% от валового показателя, а стоимость заимствования — 1.8%. Преимущество невелико и чувствительно к издержкам. Часть оборота возникает из-за закрытия всего лота и повторного открытия при изменении размера позиции (см. предупреждение).
- [критично] Катастрофический стоп портфеля в гипотезе (закрытие всех позиций, когда портфель проседает на 8% от капитала на момент последней ребалансировки) фактически не работает. Он сравнивает self.get_account_equity() с self._rebal_equity. get_account_equity() вызывает resolve_account_equity(), возвращающий AccountBalance.total счёта USEQ MARGIN. В NautilusTrader это денежный баланс: он меняется только при реализации REALIZED PnL и не учитывает нереализованный PnL открытых позиций. При ребалансировке портфель открывает все 10 позиций и держит их до следующей, поэтому реализованный капитал почти не меняется в течение периода удержания. Портфель может потерять 15% по рыночной оценке, а стоп так и не сработает. Убытки реализуются только при следующей ребалансировке, которая в любом случае сбрасывает _rebal_equity и _book_stopped. Поскольку в гипотезе этот стоп указан явно, стоп, который не может сработать, считается отсутствующим. (строка 197) — исправление: вычислять капитал с учётом рыночной оценки: баланс плюс сумма нереализованного PnL открытых позиций. Использовать self.portfolio.unrealized_pnls(venue) или суммировать position.unrealized_pnl(Price) по последним синхронизированным ценам закрытия каждой позиции. Использовать это значение и для стопа 8%, и для _rebal_equity при ребалансировке. При ребалансировке размер позиций также следует рассчитывать исходя из MTM капитала; текущий расчёт по реализованному балансу верен только при отсутствии открытых позиций.
- [предупреждение] В _reconcile, если знак удерживаемой позиции не меняется, но её целевой размер изменяется более чем на min_adjust_notional ($500), код закрывает весь лот и открывает позицию нового размера. Разница не торгуется отдельно. Для 0.9/9 = 10% позиций это происходит почти при каждой ребалансировке, поэтому хедж SPY и сектора с неизменным знаком полностью закрываются и открываются заново. Это примерно удваивает оборот и затраты на спред и рыночное воздействие, а также завышает число сделок по закрытым лотам. (строка 160) — исправление: отправлять только разницу (want - have) одним ордером по неттированной позиции. Закрывать и открывать заново только при смене знака.
- [предупреждение] Интервал ребалансировки задаётся выражением (days_since_epoch*5//7)//21 — это приближение, основанное на количестве рабочих дней, а не «каждая 21-я сессия, отсчитанная по барам», как указано в гипотезе. Такая привязка к календарю допустима и предпочтительна согласно проверке 20, поскольку обеспечивает стабильность после перезапуска и паритет результатов. Из-за праздников фактическая периодичность сдвигается примерно на 1 сессию в месяц. Поэтому период формирования (lookback_days строк) и период удержания (интервал) не совпадают точно. На механизм это не влияет. (строка 194) — исправление: изменения не требуются. Описать это приближение в описании.
Сводка по итогам
Прежде чем многопозиционная стратегия USEQ перейдет к бэктестингу, проверь, что по всем позициям (здесь XLK.USEQ 1-DAY) есть полные данные в каталоге за запрошенный период, чтобы пробел в данных не расходовал итерации.
Стратегия была закрыта по причине backtest_failed: после полного бэктеста попытка обработки данных завершилась сбоем 3 раз с ошибкой data_unavailable: в XLK.USEQ-1-DAY-LAST-EXTERNAL отсутствовали 1490 ожидаемых баров, в том числе на запрошенных границах. Конвейер отметил сбой данных, а не вынес вердикт о стратегии, и указал, что стратегию можно возобновить после устранения причины.
Длинно-короткий портфель с хеджем SPY на девяти исходных Select Sector SPDR, который делает ставку на импульс отраслевых факторов с коротким лагом: для доходности спреда каждого сектора к SPY за последние 21 сессий берётся знак (режим временного ряда) или ранг (режим поперечного среза: верхние -3/нижние -3), ребалансировка проводится каждые 21 сессий на основе Falck и соавторов (2020).
Данных о доходности нет. Полный бэктест не запускался, поэтому доходность, коэффициент Шарпа и число сделок не определены, а отчёт об оптимизации пуст.
Анализ
Is Factor Momentum More than Stock Momentum?
Stratmill — это инструмент для исследований и бумажной торговли, а не финансовая консультация или брокер. Результаты бэктестов и бумажной торговли являются гипотетическими. Торговля сопряжена с риском убытков.