Fáze Vývoje Strategie - Intradenní strategie používajíci Price Patterns

Fáze Vývoje Strategie

Mezi tradery je velice populární vyvíjet a obchodovat intradenní strategie. Důvody jsou prosté. Tento typ strategií do značné míry limituje potenciálně maximální drawdown tím, že strategie není vystavena riziku nočních pohybů a víkendových gapů. Pravidlo, že čím méně celkového času je strategie v pozici, tím nižší ji vystavujete celkovému riziku určitě platí. 

Na druhou stranu si tím dost omezujete i celkový potenciál ziskovosti. Nicméně pojďme si ukázat, jakým tradičním způsobem bychom mohli intradenní strategii vyvíjet.

Mezi naše velmi oblíbené typy strategií patří ty, které používají na vstupních podmínkách určité cenové patterny. Na ně se taky zaměříme.

faze vyvoje strategie klicove informace

Nejprve si připomeňme v základních bodech, za jakých podmínek jdeme strategii vyvíjet:

  1. Trh: E-mini Russell 2000 (při nižších kapitalizacích Micro E-mini Russell 2000)
  2. Timeframe: 60 min bar
  3. Obchodní seance: 08:45 a.m. – 03:03 p.m.
  4. In-Sample data: 1.1.2006 – 1.7.2015
  5. Out-of-sample data: 1.7.2015 – 10.11.2020

Podmínky vývoje strategií:

1. Definice výstupní podmínky na konci obchodní seance

Základní výstupní podmínkou je, že nechceme držet pozice přes noc. Chceme tedy vždy vystoupit z pozice nejpozději na konci obchodní seance. EasyLanguage disponuje jedním výstupním obchodním příkazem, který tuto podmínku splňuje a tím je:

SetExitOnClose;   

Tento kód splňuje kritéria:

  • Exit Conditions (Výstupní podmínky) – Podmínkou tedy je, že strategie vystoupí z pozice na konci dne, v našem případě tedy 03:03 p.m.
  • Výstupní příkazy (Exit Orders) Vytupujeme ze všech pozic obchodním příkazem Market. Tento příkaz umí odlišit, jestli vystoupit z dlouhé (long) či krátké (short) pozice.
2. Definice vstupních Price Patterns podmínek

Předpokladem je, že chceme vyvíjet strategii, která obchoduje na obě strany, jak long, tak short a má tyto podmínky zrcadlové identické. Motivací k vývoji těchto strategií je disponovat strategií, která bude stabilně profitabilní ideálně v jakémkoliv tržním režimu (byčí, medvědí trhy, flat).

 

Vstupní podmínky jsou proměnnými, které nám určují, zdali jsou splněná předem nadefinovaná vstupní kritéria, abychom mohli vstoupit do pozice. Pokud jsou podmínky splněné vstoupíme do pozice long či short. V případě, že nejsou podmínky splněny, do pozice nevstoupíme. V rámci vstupních podmínek se často používají matematické operátory. Existují tyto typy:

            <, což značí je menší

            >, což značí je větší

            =, což značí rovná se

            <=, což značí je menší rovno

            >=, což značí je větší rovno

            <>, což značí nerovná se 

 

Price Patterny pracují především s těmito Funkcemi, které mají předdefinovanou určitý úkol (Functions):

OpenD(PeriodsAgo)

HighD(PeriodsAgo)

LowD(PeriodsAgo)

CloseD(PeriodsAgo)

Jedná se o otevírací (OpenD), uzavírací (CloseD), nejvyšší (HighD) či nejnižší (LowD) ceny v rámci nadefinované obchodní seance pro daný den, který je definovaný hodnotou PeriodsAgo.

Takže například hodnota CloseD(1) znamená uzavírací cenu předchozího dne, v našem případě v 03:03 p.m.

Oproti tomu HighD(0) znamená prozatím nejvyšší hodnotu High pro aktuální den.

V případě HighD(2) by se jednalo o nejvyšší hodnotu High z obchodní seance před dvěma dny.

A také OpenD(0) znamená hodnotu otevírací cany pro aktuální den, v našem případě tedy 08:45 a.m.

Tak co například tyto formace, kdy:

{ Variables for entry and exit conditions }

Var: EntryConditionLong(false),

        EntryConditionsShort(false);

 

{ Entry and exit conditions }

EntryConditionLong = CloseD(1) <= LowD(0) and OpenD(0) >= O;

EntryConditionShort = CloseD(1) >= HighD(0) and OpenD(0) <= O;

 

Pro vysvětlení Var: definují tzv. Variables (Proměnné), které jsou programátorem definovaná slova nebo písmena, která slouží ke skladování určité informace.  Variables vždy definujeme na začátku kódu a nesou informaci, která se v průběhu času mění. EasyLanguage disponuje dvěma typy Variables:

1) Numeric  – Variables, které je přiřazena číselná hodnota, která se v průběhu času  může měnit. V tomto konkrétním příkladu, co jsme si zde odprezentovali, žádná numerická podmínka není.  

2) Boolean – Variables, které skladují informace pouze true (pravda) nebo false (nepravda). Tzn., že v průběhu času je skladovaná informace pouze jako  pravdivá nebo nepravdivá. Ve chvíli, kdy je  true  – pravdivá, tak je daná informace aktivní a ve chvíli, kdy je false – nepravdivá, tak je daná informace neaktivní.

 

Příklady Boolean – Variables v kódu jsou  

Var: EntryConditionLong(false),

        EntryConditionsShort(false);

Pojďme si nyní vysvětlit konkrétní podmínky:

EntryConditionLong = CloseD(1) <= LowD(0) and OpenD(0) >= O;

EntryConditionShort = CloseD(1) >= HighD(0) and OpenD(0) <= O;

 

První věc, které si můžete všimnout, je fakt, že kód obsahuje dvě podmínky, které se zrcadlí jak na long, tak na short stranu.

EntryConditionLong

V překladu znamená podmínka vstupu do dlouhé (long) pozice, že uzavírací cena Close obchodní seance z předchozího dne, tedy v 03.03 p.m. („CloseD(1)“) je menší rovna nejnižší ceně Low aktuálního dne („LowD(0)“) a zároveň je otevírací hodnota aktuálního dne v 08:45 a.m. („OpenD(0)“) větší rovna než hodnota Open („O“) posledního baru.

EntryConditionShort

V překladu znamená podmínka vstupu do krátké (short) pozice, že uzavírací cena Close obchodní seance z předchozího dne, tedy v 03.03 p.m. („CloseD(1)“) je větší rovna nejvyšší ceně High aktuálního dne („HighD(0)“) a zároveň je otevírací hodnota aktuálního dne v 08:45 a.m. („OpenD(0)“) menší rovna než hodnota Open („O“) posledního baru.

Vstupní obchodní příkaz

Níže uvádím kód EasyLanguage, který jasně definuje vstup do dlouhé i krátké pozice

{ Entry orders }

Dlouhá pozice

If (MarketPosition = 0) and (EntriesToday(Date) < 1) and EntryConditionLong then begin

    Buy(„EntryConditionLong“) next bar at market;

end;

V překladu tato část kódu znamená:

Pokud nejsme v pozici („MarketPosition=0“) a zároveň jsme ještě pro daný den nevstoupili do pozice (EntriesToday(Date) < 1) a zároveň je splněná podmínka EntryConditionLong pak vstup do dlouhé pozice příkazem Buy Market na příštím baru hned po zformování aktuálního baru (Buy(„EntryConditionLong“) next bar at market).

If (MarketPosition = 0) and (EntriesToday(Date) < 1) and EntryConditionShort and EntryConditionLong = false then begin

    Sell short(„EntryConditionShort“) next bar at market;

end; 

V překladu tato část kódu znamená:

Pokud nejsme v pozici („MarketPosition=0“) a zároveň jsme ještě pro daný den nevstoupili do pozice (EntriesToday(Date) < 1) a zároveň je splněná podmínka EntryConditionShort a podmínka EntryConditionLong neplatí („EntryConditionLong = false“) pak vstup do krátké pozice příkazem Sell Short Market na příštím baru hned po zformování aktuálního baru („Sell short („EntryConditionShort“) next bar at market“)

A tímto jsme v podstatě nadefinovali velice jednoduchou strategii doslova na pár řádků.

Na Obrázku 1 můžeme vidět celý kód v EasyLanguage:

Obrázek 1: Strategie Intraday Strategy with Simple Price Pattern“ v EasyLanguage

Výchozí situace strategie „Intraday Strategy with Simple Price Pattern“:

  • Nadefinovali jsme si tedy strategii, která vystupuje vždy na konci obchodní seance v 03:03 p.m. na trhu E-mini Russell 2000
  • Má jednoduchý price pattern pro vstup jak dlouhé, tak krátké pozice, které jsou zrcadlové. Když jsou tyto jednoduché podmínky splněny, strategie vstoupí do pozice příkazem market do longu nebo shortu při otevření následující úsečky
  • Může otevřít maximálně jednu pozici za den
  • Obchoduje fixně s jedním kontraktem
  • Neobsahuje žádné vstupní parametry (vstupní parametry může být například délka klouzavého průměru atp.). Tím pádem se jedná o velice jednoduchou strategii s dalším potenciálem ke zlepšení (tzn. můžeme přidat další podmínky)
  • Podmínky strategie byly budovány na In-Sample datech, tedy od 1.1.2006 do 1.7.2015, pojďme se nyní podívat na Ekvity křivku strategie. Počítáme s celkovým nákladem $10 USD na slippage a komisi dohromady (round-turn) za jeden obchod. Ekvity křivka vypadá následně:

Obrázek 2: Ekvity křivka strategie „Intraday Strategy with Simple Price Pattern“

  • Z Obrázku 2 můžeme vidět, že strategie za období In-Sample vygenerovala celkově 1374 obchodů s celkovým čistým ziskem $43,165. (U Micro E-mini kontraktu by to bylo tedy $4316,5. Na long stranu strategie vydělala $19,035 a na Short
  • Long obchodů je 702, Short 672
  • Maximální drawdown činí $9 805 (Micro E-mini $980)
  • Průměrný zisk na obchod po odečtení nákladů $10 na jeden obchod je $42
  • Nejziskovější byla strategie v roce 2008, vydělala celých $19,630
  • Nejztrátovější pak v roce 2012: -$5405

Výhody strategie

  • Je principiálně velice jednoduchá, neobsahuje žádné parametry k optimalizaci. Čím jsou strategie jednodušší, tím lépe (menší riziko přeoptimalizace strategií).
  • Vydělává se zrcadlovými podmínkami jak na long, tak na short stranu (na short stranu dokonce více)
  • Je velmi výkonná v krizovém roce 2008. Otázkou je, zdali potvrdí svoji výkonnost i v rámci krize v roce 2020
  • Obsahuje značný počet obchodů, tím pádem se můžeme pokusit strategii dále vylepšit

Nevýhody strategie

  • Ekvity křivka není natolik stabilní. Strategie obsahuje hodně období stagnací i dvě periody poměrně značných drawdownů

Návrhy na zlepšení strategie

Můžeme se pokusit vylepšit strategii na dvou frontách

  • Přidat další vstupní podmínku

Díky velkému vzorku obchodů si můžeme dovolit zkusit přidat další vstupní podmínku. Je očividné, že strategie svědčí období vyšší volatility (viz rok 2008). Zkusme tedy přidat vstupní podmínku, která bude pracovat s velice známým indikátorem volatility Average True Range s periodou 14:

Nadefinujeme si vstupní parametr:

Input: ATRTreshold(10);

Rovněž i boolean proměnnou:

Vars: ATREntryCondition(false);

A přidáme podmínku, že pokud bude ATR musí být větší než určitá jeho hodnota pro to, abychom mohli vstoupit do pozice. ATRTreshold podrobíme optimalizačnímu testu tak, abychom našli jeho optimální hodnotu:

ATREntryCondition = AvgTrueRange(14) > ATRTreshold;

Výsledný kód bude tedy takto vypadat (Obrázek 3):

Obrázek 3: Strategie „Intraday Strategy with Simple Price Pattern“ v EasyLanguage s přidáním vstupní podmínky s indikátorem volatility ATR

Na Obrázku 3 můžete vidět strategii, která má nově nadefinovaný jeden vstupní parametr (ATRTreshold), který používáme v rámci nové obecné podmínky jak pro long, tak pro short stranu (ATREntryCondition). Všimněte si, že tato podmínka je nyní zakomponována do Vstupních příkazů (Entry Orders).

Nyní jsme připraveni vyzkoušet novou podmínku na optimalizačních testech pro posouzení, jestli má jasně definovatelnou přidanou hodnotu:

Obrázek 4: Výsledky optimalizačních testů strategie „Intraday Strategy with Simple Price Pattern“ v EasyLanguage s přidáním vstupní podmínky s indikátorem volatility ATR (od 1 do 10)

Z Obrázku 4 lze krásně vidět, jak vstupní podmínka ATR dává jasnou logiku. Čím vyšší je v trzích volatilita, tím větší je pravděpodobnosti, že daný vstupní signál s výstupem na konci dne bude fungovat. Závěr jednoznařně vidíme z dvou věcí. S hodnotou ATRTresholdu (první sloupeček) se zvyšuje jednak % Profitable (procento úspěšných obchodů, zvyšuje se Profit Factor a logicky se snižuje počet obchodů, protože období s vyšší volatilitou bývá méně, než období s nižší volatilitou).

Řízení výstupu z pozice

Vyzkoušíme si, jestli není možné v rámci této strategie lépe řídit výstup z pozice například aktivací Stop-Lossu, či posuvného Stop-Lossu, případně Profit Targetu. V našem konkrétním příkladu si ukážeme klasický Stop Loss od vstupní ceny pracující s Average True Range s periodou 14 a prozkoumáme, zdali by nám v rámci In-Sample dat mohl přinést zlepšení:

Fixní ATR Stop-Loss

Nejprve začněme Stop Lossem v případě, že vstoupíme do dlouhé pozice.

{Variables }

Inputs: Multiplier(1);

Var: LongStopLoss(0),

        ShortStopLoss(0);

{ Exit orders, long trades }

If MarketPosition = 1 then begin

    If BarsSinceEntry = 0 then begin

        LongStopLoss = EntryPrice – Multiplier * (AvgTrueRange(14));

    end;

    Sell(„StopLossATR-Long“) next bar at LongStopLoss stop;

end;

Tento kód v podstatě říká, jsme-li v dlouhé pozici (Market Position = 1), poté začneme počítat v rámci daného baru (BarsSinceEntry = 0) a pak začneme s výpočtem LongStopLoss, který se rovná hodnotě Vstupní ceny (EntryPrice) – Násobek (Multiplier) * Average True Range (14). Výstupní úroveň se bude každý bar měnit na základě měnící se hodnoty Average True Range (14). Multiplier je konstanta, kterou si na základě optimalizačních testů můžeme zvolit.

V případě že, dojde k zasažení této ceny, vystoupíme z dlouhé pozice (Sell) na cenové úrovni LongStopLoss příkazem stop market (stop)

Nyní se podívejme na vystoupení z krátké pozice.

{ Exit orders, short trades }

If MarketPosition = -1 then begin

    If BarsSinceEntry = 0 then begin

        ShortStopLoss = EntryPrice + Multiplier * (AvgTrueRange(14));

    end;

    Buy to cover(„StopLossATR-Short“) next bar at ShortStopLoss stop;

end;

Tento kód v podstatě říká, jsme-li v krátké pozici (Market Position = -1), poté začneme počítat v rámci daného baru (BarsSinceEntry = 0) a pak začneme s výpočtem ShortStopLoss, který se rovná hodnotě Vstupní ceny (EntryPrice) + Násobek (Multiplier) * Average True Range (14). Výstupní úroveň se bude každý bar měnit na základě měnící se hodnoty Average True Range (14). Multiplier je konstanta, kterou si na základě optimalizačních testů můžeme zvolit.

V případě že, dojde k zasažení této ceny, vystoupíme z krátké pozice (Buy to cover) na cenové úrovni ShortStopLoss příkazem stop market (stop).

Nyní zkusíme optimalizovat Multiplier a najít jeho ideální hodnotu (Obrázek 5):

Obrázek 5: Výsledky optimalizačních testů strategie „Intraday Strategy with Simple Price Pattern se vstupním indikátorem volatility“ a přidáním Stop Lossu založeném na Average True Range 14

Z Obrázku 5 vidíme, že konstanta Multiplier byla optimalizovaná od 0.1 do 3.1 s inkrementem 0.3. Je jasné, že nejnižší hodnota 0.1 měla velký vliv na celkovou výkonnost strategie, protože k zasažení stop lossu došlo velice často, což mělo obrovský vliv na celkový čistý zisk a procento úspěšných obchodů. Stop Loss jsme chtěli do strategie zařadit především pro potenciálně nižší drawdowny, což ve své podstatě platí (sloupeček Max Intraday Drawdown), ale jasně se ukazuje, že využití tohoto typu Stop Lossu výrazně snižuje celkový zisk, Průměrný zisk na obchod (Avg Trade), úspěšnost obchodů (% Profitable). Použití se tedy jeví spíše kontraproduktivně a z toho důvodu ho nakonec nepoužijeme.

Ověření strategie na Out-of-Sample datech

Finální kód strategie je k dispozici na Obrázku 12. Nyní se pojďme podívat, jak bude strategie výkonná na úplně neznámých datech (Out-of-Sample) tedy od 1.7.2015 do 13.11.2020 (Obrázek 6):

Obrázek 6: Strategie „Intraday Strategy with Simple Price Pattern“ v EasyLanguage s přidáním vstupní podmínky s indikátorem volatility ATR a její výsledek na Out-of-Sample datech

Celkové vyhodnocení strategie „Intraday Strategy with Simple Price Pattern“

  • Velkou výhodou této strategie byla její očividná jednoduchost. Výsledný kód obsahoval jednoduchou vstupní podmínku v podobě Price Patternu, dále jeden parametr k optimalizaci (ATRTreshold) a jednoduchý výstup na konci obchodní seance. Pamatujte, čím jednodušší strategie je, tím lépe pro Váš trading.
  • Backtestovací proces proběhl v pořádku. Strategie se vyvíjela a vytvářela v rámci In-Sample dat.
  • Nicméně je zřejmé, že strategie nepotvrdila svou stabilní výkonnost z In-Sample dat (Obrázek 15). Již na první pohled je tedy zřejmé, že se s největší pravděpodobností jedná o přeoptimalizovanou strategii, která v rámci Out-of-Sample dat nepotvrdila svou výkonnost. Jedna statistika za všechny: V rámci In-Sample dat činil průměrný zisk na obchod $80.69. V rámci Out-of-Sample dat činí průměrný zisk na obchod pouhých $23.95, což by nemuselo až tak vadit, kdyby strategie prakticky nestagnovala od března 2017 do března 2020. Strategie byla pak výrazně profitabilní v rámci COVID krize od začátku března 2020 do začátku května 2020. Od května 2020 do listopadu 2020 je pak ztrátová s téměr $10 000 drawdownem. Strategie tak nepotvrdila svou stabilní výkonnost napříč léty a je zřejmé, že tedy nebude s největší pravděpodobností robustní v rámci živého obchodování.
  • Vzhledem k jednoduchosti vývoje lze s vysokou pravděpodobností konstatovat minimální riziko Selection Biasu, žádné obrovské množství stratetgií jsme nevygenerovali. Přeoptimalizace taky není pravděpodobná, kód je velmi jednoduchý.
  • Strategie nepoužívá žádné limitní příkazy, což je pro backtestování velmi vhodné a přesné.
  • Look-ahead bias lze prakticky vyloučit vzhledem k jednoduchosti kódu strategie. Riziko je naprosto minimální, nicméně bylo by samozřejmě zapotřebí tento potenciální bias ještě ověřit v rámci simulovaného živého obchodování. Pokud ale strategie neprokázala potenciál v rámci Out-of-Sample testů, nemá cenu se samozřejmě simulovaným tradingem vůbec zabývat.
  • Bohužel strategie neobstála v out-of-sample testech. Nemá tedy cenu se jakkoliv zabývat dalšími testy robustnosti, které budeme probírat dále v rámci tohoto Ebooku.
Rada: Pokud out-of-sample ukazuje, že strategie není dost dobrá, zkuste vyvinout novou

Pokud si chcete přečíst celý Ebook Ultimátní Průvodce Jak Na Úspěšný Algoritmický Trading, a nechcete jít článek po článku na našich stránkach, stáhnout si ho můžete okamžite a zcela zdarma zde! 12 kapitol, 118 stránek, všechno na jednom místě.

Leave a comment