English
preview
Машинное обучение в условиях ограничений (Часть 2): Калибровка размера позиции по оставшемуся бюджету допустимой просадки

Машинное обучение в условиях ограничений (Часть 2): Калибровка размера позиции по оставшемуся бюджету допустимой просадки

MetaTrader 5 — Машинное обучение |
23 0
Patrick Murimi Njoroge
Patrick Murimi Njoroge

Содержание

  1. Введение
  2. Почему сигмоида, а не порог
  3. Цепочка калибровки (WParamCalibrator)
  4. Что на самом деле выдаёт цепочка
  5. Проблема рабочей системы: ограничение, которое нигде не применяется
  6. Мнение: ещё два числа, жёстко заданных в коде, которые стоит такими и оставить
  7. Заключение
  8. Прикрепленные файлы


Введение

В первой части этой серии была рассмотрена фундаментальная проблема абстракции. В ней жёстко заданные в коде константы правил FundedNext были заменены явно заданным набором правил PropFirmRuleSet, а PropFirmAccountState был переработан для динамического вычисления оставшегося бюджета риска (risk_budget_pct). После этого рефакторинга система может корректно интерпретировать дневной и общий лимиты убытка для любой загруженной программы — будь то фиксированный дневной лимит FundedNext в 5 %, переменная шкала лимитов программы с динамической просадкой или особая структура правил конкретной компании. Однако, как отмечалось в заключении первой части, вычисления бесполезны, если их результаты нигде не используются. Объект состояния счёта точно знает, какой запас допустимых потерь ещё остаётся, но механизм расчёта размера позиции по-прежнему опирался на старые, жёстко заданные в коде правила.

В этой статье данный пробел устраняется за счёт реализации компонента-потребителя этих данных — WParamCalibrator. Данный калибратор преобразует абстрактный параметр risk_budget_pct в конкретный параметр w сигмоиды. Затем этот параметр w передаётся в модуль расчёта размера позиции PropFirmAwareSizer, который плавно изменяет размер каждой новой позиции от полного до нуля по мере истощения дневного бюджета. Эта архитектура намеренно построена по модульному принципу: калибратору неважно, используется ли в торговой программе дневной лимит, общий лимит или скользящая максимальная просадка. Он получает только сводную долю оставшегося бюджета риска. Такое разделение ответственности означает, что при внедрении в будущем нового набора правил проп-трейдинговой компании логика расчёта размера позиции останется неизменной.

В этой части статьи подробно рассматривается цепочка калибровки. В ней объясняется, почему вместо жёсткого порога используется сигмоида, выводятся формулы калибровки и наглядно показываются выходные значения во всём диапазоне дневного бюджета риска. В статье также отмечается пробел, выявленный в ходе углублённого анализа: модуль расчёта размера позиции проверяет корректность max_leverage, но никогда не применяет заданное этим параметром ограничение. Вместо того чтобы исправлять это упущение как попало, я определяю, в какой части архитектуры следует внести исправление. Наконец, в статье приводится отдельное руководство по настройке safety_factor — параметра, который специалисты по количественным методам в финансах часто ошибочно считают фиксированной константой, хотя на самом деле он в значительной степени зависит от стратегии.



Почему сигмоида, а не порог

На первый взгляд задача расчёта размера позиции при ограничении убытка кажется классическим случаем для применения пороговой функции. Логика кажется интуитивно понятной: пока risk_budget_pct остаётся выше определённого порога (например, пока остаётся более 20 % дневного лимита), торговать с полным размером позиции. Как только бюджет опустится ниже этого порогового значения, полностью прекратите торговлю. Этот бинарный подход чрезвычайно прост в реализации, его логику легко проанализировать и объяснить заинтересованным сторонам в записке о рисках. Однако за этой простотой скрывается опасность в торговой среде, где результат зависит от предшествующей траектории.

Порог создаёт разрыв в функции расчёта размера позиции. Представьте ситуацию, в которой стратегия приносит пять небольших убытков подряд, каждый из которых расходует 4 % дневного бюджета риска. Изначально на счёте остаётся 100 % бюджета риска, затем эта доля снижается до 96 %, 92 %, 88 %, 84 % и, наконец, до 80 %. Если порог установлен на уровне 80 %, трейдер торгует с полным размером позиции на протяжении первых четырёх убыточных сделок, а после пятого убытка размер позиции мгновенно снижается с полного до нуля. Нет ни предупреждения, ни постепенного снижения риска, ни сигнала о приближении к краю обрыва — пока стратегия не сорвётся с него. В автоматизированной системе такой резкий переход может вызвать катастрофические эффекты «пилы», особенно если стратегия опирается на импульс или возврат к среднему, которые обычно усиливаются во время просадок.

Функции bet_size_sigmoid и get_w, определённые во фрагменте кода 10.4 из AFML, изначально предназначались для решения другой, но структурно идентичной задачи: преобразования отклонения прогнозируемой цены от текущей в ограниченный размер позиции. В части 11 серии «Архитектура машинного обучения в MetaTrader 5» этот механизм был заимствован, но смысл его входных данных был изменён. Вместо калибровки с учетом ценовых отклонений WParamCalibrator осуществляет калибровку с учетом оставшегося бюджета риска. Сигмоида преобразует каждое небольшое сокращение бюджета в плавное уменьшение максимально допустимого размера позиции. По мере того как бюджет приближается к нулю, наклон кривой размера позиции увеличивается, что фактически приводит к ускоренному ужесточению ограничений, при этом никогда не возникает резкого скачка. Резкий переход на пороге сменяется непрерывным монотонным снижением, что позволяет избежать скачков от бара к бару, характерных для систем на основе пороговых значений. Единственное исключение возникает при полном исчерпании бюджета риска — когда он математически равен нулю; в разделе 3 этот случай рассматривается как отдельная ветвь алгоритма, а не как предельное значение формулы.



Цепочка калибровки (WParamCalibrator)

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

risk_budget_pct  --[stop_loss_pct, safety_factor]  -->  cal_bet_size
cal_bet_size     --[cal_divergence, get_w]         -->  w_param
w_param          --[bet_size_sigmoid]              -->  sigmoid_scale
def calibrate(self, state: PropFirmAccountState) -> float:
    """Compute the sigmoid w parameter from the current account state."""
    risk_budget_pct = state.risk_budget_pct

    # Maximum allowable bet size at full signal strength:
    #   position x stop_loss <= risk_budget x safety_factor
    cal_bet_size = (risk_budget_pct * self.safety_factor) / self.stop_loss_pct
    cal_bet_size = float(np.clip(cal_bet_size, 0.0, 0.98))

    if cal_bet_size < 0.02:
        return np.inf  # budget exhausted - sigmoid collapses to zero

    return get_w(
        price_div=self.cal_divergence,
        m_bet_size=cal_bet_size,
        func="sigmoid",
    )

На первом этапе вычисляется величина cal_bet_size. Это значение даёт ответ на конкретный количественный вопрос:

каков максимальный долевой размер позиции, допустимый для счёта при полной уверенности сигнала, если известны оставшаяся доля бюджета допустимых потерь и фиксированное значение стоп-лосса в процентах, выраженное в долях капитала счёта в каждой сделке?

Формула представляет собой соотношение прямой пропорциональности: cal_bet_size = (risk_budget_pct * safety_factor) / stop_loss_pct. Коэффициент запаса safety_factor (обычно меньше 1.0) служит буфером. Он резервирует часть бюджета для покрытия затрат сверх убытка по стоп-лоссу, таких как комиссии, свопы и — что особенно важно — потери из-за риска ценового разрыва, когда в условиях высокой волатильности рыночная цена скачком перескакивает через уровень стоп-лосса. Если бы коэффициент запаса был равен 1.0, калибратор позволял бы подвергать риску весь бюджет, не оставляя резерва на транзакционные издержки. На практике столь высокое значение почти неизбежно приведёт к превышению дневного лимита убытка из-за издержек исполнения.

Настройка коэффициента запаса safety_factor для вашей стратегии: это не глобальная константа; его необходимо рассчитывать исходя из конкретной структуры издержек стратегии и профиля волатильности инструмента. Для внутридневного скальпера с высоким торговым оборотом, совершающего десятки сделок в день, суммарные комиссии и проскальзывание при исполнении по ценам спроса и предложения могут легко поглотить 10–15 % дневного бюджета допустимых потерь. Для такой стратегии целесообразно использовать коэффициент запаса от 0.60 до 0.65. Напротив, свинг-трейдер, который удерживает позиции несколько дней и торгует лишь один или два раза в неделю, несёт незначительные комиссионные издержки, но должен учитывать риск ценового разрыва за ночь — коэффициент запаса следует установить на более высоком уровне, ближе к 0.80 или 0.85, чтобы ценовой разрыв за уровень стоп-лосса не исчерпал весь бюджет риска. Надёжный метод настройки предполагает тестирование на исторических данных за выбранные периоды высокой волатильности с фиксацией фактического проскальзывания (разницы между ценой стопа и ценой исполнения) и общей суммы комиссии по каждой сделке. Коэффициент запаса следует откалибровать так, чтобы совокупные издержки не превышали предусмотренный резерв даже при наихудшем сценарии. Благодаря этому коэффициент превращается из произвольного числа в защитный механизм, основанный на данных.

После определения cal_bet_size на втором этапе выполняется обращение сигмоиды с помощью функции get_w. Эта функция находит параметр w, при котором функция bet_size_sigmoid выдаёт значение, в точности равное cal_bet_size, при опорном отклонении cal_divergence. В результате сигнал с максимальной уверенностью (когда stage1_signal равен cal_divergence) даст размер позиции, в точности равный верхнему пределу, допускаемому бюджетом риска. Любой сигнал с меньшей уверенностью даст пропорционально меньший размер позиции относительно этого верхнего предела. Само обращение сигмоиды — вычислительно нетривиальная задача: обычно для него требуется численный алгоритм поиска корня (например, метод бисекции или метод Ньютона — Рафсона), поскольку уравнение сигмоиды нельзя аналитически решить относительно w в замкнутой форме. Такие вычислительные затраты приемлемы, поскольку калибратор вызывается один раз при каждом расчёте размера позиции, а не на каждом ценовом тике между такими расчётами.

Два числа в этой функции намеренно жёстко заданы в коде, а не берутся из PropFirmRuleSet: верхний предел 0.98 и нижний порог истощения бюджета 0.02. В разделе 6 подробно объясняется, почему эти значения относятся к самой логике калибровки, а не к слою конфигурации; вкратце же это арифметические защитные ограничения для преобразования сигмоиды, а не бизнес-правила, установленные какой-либо проп-трейдинговой компанией.



Что на самом деле выдаёт цепочка калибровки

Запуск WParamCalibrator с параметрами по умолчанию (stop_loss_pct=0.01, safety_factor=0.70, cal_divergence=0.90) во всём диапазоне значений risk_budget_pct даёт кривую, форма которой одновременно неожиданна и показательна. На рисунке 1 эта взаимосвязь представлена на двух панелях.

Результат работы цепочки калибровки параметра w во всём диапазоне значений бюджета риска

Результат работы цепочки калибровки параметра w во всём диапазоне значений бюджета риска

Рисунок 1. Иллюстрация цепочки калибровки параметра w на двух панелях

  • Левая панель: bet_size_sigmoid в зависимости от stage1_signal при четырёх различных откалиброванных значениях w, каждое из которых соответствует своему уровню бюджета. При оставшемся бюджете риска в размере 5 % баланса счёта параметр w очень мал (0.03), поэтому сигмоида приближается к ступенчатой функции. Это означает, что модуль расчёта размера позиции доводит позицию до полного размера почти сразу при пересечении сигналом нуля. В противоположном предельном случае, когда остаётся всего 0.2 % бюджета, значение w резко возрастает до 40.5, а сигмоида становится значительно более пологой. Даже идеальный сигнал с максимальной уверенностью едва позволяет достичь размера позиции 0.15.
  • Правая панель: рассчитанный верхний предел cal_bet_size — максимально допустимый размер позиции для сигнала с максимальной уверенностью — показан как функция оставшегося бюджета. Кривая остаётся горизонтальной на уровне верхнего предела 0.98, пока оставшийся бюджет не опустится ниже примерно 1.4 % баланса счёта. После этой точки перегиба верхний предел линейно снижается к нижнему порогу истощения бюджета.

Горизонтальный участок на правой панели — наиболее важный эмпирический результат этого анализа. Это прямо противоречит интуитивному представлению о том, что снижение риска должно происходить постепенно на протяжении всего дня. При настройках по умолчанию решение уравнения risk_budget_pct * 0.70 / 0.01 = 0.98 даёт пороговое значение 1.4 %. На практике для счёта FundedNext с балансом 100 000 долларов и дневным лимитом убытка 5 % (5 000 долларов) калибратор практически не ограничивает расчёт размера позиции, пока убыток по счёту не достигнет 3 600 долларов из допустимых 5 000 долларов: уже израсходовано 72 % дневного лимита, а верхний предел всё ещё остаётся на уровне 0.98. Механизм уменьшения размера позиции включается лишь тогда, когда от бюджета остаётся 1 400 долларов (28 %). Это означает, что подавляющая часть динамического диапазона калибратора сосредоточена в последней пятой части бюджета, а не распределена равномерно по всему бюджету.

Это прямое следствие значений параметров stop_loss_pct и safety_factor по умолчанию, обусловленное механизмом расчёта, а не неотъемлемое свойство самой сигмоиды. Если трейдер задаёт более широкий стоп-лосс, например 2 % вместо 1 %, горизонтальный участок сокращается, а снижение риска начинается раньше. И наоборот, более узкий стоп-лосс сдвигает порог ещё ближе к нулю. Перед запуском пересчитайте пороговое значение, используя собственное значение stop_loss_pct. Не следует полагать, что показатель 1.4 % применим к другим конфигурациям.

Накопленный убыток

risk_budget_pct

cal_bet_size

Верхний предел размера позиции

0 долларов0.05003.50 → 0.98 (с ограничением)Полный размер позиции
1 000 долларов0.04002.80 → 0.98 (с ограничением)Полный размер позиции
2 000 долларов0.03002.10 → 0.98 (с ограничением)Полный размер позиции
3 000 долларов0.02001.40 → 0.98 (с ограничением)Полный размер позиции
3 600 долларов (пороговое значение)0.01400.98На верхнем пределе — начинает снижаться
4 000 долларов0.01000.7070 % от полного размера
4 500 долларов0.00500.3535 % от полного размера
4 900 долларов0.00100.077 % от полного размера

Таблица 1. Значения cal_bet_size при характерных уровнях накопленного убытка: счёт на 100 000 долларов, дневной лимит FundedNext — 5 % (5 000 долларов), stop_loss_pct=0.01, safety_factor=0.70. Значения получены по формуле калибровки из раздела 3, а не путём независимого вывода; на правой панели рисунка 1 эта же зависимость представлена непрерывной кривой.

В связи с этим возникает эмпирический вопрос, на который статический анализ не может дать ответа. Приносит ли пользу сосредоточение калибровки на последних 1.4 %, или это приводит к недостаточной защите счета на ранних этапах и чрезмерной реакции в конце? Ответ полностью зависит от совместного распределения переменных stage1_signal и risk_budget_pct. Если серии убытков (сокращающие бюджет риска) обычно совпадают с периодами высокой уверенности сигнала — возможно, потому что преимущество стратегии наиболее выражено на трендовых рынках, где также возникают убытки при низкой волатильности, — то агрессивный подход калибратора, использующего полный размер позиции, оправдан.

И наоборот, если убытки, как правило, возникают тогда, когда сигнал уже слабый, отсутствие снижения риска на раннем этапе является структурным недостатком. Ответ на этот вопрос должно дать тестирование на исторических данных, а не алгебра. В одной из следующих статей этой серии будут представлены подробные результаты тестирования на исторических данных для нескольких наборов правил проп-трейдинговых компаний: будет проверено, снижает ли откалиброванная сигмоида вероятность нарушения дневного лимита без преждевременного сокращения прибыльных позиций. На данный момент анализ калибровки подтверждает, что цепочка калибровки работает в соответствии с математическим замыслом; оценка её эффективности остаётся открытым эмпирическим вопросом.



Проблема рабочей системы: ограничение, которое нигде не применяется

Эту проблему выявили не при изолированном анализе кода; её обнаружили благодаря прямому практическому вопросу:

почему параметр max_leverage никогда не используется при расчёте размера позиции, хотя он строго проверяется в PropFirmRuleSet.__post_init__ и явно задан в таких наборах правил, как FUNDEDNEXT_STELLAR_2STEP (где его значение обычно составляет 100:1 для валютных инструментов, 30:1 для сырьевых товаров и 1:1 для криптовалют)?

На первый взгляд это выглядит как простая оплошность — пропущенная строка кода. Однако при более тщательном рассмотрении в этом конвейере обнаруживается фундаментальный архитектурный пробел.

Каждая величина, которую вычисляют WParamCalibrator и PropFirmAwareSizer, представляет собой долевой размер позиции в диапазоне [-1, 1]. Это лишь сигнал распределения риска, отражающий долю средств счёта, которой стратегия готова рискнуть в одной сделке. Это не объём позиции в лотах и не номинальный объём позиции в долларах. Параметр max_leverage, напротив, ограничивает совершенно иную величину: отношение маржи к средствам счёта. Соотношение определяется следующим образом: margin_required = notional / max_leverage, где notional — номинальная стоимость позиции, равная объёму в лотах, умноженному на цену инструмента и размер контракта.

margin_required = notional / max_leverage, where the notional is the lot size multiplied by the instrument's price and contract size.

В текущем подпакете отсутствует логика преобразования долевого размера позиции в объём позиции в лотах. Это преобразование происходит на последующем этапе, в слое исполнения — в системе тестирования на исторических данных или в советнике, — где final_size преобразуется в фактический объём заявки (например, 1.5 лота). Поскольку этот слой преобразования отсутствует в afml.prop_firm, в конвейере нет ни одной точки, где можно было бы проверить соблюдение ограничения max_leverage. Дело не в том, что ограничение проверяется не там, где нужно; его вообще негде проверять.

Это пробел принципиально иного рода, чем неиспользуемые константы, описанные в части 1. Такие поля, как min_trading_days и commission_per_lot, представляли собой метаданные о фактических условиях, которые оставались незадействованными в ожидании будущего компонента-потребителя. Однако max_leverage — это жёсткое ограничение, относящееся к той же логической категории, что и daily_loss_limit_pct. Расчёт размера позиции с учётом риска не обеспечивает автоматического соблюдения ограничений кредитного плеча. Эти два ограничения математически ортогональны: расчёт размера позиции с учётом риска контролирует величину убытка при срабатывании стоп-лосса, тогда как ограничения кредитного плеча задают максимальный номинальный объём позиции, которую вообще можно открыть, совершенно независимо от того, где установлен стоп-лосс. Эти ограничения согласуются лишь по случайности, и такое совпадение полностью нарушается для инструментов, у которых размер контракта велик по сравнению с типичными расстояниями до стоп-лосса. Рассмотрим золото (XAUUSD) по цене 2 500 долларов за унцию со стандартным лотом в 100 унций, в результате чего номинальная стоимость одного лота составляет 250 000 долларов. Для счёта на 100 000 долларов при значении параметра max_leverage 30:1 максимально допустимый объём позиции в лотах рассчитывается следующим образом:

max_lots = (account_equity × max_leverage) / (price × contract_size)

max_lots = (100 000 × 30) / (2 500 × 100) = 12.0 лотов

Если алгоритм расчёта размера позиции с учётом риска выдаёт 15 лотов (например, при высокой уверенности сигнала и близком стоп-лоссе), ограничение кредитного плеча уменьшит этот объём до 12 лотов. Без этой проверки советник попытался бы разместить ордер на 15 лотов, который брокер, скорее всего, отклонил бы. Хуже того, некоторые брокеры могут принять такой ордер с предупреждением о «превышении кредитного плеча», подвергая трейдера риску маржин-колла и нарушения условий проп-трейдинговой компании. Эта проблема ещё более остро стоит в случае небольших счетов. Для счёта на 25 000 долларов максимальный объём позиции составит 3 лота — значительно меньше, чем может дать расчёт размера позиции с учётом риска. Для исправления требуется специальная функция:

leverage_cap_lots(account_equity, price, contract_size, max_leverage)

которую следует применять именно на этапе преобразования final_size в объём ордера:

lots = min(risk_based_lots, leverage_cap_lots(...))

Этот слой преобразования долевого размера позиции в объём позиции в лотах в настоящее время отсутствует в afml.prop_firm. Следовательно, это исправление следует реализовать не в виде быстрого патча в sizing.py, а как базовый элемент модуля, который в конечном итоге будет отвечать за интерфейс исполнения ордеров. Реализация этого исправления в виде патча нарушила бы архитектурные принципы, связав логику управления риском с деталями исполнения ордеров. Этот вопрос выходит за рамки данной статьи и вполне заслуживает рассмотрения в одной из следующих частей серии.



Мнение: ещё два числа, жёстко заданных в коде, которые следует оставить такими

В разделе «Мнение» первой части обосновывалось, что пороги 80 % и 30 % внутри derisking_factor должны находиться за пределами PropFirmRuleSet, поскольку они отражают выбор стратегии по усмотрению трейдера, а не реально действующее правило проп-трейдинговой компании. Этот аргумент создал прецедент для разграничения «бизнес-логики» и «арифметической безопасности». Метод WParamCalibrator.calibrate вводит два числа, на примере которых проверяется этот принцип: верхний предел 0.98 и нижний порог истощения бюджета 0.02. Я считаю, что по тем же причинам эти значения следует оставить жёстко заданными в коде.

Ни 0.98, ни 0.02 не отражают каких-либо положений условий предоставления услуг FundedNext или набора правил любой другой проп-трейдинговой компании. Вы не найдёте ни в одном контракте положения, требующего ограничить сигмоиду сверху на уровне 98 % или снизу на уровне 2 %. 0.98 — это практический инженерный запас, позволяющий обойти математическую особенность: значение сигмоидной функции асимптотически приближается к 1.0, но никогда не достигает его при конечном w. Если требовать от get_w найти решение для значения сигмоиды, в точности равного 1.0, численный решатель будет вынужден искать бесконечное значение, расходуя вычислительные ресурсы без практического повышения точности расчёта размера позиции. Нижний порог истощения бюджета 0.02 выполняет аналогичную функцию. Если оставшийся бюджет настолько истощён, что рассчитанное значение cal_bet_size опускается ниже 2 % по шкале долевого размера позиции, итоговый объём позиции в лотах будет настолько мал, что окажется ниже минимального шага step_size, установленного брокером. В большинстве конфигураций при дискретизации объёма позиции в лотах (например, с шагом 0.01 лота) такое значение в любом случае будет округлено до нуля. Возврат значения np.inf на этом этапе просто досрочно завершает калибровку, сразу сводя сигмоиду к нулю, что экономит вычислительные ресурсы и позволяет избежать численной неустойчивости при вычислениях с плавающей запятой.

Это различие стоит подчеркнуть: велик соблазн поступить наоборот. Эти цифры выглядят как универсальные константы — это округленные, интуитивно понятные процентные значения. Разработчик, взглянув на этот код, может подумать: «Эти значения нужно сделать настраиваемыми, чтобы пользователи могли регулировать агрессивность калибратора». Однако их настройка определяет не то, как трейдер хочет работать с правилами компании, а то, насколько консервативно сама математика калибровки должна учитывать численные ограничения. PropFirmRuleSet предназначен для хранения информации первого типа — бизнес-правил, различающихся от программы к программе. Он не предназначен для хранения информации второго типа — арифметических запасов, обеспечивающих надёжность вычислений и неизменных во всех сценариях использования. Перенос этих констант в конфигурацию засорит набор правил деталями реализации и создаст ложное впечатление, будто их изменение содержательно меняет поведение стратегии с учётом риска, а не просто регулирует точность вычисления обратной функции сигмоиды.



Заключение

В части 1 был создан объект состояния счёта, который определяет оставшийся бюджет риска при любом наборе правил. В этой статье создан механизм, использующий эту информацию: цепочка калибровки сигмоиды, которая непрерывно преобразует сокращение бюджета в уменьшение размера позиции — без порогов, которые нужно пересекать, и без разрывов, по неблагоприятную сторону которых можно внезапно оказаться. Реализация в настоящее время математически завершена и готова к интеграции. Основные выводы из этого подробного анализа:

  • Непрерывная калибровка позволяет избежать проблемы, характерной для жёсткого порога. Жёсткое отсечение может без предупреждения уменьшить размер позиции с полного до нуля за один бар; при калиброванной сигмоиде такого не происходит, поскольку она преобразует каждое малое изменение бюджета в малое изменение размера позиции.
  • Динамический диапазон калибровки сосредоточен на узком участке, а не распределён равномерно. При параметрах по умолчанию размер позиции ничем не ограничивается, пока не будет израсходовано примерно 70 % дневного бюджета. Прежде чем считать этот порог применимым, заново выведите его для своих значений stop_loss_pct и safety_factor.
  • safety_factor — это параметр, зависящий от конкретной стратегии, а не константа. Его необходимо настраивать с учетом исторических данных о проскальзывании и комиссионных. Стратегиям с высокой оборачиваемостью нужны меньшие значения коэффициента запаса, чтобы избежать снижения доходности из-за комиссий; стратегиям с низкой оборачиваемостью, подверженным риску ценового разрыва, нужны более высокие значения.
  • Расчёт размера позиции с учётом риска и ограничение кредитного плеча — независимые ограничения. Сейчас в этом подпакете ничто не проверяет второе из них, а реализовать такую проверку следует в ещё не существующем слое преобразования, а не в виде исправления кода из этой статьи.
  • Не каждое жёстко заданное в коде число следует включать в PropFirmRuleSet. Значения 0.98 и 0.02 относятся к самой арифметике калибровки, а не к правилам компании. Тем самым принцип разграничения из части 1 распространяется на случай, который поначалу казался скорее универсальной константой, чем проектным решением.
  • Эмпирический вопрос ещё предстоит решить с помощью тестирования на исторических данных. Улучшает ли профиль с концентрированным снижением риска общие результаты или ухудшает их, зависит от совместного распределения сигнала и бюджета; в одной из последующих статей будут представлены результаты для нескольких наборов правил.

В части 3 речь пойдёт о параметре derisking_factor и кривой прогресса прохождения этапа: почему этот параметр реагирует на другую входную величину, нежели WParamCalibrator, и что происходит, когда оба модификатора действуют на одну и ту же сделку ближе к концу прибыльного дня.

Прикрепленные файлы

1.phase.pyafml.prop_firmПеречисление Phase, вынесенное в отдельный файл во избежание циклического импорта.
2.rule_set.pyafml.prop_firmКласс данных PropFirmRuleSet и предустановка FUNDEDNEXT_STELLAR_2STEP.
3.account_state.pyafml.prop_firmPropFirmAccountState, переработанный для использования PropFirmRuleSet: значение current_balance учитывается нарастающим итогом на протяжении всех дней и вызовов, а дневной и общий лимиты убытка рассчитываются с учётом drawdown_basis.
4.sizing.pyafml.prop_firmWParamCalibrator, kelly_payoff_multiplier, derisking_factor, news_window_factor, PropFirmAwareSizer, make_sizer и prop_firm_sl_ceiling, из реализации которого устранено дублирование.
5.test_prop_firm.pyafml.prop_firmНабор тестов: валидация набора правил, проверка состояния счёта за отдельный день и нарастающим итогом, проверка применимости к набору правил другой компании, отличной от FundedNext, проверка порогов модификаторов и сквозной тест базовой работоспособности модуля расчёта размера позиции.

Дополнительная литература

  • Лопес де Прадо, М. (2018). Advances in Financial Machine Learning, глава 10 (фрагмент кода 10.4). John Wiley & Sons.

Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/24249

Прикрепленные файлы |
MQL5.zip (17.95 KB)
Торговые инструменты на MQL5 (Часть 35): Расширение слоя рисования на холсте — каналы, вилы, инструменты Ганна и Фибоначчи Торговые инструменты на MQL5 (Часть 35): Расширение слоя рисования на холсте — каналы, вилы, инструменты Ганна и Фибоначчи
Мы расширяем слой рисования на холсте из предыдущей части, добавляя семь новых категорий аналитических инструментов с несколькими опорными точками, которые охватывают три варианта каналов, три варианта вил, три инструмента Ганна и шесть инструментов Фибоначчи. Рассмотрим, как каждый инструмент задает свою геометрию на холсте, как вычисляемые маркеры позволяют пользователям согласованно изменять форму составных фигур и как общие вспомогательные функции выполняют отсечение лучей, построчную заливку и отрисовку дуг со сглаживанием. В итоге у нас будет полный набор инструментов для аналитического рисования, которые будут располагаться на одном интерактивном холсте наряду с базовыми инструментами для рисования линий из предыдущей части.
Архитектура машинного обучения для MetaTrader 5 (Часть 20): Подавление шума, удаление рыночной компоненты и кластеризация корреляционной матрицы признаков Архитектура машинного обучения для MetaTrader 5 (Часть 20): Подавление шума, удаление рыночной компоненты и кластеризация корреляционной матрицы признаков
Исходные корреляции признаков содержат шум оценивания и компоненту общей рыночной моды, которые искажают результаты кластеризации. Мы оцениваем верхнюю границу шумового спектра по теореме Марченко — Пастура (с поправкой на эффективный размер выборки), подавляем шум методом выравнивания остаточных собственных значений, удаляем рыночную компоненту и запускаем алгоритм оптимального числа кластеров (ONC). В результате получаются очищенная корреляционная матрица и устойчивые метки кластеров, которые позволяют избежать эффекта замещения и служат входными данными для оценки групповой важности признаков методами среднего уменьшения неоднородности (MDI) и среднего снижения точности (MDA) в следующей статье.
Паттерн "Строитель" в MQL5: Формирование ордеров с помощью цепочек вызовов методов Паттерн "Строитель" в MQL5: Формирование ордеров с помощью цепочек вызовов методов
При ручном заполнении структуры MqlTradeRequest правила согласованности полей остаются непроверенными, что приводит к скрытым ошибкам конфигурации, проявляющимся во время выполнения. COrderBuilder с плавным интерфейсом (Fluent Interface) для MQL5 поддерживает цепочку вызовов методов с использованием указателей, проверку каждого поля и проверку расположения SL/TP с учетом направления сделки и ограничений брокера по уровню стопов. Метод Send() выполняет четыре этапа: проверку установки всех необходимых флагов, проверку согласованности полей, OrderCheck(), а затем OrderSend(), благодаря чему ошибки конфигурации выявляются на ранней стадии, а код отправки ордеров остается понятным и пригодным для повторного использования.
Ценовые каналы в MQL5 без предположений о форме распределения: Квантильная регрессия методом итеративно перевзвешенных наименьших квадратов (IRLS) Ценовые каналы в MQL5 без предположений о форме распределения: Квантильная регрессия методом итеративно перевзвешенных наименьших квадратов (IRLS)
Мы строим скользящий ценовой канал по условным квантильным прямым уровней 0.1, 0.5 и 0.9, оцениваемым методом итеративно перевзвешенных наименьших квадратов (IRLS) с квантильной функцией потерь (pinball loss); реализация включает класс для повторного использования и два индикатора MetaTrader 5. Мы проверяем охват внутри выборки, анализируем пересечение квантильных прямых и сравниваем ширину канала со средним истинным диапазоном (ATR), шириной полос Боллинджера и шириной регрессионного канала на одинаковых горизонтах. Проверки в тестере стратегий показывают, что границы канала носят описательный характер, тогда как нормированная ширина служит признаком волатильности и рыночного режима.