Ідея коротко
Фільтр нічого не купує сам. Він відповідає «так» чи «ні» на питання, чи пропускати сьогодні сигнал уже готового входу. У картці два підходи до таких фільтрів від двох систематиків, які будують внутрішньоденні пробійні системи.
Brendan (Trivium System Trading) генерує стратегії в StrategyQuant X і майже не пускає в конструктор індикатори з налаштуваннями. Замість RSI і MACD він закодував близько сотні своїх умов, у яких нічого оптимізувати. Два його приклади: учорашній день закрився вище відкриття; денне закриття вище 200-періодної середньої, де 200 зафіксовано назавжди.
Andrea Unger, чотириразовий чемпіон World Cup Trading Championship, починає з простого скелета: пробій максимуму минулої сесії, вихід наприкінці дня, обов'язковий стоп. Якщо крива зростає, але середня угода не покриває витрати, він проганяє скелет через бібліотеку умов про вчорашній день: тихий день, великий рух, три закриття поспіль угору, понеділок або п'ятниця. Кожна умова перевіряється окремо.
Чому це може працювати
Аргумент Brendan про ступені свободи. У RSI період можна змінювати від двох майже до нескінченності, плюс поріг. У MACD три налаштування. Що більше таких ручок, то простіше підігнати криву під історію. Умова «вчора закрилося в плюсі» або виконана, або ні, і підганяти в ній нічого.
Аргумент Unger про поведінку ринку. Той самий вхід працює по-різному залежно від того, що ринок зробив напередодні. Фільтр відсікає дні, де пробій у середньому гірший, і піднімає середню угоду до рівня, де вона покриває комісію та прослизання.
Обидва аргументи не скасовують відбору. Умова без параметрів стає параметром, щойно її вибирають із сотні інших. Unger захищається від цього так: не шукає найкращий варіант, а дивиться, чи є різниця; залишає умову, лише якщо може її пояснити; занадто гарній кривій не вірить. Про доопрацювання ослабленої системи новими фільтрами він каже прямо: це шлях до підгонки, краще зібрати систему заново від вихідного принципу.
Правила
Блоки Brendan (автор)
// умови рахуються за закритими денними барами й застосовуються на внутрішньоденному графіку
// в автора графіки 30 хвилин, CFD на індекси США, DAX, Nikkei, біткоїн, золото, нафта
UpDay = Close[D1, 1] > Open[D1, 1] // автор: учорашня сесія закрилася в плюсі
Above200 = Close[D1, 1] > MA(Close[D1], 200)[1] // автор: період 200 не оптимізується
// Finetiq: тип середньої не названий, беремо SMA
// Finetiq: дзеркально для шортів Close[D1, 1] < Open[D1, 1] і закриття нижче середньої
// приклад умови, яку знаходив генетичний конструктор (автор наводить її «з голови»)
SessHighVs3W = максимум вікна сесії сьогодні > Open[D1, 15]
// Finetiq: три тижні = 15 торгових днів, вікно = перші 2 години, перевірка після закриття вікна
// у цієї умови вже два приховані параметри: вікно й глибина
Бібліотека умов учорашнього дня (Unger, пороги Finetiq)
Unger називає умови словами. Числових визначень в інтерв'ю немає, нижче стартові значення для перевірки.
// [1] = учорашній закритий денний бар
// автор: денний ряд з 1440-хвилинних барів, щоб закриттям була остання угода, а не settlement
Range1 = High[1] - Low[1]
ATR20 = ATR(20)[1] // Finetiq
Quiet = Range1 < 0.7 * ATR20 // автор: «учора був тихий день»; Finetiq: поріг
Choppy = |Close[1] - Open[1]| < 0.25 * Range1 // автор: «рваний день»; Finetiq: тіло менше за чверть діапазону
HugeMove = Range1 > 1.5 * ATR20 // автор: «великий рух»; Finetiq: поріг
DownClose = Close[1] < Close[2] // автор: закриття вниз «до рівня», рівень не названий
ThreeUp = Close[1] > Close[2] AND Close[2] > Close[3] AND Close[3] > Close[4] // автор
Monday = сьогодні понеділок // автор
Friday = сьогодні п'ятниця // автор
HighVol = ATR(5)[1] > ATR(50)[1] // автор: «висока волатильність»; Finetiq: порівняння
LowADX = ADX(5)[1] < 35 // автор: «нижче 40 або 35»
Процедура відбору (автор, обмеження Finetiq)
// скелет (автор): BUY STOP at PrevHigh, EXIT наприкінці дня (або через 2 дні, або за ціллю), стоп завжди
// скелет придатний, якщо крива зростає, а середня угода менша за витрати (автор)
FOR EACH P IN Library
On = угоди скелета в дні, де P = TRUE
Off = угоди скелета в дні, де P = FALSE
порівняти середню угоду, кількість угод і форму кривої
KEEP P IF різниця помітна AND є пояснення, чому так // автор: здоровий глузд проти збігу
// Finetiq: в On не менше 100 угод, у системі не більше двох умов
// Finetiq: умови вибираються лише на in-sample, рішення перевіряється на out-of-sample
// Validator (автор): зсунути вчорашні High і Open на ±10 тіків, перерахувати систему багато разів
// і подивитися, в якому перцентилі лежить вихідна крива. Край розподілу означає нестійкість
Walk-forward до бібліотеки Unger не застосовує: список патернів не є неперервним параметром, і вибирати «найкращий патерн тижня» безглуздо.
Підключення до карток бази (Finetiq)
// приклад 1: prev-high-breakout-adx. Там фільтр із двома параметрами: ADX(5) < 35
Allowed_A = ADX(5)[1] < 35 // як у картці
Allowed_B = UpDay // фільтр без параметрів замість ADX
Allowed_C = ADX(5)[1] < 35 AND Above200
IF Allowed_x AND TradesToday = 0
BUY STOP at PrevHigh + 1 тік // вхід і вихід картки без змін
// приклад 2: intraday-breakout-eod-exit. Там уже стоять UpDay AND Above200
Filter = UpDay AND Above200 // як у картці
Filter_Test = Filter AND NOT HugeMove // одна нова умова за раз, за процедурою Unger
Параметри
| Параметр | Значення | Звідки |
|---|---|---|
| Період середньої в Above200 | 200, не оптимізується | автор (Brendan) |
| Тип середньої | SMA | Finetiq |
| Вікно сесії в SessHighVs3W | перші 2 години | Finetiq |
| «Три тижні тому» | 15 торгових днів | Finetiq |
| Денний бар | 1440 хвилин, не settlement | автор (Unger) |
| Quiet | діапазон учора < 0.7 ATR(20) | Finetiq |
| Choppy | тіло < 25% діапазону | Finetiq |
| HugeMove | діапазон учора > 1.5 ATR(20) | Finetiq |
| HighVol | ATR(5) > ATR(50) | Finetiq |
| LowADX | ADX(5) < 35 | автор (Unger: 40 або 35) |
| Зсув цін у Validator | ±10 тіків | автор (Unger) |
| Мінімум угод в On | 100 | Finetiq |
| Умов в одній системі | не більше 2 | Finetiq |
Що перевірити
- Різниця on і off для кожної умови. На одному скелеті й одному ринку розбийте угоди за кожною умовою і порівняйте середню угоду після витрат. Зведена таблиця за всіма умовами одразу показує, скільки з них дають різницю випадково.
- Випадковий фільтр тієї самої частоти. Якщо умова істинна, скажімо, у 40% днів, 200 разів розмітьте дні випадково з тією самою часткою і проженіть скелет. Якщо справжній фільтр не виходить за верхні 5% випадкових, його поліпшення пояснюється відбором.
- Зсув цін за Unger. Зсуньте вчорашні High і Open на ±10 тіків (для CFD на 5% ATR) і порахуйте, як часто умова змінює значення і наскільки падає результат.
- Околиця прихованих параметрів. 200 проти 150 і 250, пороги 0.7 і 1.5 ATR проти 0.5–0.9 і 1.2–2.0. Brendan вважає 200 константою, але варто переконатися, що результат не тримається лише на ній.
- Out-of-sample за часом. Вибирайте умови на першій половині історії, оцінюйте на другій. Змінювати набір умов можна лише до цього кроку.
- Інші ринки. Brendan очікує, що логіка, знайдена на NASDAQ, буде хоча б прибутковою на Dow і S&P 500. Unger так не перевіряє. Проженіть фільтр на сусідніх індексах.
- Витрати й кількість угод. Перевірте, чи лишається середня угода після фільтра вищою за подвійні витрати і чи вистачає угод для висновків.
Особливості платформ
TradingView (Pine Script)
- Денні значення на внутрішньоденному графіку:
request.security(syminfo.tickerid, "D", close[1] > open[1], lookahead = barmerge.lookahead_on). Без[1]у бектест потрапляє сьогоднішнє закриття. - Денний бар будується за сесією символу. У ф'ючерсів CME день починається о 18:00 ET напередодні, у CFD торгівля майже цілодобова. «Вчора» на кеш-індексі й на ф'ючерсі різне, і UpDay спрацьовує в різні дні.
- Вікно сесії для SessHighVs3W задавайте з часовим поясом біржі:
time(timeframe.period, "0930-1130", "America/New_York"). Інакше вікно з'їде при переході на літній час.
MultiCharts і TradeStation (EasyLanguage)
- Unger бере 1440-хвилинні бари замість денних. У ф'ючерса в TradeStation денний бар закривається за settlement, 1440-хвилинний за останньою угодою. UpDay і ThreeUp на двох видах бару випадуть на різні дні.
- Денний ряд підключається другим потоком (
Close of Data2). Перевірте на графіку, що під час сесії Data2 віддає вчорашній закритий бар, а не поточний. - День тижня:
DayOfWeek(Date), неділя 0, понеділок 1, п'ятниця 5. AvgTrueRangeце просте середнє TR, у Pine ATR за Вайлдером. Пороги Quiet і HugeMove у частках ATR на двох платформах дадуть різні дні.
MetaTrader 5 (MQL5)
- Учорашній бар:
iOpen(_Symbol, PERIOD_D1, 1)іiClose(_Symbol, PERIOD_D1, 1). Денний бар будується за часом сервера брокера, а не біржі. - У брокерів із сервером не в GMT+2/+3 бувають короткі недільні бари. У понеділок «вчора» виявиться недільним уривком, і UpDay, Quiet і ThreeUp порахуються за ним.
iADXзгладжує не за Вайлдером. Щоб LowADX збігався з Pine і EasyLanguage, берітьiADXWilder.iATRпросте середнє TR, як і в EasyLanguage.- Зсув на ±10 тіків для Validator рахуйте через
SYMBOL_TRADE_TICK_SIZE. У CFD на індекс тік буває 0.01 або 0.1, і 10 тіків ф'ючерса там відповідають іншому зсуву.
Де ідея може зламатися
- Інтерв'ю Brendan вийшло на каналі StrategyQuant, продавця софту, і наприкінці автор рекламує свій курс. Цифр щодо окремих блоків немає, лише загальний висновок, що вони частіше проходять перевірки.
- Нуль параметрів усередині умови не означає нуль ступенів свободи. Генетичний конструктор перебирає сотню блоків та їх поєднання. Brendan сам наводить умову, яка виглядає випадковою, і торгує такі, якщо вони пройшли перевірки.
- Unger не дає числових визначень. З порогами з цієї картки бібліотека вже не безпараметрична, і її треба перевіряти на околицю.
- Validator Unger описує як рекомендацію учням, а сам покладається на досвід. Його здоровий глузд механічно не відтворити.
- Кожен фільтр зменшує вибірку, а Unger ще й будує окрему систему під кожен ринок, не перевіряючи її на інших. Обидві обставини підвищують ризик підгонки.
- «Вчора» залежить від того, де закінчується день: кеш-сесія, торговий день ф'ючерса, сервер брокера. Той самий фільтр на трьох платформах може вибрати різні дні.