Експеримент: Наскільки ірраціональна біржова торгівля на коротких інтервалах (скальпінг)



Розробник і трейдер Йоан Крістіан Лоттер, творець бога Financial Hacker, написав цікавий матеріал, в якому розповів про свій експеримент, покликаний з'ясувати, чи має сенс торгівля з використанням коротких і надкоротких інтервалів для здійснення угод. Ми представляємо вашій увазі головні думки цієї замітки.

Починаючі трейдери часто хочуть працювати на дуже коротких часових інтервалах. Деякі з них надихаються історіями про те, як хтось заробив $2000 за п'ять хвилин — такого добра дуже багато на фінансових фороумах. Інші почули про високочастотної торгівлі і тепер впевнені, що чим вище частота здійснення угод, тим краще підсумковий результат. Повністю це марне заняття або у такий короткостроковій торгівлі є якісь кількісні переваги? Експеримент, метою якого було з'ясувати, показав несподівані результати.

Спокуса отримувати доходи протягом якихось хвилин дуже великий. Крім того, при торгівлі на коротких часових інтервалах (таймфреймах) здійснюється більше угод і є більше барів для аналізу і поліпшення стратегії. Якість тестів і навчання залежить від обсягу доступних даних. І тим не менш скальпінг — тобто відкриття та закриття угод за хвилини або навіть секунди — в середовищі алготрейдерів багатьма вважається нісенітницею і чимось ірраціональним. Цьому є кілька причин:

  1. Короткі таймфрейм призводять до зростання витрат — проскользывание, спред, комісії — по відношенню до очікуваного доходу.
  2. При коротких інтервалах кривої попиту більше шуму, випадковостей і артефактів — все це знижує дохід і збільшує ризик.
  3. Кожен торговий алгоритм потрібно адаптувати для роботи з конкретним брокером або постачальником фінансових даних, оскільки для успішної торгівлі вкрай важлива якісна робота з потоком даних про ціни (price feed).
  4. Алгоритмічні стратегії зазвичай просто припиняють працювати на таймфреймах нижче певного значення.
Високі витрати, менша вигода, більший ризик, залежність від дата-фіда, непрацюючі алгостратегии — непогані аргументи проти скальпинга (HFT — зовсім інша історія). Незважаючи на те, що викладене вище може бути правдою, і наприклад, експерименти показують, що при бэктестинге стратегій на таймфреймах менше 10 хвилин на даних від різних брокерів результати сильно різняться. Але це не означає, що такий спосіб торгівлі на біржі не має ніякого сенсу, може бути робота з невеликими таймфрейм просто вимагає особливого підходу?

Щоб це з'ясувати, Лоттер провів експеримент, який включав створення реальної стратегії скальпинга.

Вплив супутніх витрат

Перша частина експерименту полягала в статистичному аналізі вплив на підсумковий фінансовий результат супутніх витрат. Логічно, що більш високі витрати вимагають більшого доходу, щоб якось їх компенсувати. Скільки успішних угод потрібно зробити, щоб прибуток перевищив витрати на торгівлю на різних таймфреймах? Невеликий скрипт нижче відповідає на це питання:

function run()
{
BarPeriod = 1;
LookBack = 1440;
Commission = 0.60;
Spread = 0.5*PIP;

int duration = 1, i = 0;
if(!is(LOOKBACK))
while(duration <= 1440)
{ 
var Return = abs(priceClose(0)-priceClose(duration))*PIPCost/PIP;
var Cost = Commission*LotAmount/10000. + Spread*PIPCost/PIP;
var Rate = ifelse(Return > Cost, Cost/(2*Return) + 0.5, 1.);

plotBar("Min Rate",i++,duration,100*Rate,AVG+BARS,RED); 

if(duration < 10) duration += 1;
else if(duration < 60) duration += 5;
else if(duration < 180) duration += 30;
else duration += 60;
}
Bar += 100; // hack!
}

Скрипт обчислює мінімальну ступінь успішності угод, яка потрібна для того, щоб компенсувати витрати при торгівлі на різних часових інтервалах. Передбачається, що існує спред розміром 0,5 піпса (мінімальної величини зміни ціни валютної пари) і загальна комісія у 60 центів на 10000 контрактів — середня вартість угод на фінансовому ринку. PIPCost/PIP в коді вище — це фактор конверсії цінової різниці надбавку або втрату грошей на рахунку. Також передбачається відсутність впливу психологічних факторів на торгівлю: всі трейдери повинні в середньому отримувати прибуток або програвати однаковим чином. Це дозволяє розбити величину Return угоди на її прибутковість або збитковість, які визначаються показником WinRate. Тобто, якщо операція прибуткова, то ми отримаємо WinRate * Return, а якщо збиткове, то (1-WinRate) * Return. Для виходу на окупність потрібно, щоб різниця між успішними угодами і збитковими покривала витрати. Ступінь успішності в цьому випадку повинна бути такою:

WinRate = Cost/(2*Return) + 0.5


Цей показник усреднен по всіх барах і зображено у вигляді гістограми тривалості угод від 1 хвилини до 1 дня. Крок збільшення таймфрейма становить 1, 5, 30 і 60 хвилин. Угода для будь-якої тривалості відбувається кожні 101 хвилин (Bar +=100 в скрипті — це хитрість, щоб запустити симуляцію на кроці, починаючи зі 101-го, при цьому зберігаючи період бару дорівнює 1 хвилині).

Скрипту потрібно кілька секунд, а потім він видає ось таку гістограму для валютної пари EUR/USD в 2015 році:



Для покриття витрат при торгівлі на інтервалі до 1 день (крайній правий бар) потрібен показник успішності 53%, а для 1-хвилинних угод він виростає вже до 90%. Тобто співвідношення винагороди до ризику становить 9:1 для показника успішності в 50%. Це значно перевищує реальний дохід, що генерується торговими системами. Здавалося б, підтверджується перший пунт зі списку вище, і стає зрозуміло, що оповідання «успішних скальперів» з форумів про трейдинге потрібно сприймати з изредной часткою скептицизму.

Але як щодо другої тези про те, що на коротких таймфреймах більше шуму і випадковостей? Чи є якийсь спосіб, який дозволить домогтися більшої передбачуваності. З'ясувати це вже складніше.

Вимірювання випадковості

«Шум» часто описують з допомогою компонента високочастотної торгівлі під назвою сигнал. Зазвичай короткі тимчасові інтервали генерують більше hft-компонентів, чим більш довгі таймфрейм. Їх можна знаходити за допомогою фільтра високих частот і усувати за допомогою фільтра нижніх частот. Але є проблема: шум кривої попиту не завжди пов'язане з високими частотами. Шум це просто частина кривої, яка не несе в собі інформації про торгові сигнали. Для циклічного торгівлі, високі частоти — це сигнали, а низькочастотні тренди є шумом. Іншими словами, те, що є шумом, залежить від конкретної стратегії — немає якогось «універсального» шуму.

Таким чином для визначення «торгуемости» кривої попиту потрібен якийсь інший критерій. Це випадковість (randomness). Її можна виміряти за допомогою інформаційної наповненості кривої попиту. Хороша міра інформаційної наповненості — це ентропія Шеннона. Вона визначається так:



Ця формула вимірює невпорядкованість. У разі упорядкованого, передбачуваного сигналу ентропія буде низькою. Випадковий, непередбачений сигнал володіє високою ентропією. У формулою P(sі) — відносна частота виникнення конкретного патерну sі в сигналі s. Ентропія буде максимальною, коли всі патерни рівномірно розподілені, а все P(sі) приблизно рівні. Якщо якісь патерни виникають частіше інших, ентропія знижується. В такому випадку сигнал буде менш випадковим і більш передбачуваним. Ентропія Шеннона вимірюється в бітах.

Нижче представлений код індикатора ентропії Шеннона, зображуваної у вигляді послідовності символів:

var ShannonEntropy(char *S,int Length)
{
static var Hist[256];
memset(Hist,0,256*sizeof(var));
var Step = 1./Length;
int i;
for(i=0; i<Length; i++) 
Hist[S[i]] += Step;
var H = 0;
for(i=0;i<256;i++) {
if(Hist[i] > 0.)
H -= Hist[i]*log2(Hist[i]);
}
return H;
}

У символі 8 біт, так що в рядку може бути 28 = 256 символів. Частота кожного символу обчислюється і зберігається в масиві Hist. Цей масив містить P(sі) з формули ентропії вище. Потім ці значення помножуються на двійковий логарифм і підсумовуються. У результаті виходить H(S) — це ентропія Шеннона.

У коді вище символ є паттеном сигналу. Таким чином потрібно конвертувати криву попиту в символьні патерни. Це можна зробити за допомогою функції
ShannonEntropy
, яка викликає попередню:

var ShannonEntropy(var *Data,int Length,int PatternSize)
{
static char S[1024]; // hack!
int i,j;
int Size = min(Length-PatternSize-1,1024);
for(i=0; i < Size; i++) {
int C = 0;
for(j=0; j<PatternSize; j++) {
if(Data[i+j] > Data[i+j+1])
C += 1<<j;
}
S[i] = C;
}
return ShannonEntropy(S,Size);
} 

PatternSize
визначає сегментування кривої попиту. Патерн визначається числом змін ціни. Кожна нова ціна або вище попередньої або ні — це двійкова інформація, що описує один біт патерну. Патерн може включати до 8 бітів, що еквівалентно 256 комбінацій змін ціни. Патерни також зберігаються в символьній стрічці. Їх ентропія визначається за допомогою виклику функції
ShannonEntropy
для конкретної рядки (як видно, в обох функцій одну і ту ж назву, але компілятор їх розрізняє за параметрами). Патерни генеруються на основі ціни і наступних цінах
PatternSize
. Далі процедура повторюється для наступної ціни, таким чином відбувається накладення патернів.

Несподіваний результат

Тепер залишається лише намалювати гістограму ентропії Шеннона, як ми зробили вище з показником успішності:

function run()
{
BarPeriod = 1;
LookBack = 1440*300;
StartWeek = 10000;

int Duration = 1, i = 0;
while(Duration <= 1440)
{ 
TimeFrame = frameSync(Duration);
var *Prices = series(price(),300);

if(!is(LOOKBACK) && 0 == (Bar%101)) {
var H = ShannonEntropy(Prices,300,3);
plotBar("Randomness",i++,Duration,H,AVG+BARS,BLUE); 
}
if(Duration < 10) Duration += 1;
else if(Duration < 60) Duration += 5;
else if(Duration < 240) Duration += 30;
else if(Duration < 720) Duration += 120;
else Duration += 720;
}
}

Ентропія обчислюється для всіх таймфрейм на кожному 101-м барі (таке число вибрано, щоб уникнути проблем з синхронізацією). Тут не можна просто пропустити сто барів, як у попередньому скрипті, оскільки це не дозволить адекватно обробляти цінові ряди. Тому скрипту потрібно вивчити кожну торгову хвилину за останні три роки, на що йде кілька хвилин.

У коді є два рядки, які важливо пояснити — вони важливі для вимірювання ентропії денних свічок з використанням барів для перидов менш дня:

StartWeek = 10000;


Тиждень починається опівночі понеділка ( 1 = понеділок, 00 00 = опівночі), замість 11 вечора неділі. Якщо вибрати останнє значення, то скрипт буде розглядати цей один недільний годину, як повний день, що збільшує випадковість денних свічок.

TimeFrame = frameSync(Duration);


Ця рядок потрібна для синхронізації таймфрейма з годинником у ході дня. Якщо її прибрати, то ентропія Шеннона денних свічок буде занадто велика.

Ентропія Шеннона обчислюється для патерну розміром 3 змін ціни, що призводить до наявності 8 різних патернів. Максимальна ентропія для 8 патернів становить 3 біта. Оскільки зміни ціни не повністю випадкові, можна було б припустити, що ентропія буде менше 3, зростаючи із зменшенням таймфрейма. Однак для даних по торгах валютної пари EUR/USD у 2013-2015 роках, вийшла наступна гістограма:



Ентропія становить майже 3 біта. Це підтверджує тезу про не повною випадковості ціни. Як видно, ентропія Шеннона буде найменшою для таймфрейма 1440 розміром хвилин — вона становить близько 2,9. Це очікуваний результат, оскільки денні цикли серйозно впливають на криву попиту, тому денні свічки більш передбачувані. Тому алгоритми цінових патернів часто використовують денні свічки. Ентропія зростає із зменшенням таймфрейма, але так відбувається лише до таймфрейм розміром десять хвилин. А ще більш короткі часові інтервали насправді менш випадкові.

І ось це вже несподіванка. Чим менше таймфрейм, тим менше котирувань ціни він містить у собі, це повинно збільшувати елемент випадковості. Але відбувається навпаки — так відбувається для різних часових інтервалів (навіть надкоротких 2, 5, 10, 15, 30, 45 і 60 секунд) і навіть для різних активів.



Ентропія vs таймфрейм (в секундах)

Тепер вісь x — це секунди, а не хвилини. І все одно випадковість знижується разом зі зменшенням таймфрейма.

Цьому може бути кілька пояснень. Гранулярність ціни вище на невеликих таймфреймах, оскільки в них міститься менша кількість тактів (мінімальних коливань ціни). Великі угоди часто розбивають на багато невеликих частин («Iceberg-накази»), що може призводити до появи послідовностей схожих цінових котирувань на коротких часових інтервалах. Все це знижує цінову ентропію коротких таймфрейм, але зовсім необов'язково призводить до появи можливостей для торгівлі.

Послідовність однакових котирувань має нульову ентропію, вони на 100% передбачувані, але їх не можна використовувати для торгівлі. Угоди айсберг представляють певну неефективність ринку, яку теоретично можна використовувати — але цьому заважає високі витрати на здійснення угоди. Якщо б не було брокерських комісій, то це було б можливо, але не в поточній ситуації.

Висновки

  • Скальпінг — це не повне божевілля. Навіть у дуже невеликих таймфрейм є якась регулярність.
  • Тим не менш, цю регулярність важко використовувати приватному трейдеру з-за високих витрат на здійснення операцій.
  • Для таймфрейм вище 60 хвилин ціни стають менш випадковими і більш передбачуваними. Це означає, що такі таймфрейм добре використовувати для алгоритмічної торгівлі.
  • Найбільш передбачувані ціни для одноденних барів. При торгівлі з використанням їх також будуть мінімальні витрати.


Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.