<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
    <title>Notes &amp; Insights - python</title>
    <subtitle>Блог об архитектуре систем, AI-агентах, распределенных системах и алгоритмическом трейдинге.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://xsa-dev.github.io/tags/python/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://xsa-dev.github.io"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-11-13T00:00:00+00:00</updated>
    <id>https://xsa-dev.github.io/tags/python/atom.xml</id>
    <entry xml:lang="ru">
        <title>ORB на QQQ в PyBroker: бэктест пробоя открывающего диапазона без заглядывания вперёд</title>
        <published>2026-11-13T00:00:00+00:00</published>
        <updated>2026-11-13T00:00:00+00:00</updated>
        
        <author>
          <name>Alexei Savin</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://xsa-dev.github.io/posts/pybroker-orb-qqq-intraday-backtest/"/>
        <id>https://xsa-dev.github.io/posts/pybroker-orb-qqq-intraday-backtest/</id>
        
        <content type="html" xml:base="https://xsa-dev.github.io/posts/pybroker-orb-qqq-intraday-backtest/">&lt;p&gt;Пробой открывающего диапазона (ORB) — одна из самых старых идей в интрадей-трейдинге: если первые минуты торговли прошли выше цены открытия дня, покупаем, ожидая продолжения импульса. Идея настолько проста, что кажется, будто её нельзя испортить реализацией. На практике всё наоборот: почти вся разница между «стратегия работает» и «стратегия съедает депозит» умещается в детали исполнения бэктеста — на каком баре исполняется сигнал, как считается размер позиции и какие издержки вообще не попали в модель.&lt;/p&gt;
&lt;p&gt;Разберём конкретную реализацию: пятиминутный ORB на QQQ в open-source библиотеке &lt;strong&gt;PyBroker 2.x&lt;/strong&gt; — с бар-за-бару исполнением, состоянием в &lt;code&gt;ctx.session&lt;/code&gt;, стопом на противоположной границе диапазона и размером позиции из фиксированного риска. Отдельно посчитаем то, что обычно остаётся за кадром: какое плечо неявно создаёт «риск 1% на сделку» и почему 2026 год ломает кривую доходности при растущем индексе.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Отправная точка:&lt;/strong&gt; видео &lt;a rel=&quot;external&quot; href=&quot;https://youtu.be/Rk-Oxn5GzOo&quot;&gt;PyBroker: Backtesting 5 Minute ORB Strategy on QQQ&lt;/a&gt; канала Part Time Larry. Числа прогонов ниже — из этого разбора; код и расчёты издержек — авторские, приведены как проверяемая схема, а не как воспроизведение исходного репозитория.&lt;/p&gt;
&lt;h2 id=&quot;chto-imenno-proveriaetsia&quot;&gt;Что именно проверяется&lt;/h2&gt;
&lt;p&gt;Формализуем гипотезу, иначе бэктест превращается в подгонку:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;H1:&lt;/strong&gt; знак первых пяти минут торговли на QQQ предсказывает знак оставшейся части сессии с вероятностью, достаточной для положительного математического ожидания после издержек.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Гипотеза не про «магию первого бара», а про продолжение импульса: у крупных участников после открытия остаётся неисполненный объём, и они доносят его в первые часы. Если это верно, распределение доходностей остатка дня должно зависеть от направления первого импульса. Если не верно — мы получаем симметричную лотерею с отрицательным ожиданием после комиссий.&lt;/p&gt;
&lt;p&gt;Проверять это на пятиминутных барах означает три требования к движку: доступ только к текущему и прошлым барам, исполнение не на баре сигнала, и учёт ограничения по кэшу. Всё остальное — удобство.&lt;/p&gt;
&lt;h2 id=&quot;matematika-do-koda-chego-stoit-23-winrate&quot;&gt;Математика до кода: чего стоит 23% winrate&lt;/h2&gt;
&lt;p&gt;Пусть убыток ограничен дистанцией стопа и равен 1R, средний выигрыш равен &lt;code&gt;k&lt;/code&gt; в тех же единицах R, а доля прибыльных сделок — &lt;code&gt;p&lt;/code&gt;. Ожидание на сделку в единицах риска:&lt;/p&gt;
&lt;p&gt;$$
E = p \cdot k - (1 - p)
$$&lt;/p&gt;
&lt;p&gt;Безубыточный порог при заданном &lt;code&gt;k&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;$$
p^{*} = \frac{1}{1 + k}
$$&lt;/p&gt;
&lt;p&gt;При &lt;code&gt;k = 10&lt;/code&gt; (тейк в десять размеров диапазона) порог — &lt;strong&gt;9.1%&lt;/strong&gt;: достаточно угадывать меньше одной сделки из десяти, чтобы не терять деньги. Это и есть экономический смысл стратегии с тейком «в десять раз больше риска»: она продаёт частоту за амплитуду.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Средний выигрыш k&lt;/th&gt;&lt;th&gt;Порог p*&lt;/th&gt;&lt;th&gt;Ожидание при p = 0.23&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;3R&lt;/td&gt;&lt;td&gt;25.0%&lt;/td&gt;&lt;td&gt;−0.08R&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;5R&lt;/td&gt;&lt;td&gt;16.7%&lt;/td&gt;&lt;td&gt;+0.38R&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;8R&lt;/td&gt;&lt;td&gt;11.1%&lt;/td&gt;&lt;td&gt;+1.07R&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;10R&lt;/td&gt;&lt;td&gt;9.1%&lt;/td&gt;&lt;td&gt;+1.53R&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Таблица показывает главную уязвимость конструкции: при &lt;code&gt;k = 3&lt;/code&gt; стратегия с тем же winrate уже убыточна. Значит, вся прибыль держится не на проценте прибыльных сделок, а на том, что редкие выигрыши действительно дотягивают до десяти R. Любое событие, срезающее хвост выигрышей — выход в конце дня, сдвиг тейка, ранний стоп, — уничтожает ожидание быстрее, чем рост winrate способен его восстановить.&lt;/p&gt;
&lt;h2 id=&quot;kontrakt-ispolneniia-vazhnee-signala&quot;&gt;Контракт исполнения важнее сигнала&lt;/h2&gt;
&lt;p&gt;В векторном бэктесте («посчитать доходность по колонкам pandas») позиция на бар &lt;code&gt;t&lt;/code&gt; часто формируется по данным бара &lt;code&gt;t&lt;/code&gt; и заполняется по цене &lt;code&gt;t&lt;/code&gt;. Это заглядывание вперёд: в реальной торговле на закрытии бара вы уже не купите по его же цене. Разница в несколько базисных пунктов на сделку при 250 сделках в год превращается в разницу между «работает» и «не работает».&lt;/p&gt;
&lt;p&gt;PyBroker решает это архитектурно: функция исполнения вызывается на &lt;strong&gt;каждом баре&lt;/strong&gt; и получает контекст, в котором доступны только текущий и прошлые бары (&lt;code&gt;ctx.close[-1]&lt;/code&gt;, &lt;code&gt;ctx.high[-2]&lt;/code&gt;), а заявка, выставленная на баре &lt;code&gt;t&lt;/code&gt;, исполняется на баре &lt;code&gt;t+1&lt;/code&gt;. Заглядывание вперёд становится технически невозможным, а не «делом дисциплины».&lt;/p&gt;
&lt;p&gt;Из этого следуют два неочевидных следствия, которые ломают наивную реализацию:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Сигнал считается на баре &lt;strong&gt;09:34&lt;/strong&gt; (пятый минутный бар сессии), а вход происходит на &lt;strong&gt;09:35&lt;/strong&gt;. Цена входа — открытие следующего бара, а не закрытие сигнального.&lt;/li&gt;
&lt;li&gt;Выход «в конце дня» надо ставить на бар &lt;strong&gt;15:58&lt;/strong&gt;, а не 15:59: заявка исполнится на следующем баре, и при постановке на 15:59 позиция закроется уже на следующей сессии — с гэпом и переносом риска через ночь.&lt;/li&gt;
&lt;li&gt;Константа «конец дня» не является константой. В укороченные сессии (дни перед праздниками на американском рынке закрытие в 13:00) и при переходе на летнее время бар 15:58 либо не существует, либо приходится на другой момент UTC. Время закрытия надо вычислять из календаря торговых сессий, а не задавать минутами от полуночи; иначе часть дней просто не закроется, и в отчёт попадёт ночной риск, которого в стратегии нет.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #BFBDB6; background-color: #0D1017;&quot; &gt;&lt;code data-lang=&quot;mermaid&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;flowchart&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt; TD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    A&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;Минутные OHLCV: 09:30 &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; 15:59 NY&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;] --&amp;gt;&lt;/span&gt;&lt;span&gt; B&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;Бар 1&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;5: накопление H и L диапазона&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    B &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;span&gt; C&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;Бар 09:34: C сравнить с открытием дня O&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    C &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; C больше O &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;span&gt; D&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;Лонг на открытии бара 09:35&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    C &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; C меньше O &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;span&gt; E&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;Шорт на открытии бара 09:35&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    C &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; C равно O &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;span&gt; F&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;Сигнала нет, день пропущен&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    D &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;span&gt; G&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;Дистанция стопа D &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; C минус L&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    E &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;span&gt; G&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    G &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;span&gt; H&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;Размер позиции q &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; floor R делить на D&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    H &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;span&gt; I&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;Следующие бары: касание стопа или тейка&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    I &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; Стоп &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;span&gt; J&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;Выход, убыток около 1R&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    I &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; Тейк &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;span&gt; K&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;Выход, прибыль около k R&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    I &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; Ни то, ни другое &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;span&gt; L&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;Бар 15:58: принудительное закрытие&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;mekhanika-diapazona-i-granits&quot;&gt;Механика диапазона и границ&lt;/h2&gt;
&lt;p&gt;Открывающий диапазон — это максимум и минимум первых пяти минут:&lt;/p&gt;
&lt;p&gt;$$
H = \max_{t \in [1,5]} \text{high}_t, \qquad L = \min_{t \in [1,5]} \text{low}_t
$$&lt;/p&gt;
&lt;p&gt;Ширина диапазона &lt;code&gt;w = H − L&lt;/code&gt; — одновременно мера волатильности утра и масштаб всей сделки: от неё считаются и стоп, и тейк, и размер позиции. Сигнал:&lt;/p&gt;
&lt;p&gt;$$
\text{signal} =
\begin{cases}
+1, &amp;amp; C &amp;gt; O \
-1, &amp;amp; C &amp;lt; O \
0, &amp;amp; C = O
\end{cases}
$$&lt;/p&gt;
&lt;p&gt;где &lt;code&gt;C&lt;/code&gt; — закрытие пятого бара, &lt;code&gt;O&lt;/code&gt; — цена открытия дня. Случай равенства — не мелочь: в узких диапазонах он встречается регулярно, и молчаливая трактовка «равно нулю = лонг» добавляет к выборке сделки, которых стратегия не предполагала.&lt;/p&gt;
&lt;p&gt;Дистанция стопа до противоположной границы диапазона:&lt;/p&gt;
&lt;p&gt;$$
D =
\begin{cases}
C - L, &amp;amp; \text{лонг} \
H - C, &amp;amp; \text{шорт}
\end{cases}
$$&lt;/p&gt;
&lt;p&gt;и тейк на расстоянии &lt;code&gt;k&lt;/code&gt; ширин диапазона от входа:&lt;/p&gt;
&lt;p&gt;$$
T = C + k \cdot w \cdot \text{signal}
$$&lt;/p&gt;
&lt;p&gt;Обратите внимание: стоп задаётся как &lt;strong&gt;дистанция&lt;/strong&gt; от цены входа, а не как абсолютная цена. Это принципиально для корректного расчёта размера позиции и для переноса логики на другие таймфреймы: при переходе с пятиминутного диапазона на пятнадцатиминутный меняется только константа, а не структура кода.&lt;/p&gt;
&lt;h2 id=&quot;skrytoe-plecho-kotoroe-sozdaiot-risk-1-na-sdelku&quot;&gt;Скрытое плечо, которое создаёт «риск 1% на сделку»&lt;/h2&gt;
&lt;p&gt;Стандартная формула размера позиции из риска:&lt;/p&gt;
&lt;p&gt;$$
q = \left\lfloor \frac{R}{D} \right\rfloor, \qquad R = 0.01 \cdot \text{equity}
$$&lt;/p&gt;
&lt;p&gt;Выглядит консервативно: теряем не больше 1% счёта на сделку. Но посчитаем номинал. Подставив &lt;code&gt;q&lt;/code&gt;, получим:&lt;/p&gt;
&lt;p&gt;$$
\text{notional} = q \cdot C \approx R \cdot \frac{C}{D}
$$&lt;/p&gt;
&lt;p&gt;Отношение &lt;code&gt;C / D&lt;/code&gt; — это &lt;strong&gt;рычаг, который вы не выбирали&lt;/strong&gt;: он целиком определяется шириной утреннего диапазона. На QQQ по цене около 109 долларов при ширине диапазона 0.40 доллара отношение равно примерно 272. Умноженное на риск 1%, оно даёт &lt;strong&gt;около 2.7× счёта&lt;/strong&gt; в номинале.&lt;/p&gt;
&lt;p&gt;Именно поэтому в разборе прогон с фиксированными 250 акциями дал +9% за январь 2016, а прогон с риском 1% — +25%: разница не в «более умной» стратегии, а в том, что risk-based сайзинг на узком стопе вложил втрое больше капитала. Это не обязательно плохо, но это надо знать: стратегия масштабируется не риском на сделку, а плечом, и на кэш-счёте она просто не помещается в капитал — отсюда урезание 250 акций до 229 из-за нехватки средств.&lt;/p&gt;
&lt;p&gt;Второе следствие опаснее. Стоп — это заявка, а не гарантия. Если цена проскакивает уровень на величину &lt;code&gt;g&lt;/code&gt;, реальный убыток:&lt;/p&gt;
&lt;p&gt;$$
\text{loss} = q \cdot (D + g) = R\left(1 + \frac{g}{D}\right)
$$&lt;/p&gt;
&lt;p&gt;При &lt;code&gt;D = 0.35&lt;/code&gt; и проскальзывании 0.10 доллара потеря составит 1.29R. При узком диапазоне &lt;code&gt;D = 0.10&lt;/code&gt; и том же проскальзывании — &lt;strong&gt;2R&lt;/strong&gt;, то есть вдвое больше заявленного риска. Узкие диапазоны одновременно дают максимальное плечо и худшее исполнение стопа: двойная асимметрия против стратегии, и её не видно ни в одной метрике, кроме распределения фактических убытков.&lt;/p&gt;
&lt;h2 id=&quot;kod-sostoianie-mezhdu-barami&quot;&gt;Код: состояние между барами&lt;/h2&gt;
&lt;p&gt;Ключевая деталь PyBroker — словарь &lt;code&gt;ctx.session&lt;/code&gt;, переживающий бары внутри дня. В нём живёт накопитель диапазона; при смене даты он сбрасывается. Ниже скелет, адаптированный под API PyBroker 2.x (синтаксис проверен, прогон на данных не выполнялся — числа в статье взяты из первоисточника):&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #BFBDB6; background-color: #0D1017;&quot; &gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;from&lt;/span&gt;&lt;span&gt; datetime&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt; import&lt;/span&gt;&lt;span&gt; datetime&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;import&lt;/span&gt;&lt;span&gt; pandas&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt; as&lt;/span&gt;&lt;span&gt; pd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;from&lt;/span&gt;&lt;span&gt; pybroker&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt; import&lt;/span&gt;&lt;span&gt; Strategy&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; StrategyConfig&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; ExecContext&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;OPEN_BARS&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color: #5A6673;font-style: italic;&quot;&gt;            # первые 5 минут: 09:30 - 09:34&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;LAST_OR_MINUTE&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 34&lt;/span&gt;&lt;span style=&quot;color: #5A6673;font-style: italic;&quot;&gt;      # бар, на котором фиксируется диапазон&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;FLAT_MINUTE&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 58&lt;/span&gt;&lt;span style=&quot;color: #5A6673;font-style: italic;&quot;&gt;         # 15:58: заявка исполнится на 15:59&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;RISK_PCT&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 0.01&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;TAKE_MULT&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 10.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;MAX_LEVERAGE&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 1.0&lt;/span&gt;&lt;span style=&quot;color: #5A6673;font-style: italic;&quot;&gt;       # жёсткий потолок номинала к капиталу&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt; orb_exec&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;span&gt; ExecContext):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ts&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;span&gt; datetime&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;date&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    minute&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; ts&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;hour&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 60&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; +&lt;/span&gt;&lt;span&gt; ts&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;minute&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5A6673;font-style: italic;&quot;&gt;    # сброс состояния при смене торгового дня&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    if&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;session&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;day&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; !=&lt;/span&gt;&lt;span&gt; ts&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;date&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;session&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;update&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            day&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;=&lt;/span&gt;&lt;span&gt;ts&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;date&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; or_high&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;None&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; or_low&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;None&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            day_open&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;=&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;open[&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;1&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; entered&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;False&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    if&lt;/span&gt;&lt;span&gt; minute&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 570&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; or&lt;/span&gt;&lt;span&gt; minute&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; &amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 960&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #5A6673;font-style: italic;&quot;&gt;          # вне 09:30 - 16:00&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;        return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    if&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;session[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;or_high&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; is&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; None&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;session[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;or_high&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;high[&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;1&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;session[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;or_low&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;low[&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;1&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    else&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;session[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;or_high&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #F07178;&quot;&gt; max&lt;/span&gt;&lt;span&gt;(ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;session[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;or_high&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;high[&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;1&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;session[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;or_low&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #F07178;&quot;&gt; min&lt;/span&gt;&lt;span&gt;(ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;session[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;or_low&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;low[&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;1&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5A6673;font-style: italic;&quot;&gt;    # закрытие всех позиций: заявка уйдёт на следующий бар&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    if&lt;/span&gt;&lt;span&gt; minute&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; FLAT_MINUTE&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;sell_all_shares&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;        return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    if&lt;/span&gt;&lt;span&gt; minute&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 570&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; LAST_OR_MINUTE&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; or&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;session[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;entered&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;        return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    high&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; low&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;session[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;or_high&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;session[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;or_low&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    width&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; high&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; -&lt;/span&gt;&lt;span&gt; low&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    close&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; day_open&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;close[&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;1&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;session[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;day_open&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    if&lt;/span&gt;&lt;span&gt; width&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; &amp;lt;=&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; or&lt;/span&gt;&lt;span&gt; close&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; ==&lt;/span&gt;&lt;span&gt; day_open&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;        return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    side&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt; if&lt;/span&gt;&lt;span&gt; close&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span&gt; day_open&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt; else&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    stop_distance&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; close&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; -&lt;/span&gt;&lt;span&gt; low&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt; if&lt;/span&gt;&lt;span&gt; side&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt; else&lt;/span&gt;&lt;span&gt; high&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; -&lt;/span&gt;&lt;span&gt; close&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    equity&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;calc_total_equity&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    risk_cash&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; equity&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; RISK_PCT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    qty&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #39BAE6;&quot;&gt; int&lt;/span&gt;&lt;span&gt;(risk_cash&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; /&lt;/span&gt;&lt;span&gt; stop_distance)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    qty&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #F07178;&quot;&gt; min&lt;/span&gt;&lt;span&gt;(qty&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #39BAE6;&quot;&gt; int&lt;/span&gt;&lt;span&gt;(equity&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; MAX_LEVERAGE&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; /&lt;/span&gt;&lt;span&gt; close))&lt;/span&gt;&lt;span style=&quot;color: #5A6673;font-style: italic;&quot;&gt;   # потолок плеча&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    if&lt;/span&gt;&lt;span&gt; qty&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; &amp;lt;=&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;        return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    if&lt;/span&gt;&lt;span&gt; side&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;buy_shares&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; qty&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;stop_loss&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; close&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; -&lt;/span&gt;&lt;span&gt; stop_distance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;take_profit&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; close&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; TAKE_MULT&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; *&lt;/span&gt;&lt;span&gt; width&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    else&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;sell_shares&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; qty&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;stop_loss&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; close&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; +&lt;/span&gt;&lt;span&gt; stop_distance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;take_profit&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; close&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; TAKE_MULT&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; *&lt;/span&gt;&lt;span&gt; width&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ctx&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;session[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;entered&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; True&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;config&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt; StrategyConfig&lt;/span&gt;&lt;span&gt;(initial_cash&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;25_000&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;df&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; pd&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;read_csv&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;qqq_1min.csv&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; parse_dates&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;=&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;date&amp;quot;&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;df[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;symbol&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;QQQ&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;strategy&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt; Strategy&lt;/span&gt;&lt;span&gt;(df&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;2016-01-01&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;2023-12-31&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;=&lt;/span&gt;&lt;span&gt;config)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;strategy&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;add_execution&lt;/span&gt;&lt;span&gt;(orb_exec&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;QQQ&amp;quot;&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;result&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; strategy&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;backtest&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F07178;&quot;&gt;print&lt;/span&gt;&lt;span&gt;(result&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;orders&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;tail&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Три строки в этом коде важнее остальных. Строка с &lt;code&gt;MAX_LEVERAGE&lt;/code&gt; превращает неявное плечо из предыдущего раздела в явный, проверяемый параметр. Строка &lt;code&gt;ctx.stop_loss = ...&lt;/code&gt; ставит стоп как цену, вычисленную от фактической дистанции, — иначе риск на сделку перестаёт совпадать с &lt;code&gt;RISK_PCT&lt;/code&gt;. Строка с &lt;code&gt;sell_all_shares()&lt;/code&gt; на 58-й минуте закрывает позицию до конца сессии, а не на утро следующего дня.&lt;/p&gt;
&lt;h2 id=&quot;izderzhki-schitaem-a-ne-predpolagaem&quot;&gt;Издержки: считаем, а не предполагаем&lt;/h2&gt;
&lt;p&gt;В разборе прогоны сделаны без комиссий и проскальзывания — автор обещает отдельный выпуск. Пока этого не произошло, оценим порядок сами, на тех же числах: счёт 25 000, риск 1% ($250), дистанция стопа 0.35, около 714 акций.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Комиссия:&lt;/strong&gt; при фиксированной ставке около $0.005 за акцию — примерно $3.6 на сторону, $7.2 на круг.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Проскальзывание:&lt;/strong&gt; один цент на акцию на входе и выходе — около $14.3 на круг; на пробоях realistic-оценка выше, до трёх-пяти центов.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Стоп-ордера:&lt;/strong&gt; исполнение по стоп-маркету в момент импульса систематически хуже уровня, особенно в первые минуты.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Итого $20–35 на сделку, то есть &lt;strong&gt;0.08–0.14R&lt;/strong&gt;. При 23 сделках в месяц это 2–3R вычитаемых из валового ожидания. Само по себе терпимо — но это ровно тот порядок, который отделяет «+9% за месяц на фиксированном размере» от результата, который покажет честная модель.&lt;/p&gt;
&lt;h2 id=&quot;instrumentirovanie-izmerit-ozhidanie-a-ne-liubovat-sia-krivoi&quot;&gt;Инструментирование: измерить ожидание, а не любоваться кривой&lt;/h2&gt;
&lt;p&gt;Кривая доходности — самая плохая диагностика бэктеста: она суммирует всё и не отвечает ни на один вопрос. Минимальный набор измерений, который нужно снимать с того же прогона, — три величины на сделку: причина выхода, фактический результат в R и экстремумы хода цены до выхода (MAE и MFE). Причина выхода отделяет стратегию от её хвоста: если 70% прибыли приходит из сделок, закрытых по тайм-ауту в 15:58, — вы торгуете не ORB, а интрадей-лонг с фильтром.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #BFBDB6; background-color: #0D1017;&quot; &gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;import&lt;/span&gt;&lt;span&gt; numpy&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt; as&lt;/span&gt;&lt;span&gt; np&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;import&lt;/span&gt;&lt;span&gt; pandas&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt; as&lt;/span&gt;&lt;span&gt; pd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt; trade_r&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;orders&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;span&gt; pd&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;DataFrame)&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span&gt; pd&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;DataFrame:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;Приводит сделки PyBroker к единицам риска R.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    df&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; orders&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;copy&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    entry&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; df[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;entry_price&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;astype&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #39BAE6;&quot;&gt;float&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    stop_dist&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; (entry&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; -&lt;/span&gt;&lt;span&gt; df[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;stop_price&amp;quot;&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;abs&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    direction&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; np&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;where&lt;/span&gt;&lt;span&gt;(df[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;str&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;startswith&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;long&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 1.0&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;1.0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    df[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;r&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; (df[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;exit_price&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; -&lt;/span&gt;&lt;span&gt; entry)&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; *&lt;/span&gt;&lt;span&gt; direction&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; /&lt;/span&gt;&lt;span&gt; stop_dist&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    df[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;exit_reason&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; np&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;select&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        [df[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;bars&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; &amp;lt;=&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; df[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;r&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 1.0&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; df[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;r&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; &amp;lt; -&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;0.9&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        [&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;immediate&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;take_or_trail&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;stop&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        default&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;time_exit&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    return&lt;/span&gt;&lt;span&gt; df[[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;symbol&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;entry_date&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;r&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;exit_reason&amp;quot;&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt; expectancy_ci&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;span&gt; pd&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;Series&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; z&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #39BAE6;&quot;&gt; float&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 1.96&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    n&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #F07178;&quot;&gt; len&lt;/span&gt;&lt;span&gt;(r)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mean&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; sd&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; r&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;mean&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; r&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;std&lt;/span&gt;&lt;span&gt;(ddof&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    half&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span&gt; z&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; *&lt;/span&gt;&lt;span&gt; sd&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; /&lt;/span&gt;&lt;span&gt; np&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;sqrt&lt;/span&gt;&lt;span&gt;(n)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    return&lt;/span&gt;&lt;span&gt; mean&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; mean&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; -&lt;/span&gt;&lt;span&gt; half&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; mean&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; +&lt;/span&gt;&lt;span&gt; half&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; sd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;trades&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt; trade_r&lt;/span&gt;&lt;span&gt;(result&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;orders)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mean_r&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; lo&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; hi&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span&gt; sd&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt; expectancy_ci&lt;/span&gt;&lt;span&gt;(trades[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;r&amp;quot;&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F07178;&quot;&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;E = &lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;{&lt;/span&gt;&lt;span&gt;mean_r&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;:+.3f&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;R  95% CI [&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;{&lt;/span&gt;&lt;span&gt;lo&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;:+.3f&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;{&lt;/span&gt;&lt;span&gt;hi&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;:+.3f&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;]  sd = &lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;{&lt;/span&gt;&lt;span&gt;sd&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;:.3f&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;  n = &lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #F07178;&quot;&gt;len&lt;/span&gt;&lt;span&gt;(trades)&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F07178;&quot;&gt;print&lt;/span&gt;&lt;span&gt;(trades&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;groupby&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;exit_reason&amp;quot;&lt;/span&gt;&lt;span&gt;)[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;r&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;agg&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;count&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;mean&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;sum&amp;quot;&lt;/span&gt;&lt;span&gt;]))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Доверительный интервал здесь важнее самого числа:&lt;/p&gt;
&lt;p&gt;$$
E \pm z \cdot \frac{\sigma}{\sqrt{n}}
$$&lt;/p&gt;
&lt;p&gt;При 23 сделках в месяц и &lt;code&gt;σ ≈ 3R&lt;/code&gt; полуширина интервала равна &lt;code&gt;1.96 · 3 / √23 ≈ 1.23R&lt;/code&gt;. Иначе говоря, за месяц вы не отличите ожидание 1R от нуля — и любой вывод по одному месяцу, включая январь 2016 с его +9% и +25%, статистически пуст. Для разрешения 0.3R при том же разбросе нужно:&lt;/p&gt;
&lt;p&gt;$$
n = \left(\frac{z \cdot \sigma}{\Delta}\right)^{2} \approx \left(\frac{1.96 \cdot 3}{0.3}\right)^{2} \approx 384
$$&lt;/p&gt;
&lt;p&gt;около 384 сделок, то есть больше полутора лет при 23 сделках в месяц. Это и есть честный горизонт проверки гипотезы H1 — и причина, по которой разбивка по годам из восьми лет in-sample выглядит убедительнее, чем она есть.&lt;/p&gt;
&lt;h2 id=&quot;chto-pokazyvaiut-chisla-i-chego-oni-ne-pokazyvaiut&quot;&gt;Что показывают числа и чего они не показывают&lt;/h2&gt;
&lt;p&gt;Все цифры ниже приведены ровно так, как они получены в первоисточнике: один инструмент, параметры подобраны на том же периоде, комиссии и проскальзывание не учитываются. Это &lt;strong&gt;верхняя граница&lt;/strong&gt; оценки, а не ожидаемая доходность и не обещание результата.&lt;/p&gt;
&lt;p&gt;Сводка прогонов из первоисточника:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Прогон&lt;/th&gt;&lt;th&gt;Результат&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Январь 2016, фиксированные 250 акций&lt;/td&gt;&lt;td&gt;$25 000 → $27 360 (+9%), 23 сделки&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Январь 2016, риск 1% на сделку&lt;/td&gt;&lt;td&gt;$25 000 → $31 257 (+25%)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;In-sample 2016–2023&lt;/td&gt;&lt;td&gt;$25 000 → около $200 000, winrate 23%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Out-of-sample 2024–2025&lt;/td&gt;&lt;td&gt;Кривая растёт, обгоняет индекс&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2026 (до 27 октября)&lt;/td&gt;&lt;td&gt;−8% при +16% у QQQ&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Восемь лет и восьмикратный рост при winrate 23% выглядят как подтверждение гипотезы продолжения импульса. Но проверка на согласованность даёт важную поправку. Фактический результат января: около $6 257 прибыли на 23 сделки, то есть примерно &lt;strong&gt;$272 на сделку ≈ 1.1R&lt;/strong&gt;. Формула с &lt;code&gt;p = 0.23&lt;/code&gt; и &lt;code&gt;k = 10&lt;/code&gt; обещает 1.53R. Расхождение означает, что средний выигрыш ближе к 8R, а не к 10R: часть прибыльных сделок закрывается по времени в 15:58, не дотягивая до тейка. Распределение выигрышей — не «бимодальное ±k R», а непрерывное, и это надо учитывать при оценке просадок.&lt;/p&gt;
&lt;p&gt;Ещё важнее то, чего в таблице нет: результата &lt;strong&gt;после&lt;/strong&gt; издержек, и разбивки по годам. Именно разбивка по годам отвечает на вопрос, заданный 2026-м.&lt;/p&gt;
&lt;h2 id=&quot;pochemu-2026-god-lomaet-krivuiu&quot;&gt;Почему 2026 год ломает кривую&lt;/h2&gt;
&lt;p&gt;Минус 8% при плюс 16% у индекса — не «неудача», а сигнал о смене режима. Три конкурирующих объяснения, которые можно разделить экспериментом, а не спором:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Режим.&lt;/strong&gt; Стратегия зарабатывает на продолжении утреннего импульса. Если рынок переходит в режим возврата к среднему внутри дня, пробой открытия становится точкой разворота — и стратегия систематически покупает локальный максимум. Проверка: доля дней, где направление первого импульса совпало с направлением дня, по годам.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Издержки.&lt;/strong&gt; С ростом волатильности растёт и проскальзывание, а дистанция стопа не меняется пропорционально. Проверка: добавить модель издержек и посмотреть, не исчезает ли преимущество уже в 2024–2025.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Слабость условия.&lt;/strong&gt; «Закрытие выше открытия дня» — грубый фильтр, не учитывающий ни относительный объём в диапазоне, ни волатильность относительно ATR. Проверка: ожидание по квинтилям ширины диапазона и объёма.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Показательный контр-эксперимент: заменить сигнал на случайный вход в 09:35 с теми же стопом и тейком. Если случайный вход даёт похожую кривую за 2016–2023, стратегия измеряет не импульс, а асимметрию стопа и тейка в трендовом бычьем рынке. Это самый дешёвый способ отличить edge от бета-версии лонга.&lt;/p&gt;
&lt;h2 id=&quot;piat-invariantov-kotorye-proveriaiutsia-do-liubykh-vyvodov&quot;&gt;Пять инвариантов, которые проверяются до любых выводов&lt;/h2&gt;
&lt;p&gt;Отчёт о доходности имеет смысл только после того, как бэктест прошёл формальные проверки на согласованность. Пять утверждений, каждое из которых ломается тихо и превращает результат в фантазию:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Ни одна заявка не исполнена на баре сигнала.&lt;/strong&gt; Идентификатор бара входа строго больше идентификатора бара, на котором зафиксирован сигнал.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Сумма R сходится с деньгами.&lt;/strong&gt; Приведённая к R прибыль должна совпадать с фактическим P&amp;amp;L, делённым на риск на сделку; расхождение означает, что часть сделок потеряла привязку к своему стопу.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Касса не уходит в минус ни на одном баре.&lt;/strong&gt; Отрицательный баланс в кривой — не «плечо», а баг движка или сайзинга.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Число сессий в прогоне равно календарю.&lt;/strong&gt; Если уникальных дат меньше, чем торговых дней, пропуски в данных выглядят как отсутствие сигналов и завышают winrate.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;На каждом дне не больше одной сделки.&lt;/strong&gt; Двойной вход означает, что состояние в &lt;code&gt;ctx.session&lt;/code&gt; сбрасывается не на той границе дня.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #BFBDB6; background-color: #0D1017;&quot; &gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt; check_invariants&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;orders&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;span&gt; pd&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;DataFrame&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; equity&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;span&gt; pd&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;Series&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; sessions&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #39BAE6;&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; risk_cash&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #39BAE6;&quot;&gt; float&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    assert&lt;/span&gt;&lt;span&gt; (orders[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;entry_bar&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span&gt; orders[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;signal_bar&amp;quot;&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;all&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;fill on signal bar&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    assert&lt;/span&gt;&lt;span style=&quot;color: #F07178;&quot;&gt; abs&lt;/span&gt;&lt;span&gt;(orders[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;r&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;sum&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; -&lt;/span&gt;&lt;span&gt; orders[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;pnl&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;sum&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; /&lt;/span&gt;&lt;span&gt; risk_cash)&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 1e-6&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;R mismatch&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    assert&lt;/span&gt;&lt;span&gt; (equity&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; &amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt; 0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;all&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;negative cash&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    assert&lt;/span&gt;&lt;span&gt; orders[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;entry_date&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;dt&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;date&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;nunique&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; ==&lt;/span&gt;&lt;span&gt; sessions&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;session count mismatch&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;    assert&lt;/span&gt;&lt;span&gt; orders&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;groupby&lt;/span&gt;&lt;span&gt;(orders[&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt;&amp;quot;entry_date&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;dt&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span&gt;date)&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;size&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;le&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #FFB454;&quot;&gt;all&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #BFBDB6B3;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;double entry&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Если в результате &lt;code&gt;strategy.backtest()&lt;/code&gt; нет колонок &lt;code&gt;signal_bar&lt;/code&gt; и &lt;code&gt;entry_bar&lt;/code&gt;, их надо положить в &lt;code&gt;ctx.session&lt;/code&gt; в момент выставления заявки: движок отдаёт сделки, но не историю решений, и без этого инвариант №1 проверить нечем.&lt;/p&gt;
&lt;h2 id=&quot;chek-list-pered-real-nymi-den-gami&quot;&gt;Чек-лист перед реальными деньгами&lt;/h2&gt;
&lt;p&gt;Прежде чем переносить такую конструкцию на живой счёт через Interactive Brokers, нужно закрыть четыре разрыва:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Издержки в модели.&lt;/strong&gt; Комиссия и проскальзывание как параметры бэктеста, а не как «поправка в голове»; отдельно — ухудшение исполнения стоп-маркета.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Плечо как ограничение.&lt;/strong&gt; Явный потолок &lt;code&gt;q · C ≤ equity · L&lt;/code&gt;, иначе узкий диапазон превращает риск 1% в 3% счёта.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Учёт гэпа через стоп.&lt;/strong&gt; Риск на сделку считать как &lt;code&gt;D + g&lt;/code&gt;, а не как &lt;code&gt;D&lt;/code&gt;; на коротких диапазонах это меняет размер позиции в разы.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Walk-forward, а не in-sample.&lt;/strong&gt; Обучение на 2016–2021, проверка на 2022–2023, финальная проверка на 2024–2026. Один и тот же параметр &lt;code&gt;k&lt;/code&gt;, выбранный по всему периоду, — это уже подгонка.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;И пятое, организационное: журнал первых 50 живых сделок с фактическими R и сравнение распределения с бэктестом. Расхождение в медиане больше 0.2R означает, что проблема не в стратегии, а в исполнении — и решать её надо на уровне инфраструктуры, а не параметров.&lt;/p&gt;
&lt;h2 id=&quot;vyvody&quot;&gt;Выводы&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Бар-за-бару исполнение в PyBroker снимает целый класс ошибок: заглядывание вперёд становится невозможным, а не «не рекомендованным». Цена этого — необходимость думать про следующий бар (вход на 09:35, выход на 15:58).&lt;/li&gt;
&lt;li&gt;Экономика ORB держится на редких крупных выигрышах: при тейке в десять R безубыточный winrate — 9%, при тейке в три R — уже 25%. Стратегия чувствительна не к точности входа, а к сохранности хвоста выигрышей.&lt;/li&gt;
&lt;li&gt;«Риск 1% на сделку» на узком стопе — это скрытое плечо в 2–3× счёта и удвоение фактического убытка при проскальзывании через стоп. Ограничение номинала обязательно, а не желательно.&lt;/li&gt;
&lt;li&gt;Результат 2026 года (−8% при +16% у индекса) — не аргумент против ORB как идеи, а аргумент против публикации стратегии без разбивки по режимам и без модели издержек.&lt;/li&gt;
&lt;li&gt;Порядок издержек (0.08–0.14R на круг) достаточен, чтобы изменить вывод о пригодности стратегии. Пока он не в модели, любые абсолютные цифры доходности — верхняя граница, а не оценка.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;pervoistochnik&quot;&gt;Первоисточник&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Видео: &lt;a rel=&quot;external&quot; href=&quot;https://youtu.be/Rk-Oxn5GzOo&quot;&gt;PyBroker: Backtesting 5 Minute ORB Strategy on QQQ&lt;/a&gt;, канал Part Time Larry, 31:27. Числа прогонов, константы стратегии и последовательность шагов — из этого разбора; код в статье — авторский скелет под API PyBroker 2.x, а не код автора видео.&lt;/li&gt;
&lt;li&gt;Библиотека: &lt;code&gt;lib-pybroker&lt;/code&gt; (PyBroker), минутные данные QQQ за 2016–2026.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;sviazannye-razbory&quot;&gt;Связанные разборы&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/posts/decomposed-returns-quote-skewing-market-making/&quot;&gt;Декомпозиция доходности: где на самом деле живёт альфа&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/posts/mit-poker-roadmap-quant-trading-game-theory-variance/&quot;&gt;MIT Poker Roadmap: квант как игра с неполной информацией&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/posts/dca-martingale-capital-budget-risk-gates/&quot;&gt;DCA и мартингейл: бюджет капитала и риск-гейты&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
        
    </entry>
</feed>
