Тестер: Как преодолеть ограничения тестера стратегий при тестировании хеджевых советников

 

New article Как преодолеть ограничения тестера стратегий при тестировании хеджевых советников has been published:

Идеи по тестированию хеджевых советников с использованием тестера стратегий.

В данной статье приводятся идеи по тестированию хеджевых экспертов в тестере стратегий. Как Вы знаете, в тестере стратегий имеются ограничения, не позволяющие открывать ордера по другим символам (нет портфельного тестирования). Если есть необходимость протестировать собственный хеджевый эксперт, придется тестировать его на реальном счете. Значит ли это что наши возможности ограничены? Естественно, хеджевым трейдерам необходимо тестировать собственные эксперты перед тем, как использовать их на реальном счете. В данной статье приводятся идеи по созданию виртуального эмулятора тестера стратегий. Надеюсь, это поможет нам преодолеть ограничения в тестере стратегий MetaTrader 4 и окажется полезным при дальнейшем использовании.

Author: chayutra sriboonruang

 
эту идею я реализовал немного по другому. Я собираюсь торговать на одной валюте, но меня сильно интересует, как поведет себя мой советник на других валютах, убедиться в его устойчивости так сказать. Вот я и слепил девять пар друг за другом, получилось 35 лет истории. Теперь после оптимизации на евре он проходит такой вот тест на выносливость.
 

Если проанализировать хеджирование коррелированных инструментов с точки зрения математики, то получается, что открытие разнонаправленных позиций по двум положительно коррелированным инструментам и ононаправленным - по отрицательно коррелированным, равносильно торговле синтетического инструмента вида (в данном случае):

EUR/JPY-k*GBP/JPY, где k - некоторая константа призванная "выровнять" волатильность исходных пар.

Возможно, новый синтетический инструмент обладает рядом свойств, эксплуатация которых позволяет получать прибыль... На верхней картинке показаны два временных ряда (ВР): GBP/JPY и k*EUR/JPY+constanta. Действительно, можно отметить хорошую положительную коррелированность рядов.

Теперь построим синтетический ряд вида EUR/JPY-k*GBP/JPY см. нижний рис. синий цвет. Ничего не напоминает? Для сравнения, на этот график наложен инструмент k1*EUR/GBP+constanta1 (красный цвет).

Неожиданный результат! Неправда ли? На самом деле, этот результат получается и строго математически если пренебречть в выкладках малыми вторго порядка, т.е. с точностью до этих малых, выполняется равенство:

EUR/JPY-k*GBP/JPY = k1*EUR/GBP+constanta1.

Выходит, что хеджирование по описанной в данной статье методике, равносильно торговле на инструменте EUR/GBP но с "двойным" спредом! Получаются те же яйца (вид c другой стороны). Или я что-то упускаю?

Конечно, данная методика позволяет синтезировать различные экзотические инструменты которых нет в природе (или в данном ДЦ) и работать с ними. Но, увеличенная комиссия за каждую транзакцию сведёт на НЕТ весь потенциальный арбитраж синтетического инструмента. Вобще, наличие арбитража в том или ином инструменте это скорее редкое исключение, чем правило, а уж попытка его увеличения путём сложения двух ВР скорее приведёт к потере всякой арбитражности.

 
to Neutron:

Странное какое-то у тебя выражение: EUR/JPY-k*GBP/JPY = k1*EUR/GBP+constanta1

Чисто математически должно быть так:  EURJPY / GPBJPY = EURGBP. Это если говорить о конкретной котировке.
Если же рассматривать движение пар, то получаем: k1*EURJPY / (k2*GBPJPY) = k1/k2 * EURGBP.  Логично?

Отсюда простой вывод: если EURGBP движется прямолинейно (k1/k2=const), то EURJPY и GBPJPY будут двигаться синхронно, с коэффициентом пропорциональности = k1/k2.
Если же EURGBP выписывает кренделя, то никакой синхронности не будет.

В этом то и состоит всё коварство форекса, в отличие от других рынков. Валютные пары увязаны между собой математически, поэтому торговля по одной из них неизбежно влияет на движение других.
Если же где-то и образуется расхождение, то арбитражёры быстро устраняют это
 
Skycat:
эту идею я реализовал немного по другому. Я собираюсь торговать на одной валюте, но меня сильно интересует, как поведет себя мой советник на других валютах, убедиться в его устойчивости так сказать. Вот я и слепил девять пар друг за другом, получилось 35 лет истории. Теперь после оптимизации на евре он проходит такой вот тест на выносливость.

Как Вы это сделали ? Можете обьяснить?
 

Это полезная статья. Предлагаю немного более прозрачный код для использования тестера со многими валютами.

Идея та же - заменить MarketInfo(..) соответствующим файлом, т.к. тестер не может взять инфо из других пар.


1. Сначала создаём небольшой советник который записывает эти файлы:

extern string mini = "";
string stmp;
int ho; // идентификатор файла, записывающего bid & ask
string fname;
void putBidAsk() {
FileWrite(ho, TimeToStr(TimeCurrent(),TIME_DATE|TIME_SECONDS), Bid, Ask);
}
//+--------------------------------------------------------------------+
int init() {
//+----------------pairs div ----------------------------------------+
fname = Symbol() + "bidAsk";
ho = FileOpen(fname,FILE_CSV|FILE_WRITE); // открываем файл для bid/ask
if (ho < 1) Print("***Can't open ", fname);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
int deinit() {
FileFlush(ho);
FileClose(ho);
return(0);
}
//+------------------------------------------------------------------+
int start() {
if (!IsTradeAllowed() || IsTradeContextBusy()) return;
RefreshRates();
putBidAsk();
return(0);
}

Мы можем заменить/добавить параметры в FileWrite(ho, TimeToStr(TimeCurrent(),TIME_DATE|TIME_SECONDS), Bid, Ask);

на любые другие из MarketInfo


2. В советнике, который должен работать со многими парами добавляем в начале код:

//+---------------- работа с файлами bid/ask ----------------------------------+
extern string mini = "";
int pairCnt = 6;
string pairs[6][2] = {"EUR","USD",
"EUR","GBP",
"EUR","JPY",
"GBP","USD",
"USD","JPY",
"GBP","JPY"};
string stmp;
string stime[5]; //строки времени из файлов pairCnt - 1
double rates[6][2]; // pairCnt
int ho[5]; // идентификаторs файлов с записанными bid & ask, кроме 1-го (pairCnt - 1)
bool test = true; //для тестера нужны файлы с bid & ask
void getRates() {
for (cnt =0;cnt < pairCnt;cnt++) {
stmp = pairs[cnt,0] + pairs[cnt,1] + mini;
if (test && cnt > 0) getBidAsk(); //для тестера взять bid & ask из файлов
else {
rates[cnt,0] = MarketInfo(stmp, MODE_BID);
rates[cnt,1] = MarketInfo(stmp, MODE_ASK);
}
//Print("*rate ",stmp," bid ",rates[cnt,0]," ask ",rates[cnt,1]);
}
}
//+------------------------------------------------------------------+

void getBidAsk() {
string s = TimeToStr(TimeCurrent(),TIME_DATE|TIME_SECONDS);
while (stime[cnt - 1] < s) {
if (FileIsEnding(ho[cnt - 1])) return;
getNextBidAsk();
}
}
//+------------------------------------------------------------------+
void getNextBidAsk() {
if (FileIsEnding(ho[cnt - 1])) return;
stime[cnt - 1] = FileReadString(ho[cnt - 1]);
string s = FileReadString(ho[cnt - 1]);
rates[cnt,0] = StrToDouble(s);
s = FileReadString(ho[cnt - 1]);
rates[cnt,1] = StrToDouble(s);
}
//+------------------------------------------------------------------+


Список пар может быть любым. Надо поменять pairCnt и размеры соответствующих массивов (см. комментарии)


3. В конце init добавляем код:

if (!test) return; //файлы нужны только в режиме тестера
for (cnt = 1; cnt < pairCnt; cnt++) {
stmp = pairs[cnt,0] + pairs[cnt,1] + "bidAsk";
ho[cnt - 1] = FileOpen(stmp,FILE_CSV|FILE_READ); // открываем файлы для чтения bid/ask
if (ho[cnt - 1] < 1) Print("***Can't open ", stmp);
getNextBidAsk();


4. Для работы с парами добавляем в start вызов getRates()

Значения bid/ask (или чего-то другого в зависимости от FileWrite(ho, ...) в writeBidAsk советнике и

процедуры getNextBidAsk()) помещены в rates для соответствующих пар


5. Запускаем советник writeBidAsk для всех используемых пар.


6. Тестируем целевой советник.


Если есть вопросы - echashnik@comcast.net