Кому стратегию? Много и бесплатно) - страница 57

 
Miroslav_Popov >>:

А можно ещё просадку в процентном отношении добавить, так наглядней. Спасибо.

 

This can be the beginning of a FSB to MQL4 Converter.

Any help or feedback is highly appreciated.


//+------------------------------------------------------------------+
//|                   FSB__Bar_Opening - Bar_Closing.mq4 v0.0.1 Beta |
//|                                 Copyright © 2009, Miroslav Popov |
//|                                              http://forexsb.com/ |
//|                                                                  |
//| An exmple EA pattern:                                            |
//| * Enter the market at Bar Opening                                |
//| * Exit the market at Bar Closing                                 |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Miroslav Popov"
#property link      "http://forexsb.com/"

// The time span before bar closing time in seconds.
// It determines the time interval for position closing.
extern double ClosingTimeSpan = 10;


int start()
{
   // Check if there are open positions from the previous bar
   int iOrders = OrdersTotal();
   if(iOrders > 0)
      ClosePositionsAtBarClosing(true, true, ClosingTimeSpan);
 
 
   
   // Opening Logic Conditions
   bool bLongEntryAllowed  = false;
   bool bShortEntryAllowed = false;

   // Put the entry logic rules here ...
   
   if(iMA(NULL, 0, 13, 0, MODE_SMA, PRICE_CLOSE, 1) >
      iMA(NULL, 0, 13, 0, MODE_SMA, PRICE_CLOSE, 2))
      bLongEntryAllowed = true;
   else
      bShortEntryAllowed = true;


   // Entry at Bar Opening
   iOrders = OrdersTotal();
   if(iOrders == 0)
   {
      if(bLongEntryAllowed || bShortEntryAllowed)
         OpenPositionAtBarOpening(bLongEntryAllowed, bShortEntryAllowed);
         
      iOrders = OrdersTotal();
      if(iOrders > 0)
         return(0);
   }



   // Exit Logic Conditions
   bool bCloseLong  = true;
   bool bCloseShort = true;

   // Put the exit logic rules here ...
   
   // Exit
   if(bCloseLong || bCloseShort)
      ClosePositionsAtBarClosing(bCloseLong, bCloseShort, ClosingTimeSpan);
}

// Entry at a Bar Opening price.
//
// MetaTrader does not provide an onBarOpen event so we check the current tick volume.
// We open a position when the current tick volume is equal to 1.
void OpenPositionAtBarOpening(bool bLongEntryAllowed, bool bShortEntryAllowed)
{
   if(!bLongEntryAllowed && !bShortEntryAllowed)
   { // An entry is not allowed.
      return(0);
   } 
   
   // Check for Bar Opening
   if(iVolume(NULL, 0, 0) > 1)
   {  // This is not the first tick.
      return(0);
   } 
   
   int iLots = 1;

   // Check the free margin.
   if(AccountFreeMargin() < (1000 * iLots))
   {
      Print("We do not have money enough! Free Margin = ", AccountFreeMargin());
      return(0);  
   }
      
   int ticket = 0;
   if(bLongEntryAllowed)
   {
      ticket = OrderSend(Symbol(), OP_BUY, iLots, Ask, 3, 0, 0, "Bar Opening", 0 ,0 , Green);
   }
   if(bShortEntryAllowed)
   {
      ticket = OrderSend(Symbol(), OP_SELL, iLots, Bid, 3, 0, 0, "Bar Opening", 0 ,0 , Red);
   }
   
   if(ticket > 0)
   {
      if(OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES))
         Print("Position opened at: ", OrderOpenPrice());
   }
   else 
   {
      Print("Error opening a position: ", GetLastError());
   }
      
   return(0);
}


// Exit at a Bar Closing price (almost).
//
// MetaTrader does not provide an onBarClose event so we are not able to close a position
// exactly at Bar Closing. We workaround the problem by closing the position within a time span
// near to the bar closing time. In the cases when there is no any ticks within this period,
// we close the position att he next bar opening price.
void ClosePositionsAtBarClosing(bool bCloseLong, bool bCloseShort, datetime dtClosingTimeSpan)
{
   int  iOrders = OrdersTotal();
   bool bIsOpen = false;

   for(int iOrder = 0; iOrder < iOrders; iOrder++)
   {
      OrderSelect(iOrder, SELECT_BY_POS, MODE_TRADES);
      
      if((OrderType() == OP_BUY || OrderType() == OP_SELL) && OrderSymbol() == Symbol())
      {  // There is an open position for this symbol.

         datetime dtOpeningTime     = iTime(NULL, 0, 0) - TimeSeconds(iTime(NULL, 0, 0)); // The opening time of current bar
         datetime dtClosingTime     = dtOpeningTime + Period() * 60;                      // The closing time of current bars
         datetime dtCurrentTickTime = TimeCurrent() ;                                     // The time of current tick
         
         if(
            dtCurrentTickTime > dtClosingTime - dtClosingTimeSpan || // The current tick is within the closing time span.
            iVolume(NULL, 0, 0) == 1                                 // or this is the first tick of next bar
            )
         {
            if(OrderType() == OP_BUY && bCloseLong)
            {  // Close a long position
               bIsOpen = OrderClose(OrderTicket(), OrderLots(), Bid, 3, Violet);
               
               if(bIsOpen)
                  Print("Long position closed at: ", OrderClosePrice());
               else
                  Print("Error closing a position: ", GetLastError());
            }
            else if(OrderType() == OP_SELL && bCloseShort)
            {  // Close a short position
               bIsOpen = OrderClose(OrderTicket(), OrderLots(), Ask, 3, Violet);
               
               if(bIsOpen)
                  Print("Short position closed at: ", OrderClosePrice());
               else
                  Print("Error closing a position: ", GetLastError());
            }
         }
      }
   }
   
   return(0);
}
 

не плохо бы чтобы FSB генерировала dll со стратегией и функция могла бы выглядеть например так:

#define inp   100
//---

#import "FSB.dll"
int    bEntryAllowed(double close[inp], double open[inp], double high[inp], double low[inp], volume[inp]);
#import


то есть посылала по сколько то баров в dll и получала ответ от стратегии


сама длл например так

#define WIN32_LEAN_AND_MEAN  // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
//----
#define MT4_EXPFUNC __declspec(dllexport)
#define inp 100
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
  {
//----
   switch(ul_reason_for_call)
     {
      case DLL_PROCESS_ATTACH:
      case DLL_THREAD_ATTACH:
      case DLL_THREAD_DETACH:
      case DLL_PROCESS_DETACH:
         break;
     }
//----
   return(TRUE);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
MT4_EXPFUNC double __stdcall int    bEntryAllowed(double close[inp], double open[inp], double high[inp], double low[inp], volume[inp])

  {
   int out;

   //--- strategy

   if (close[1]>close[0]) out = 1;
   if (close[1]<close[0]) out = -1;

   return(out);
  }
ведь все равно у вас все индикаторы собственные и нужны только данные временного ряда
 

I'll provide complete FSB <-> MT4 bridge later.

So FSB will take quotation and account info from MT and will send back trading orders. In that way it will be able to trade the FSB strategies in MT.


Now I'm trying to make some basic EA frameworks to fit the FSB strategies in MT as EA without any interop.


I need several simple patterns like:


* Enter (add, reduce, close) at Bar Opening (or Indicator value) when:

- condition1 == true; and

- condition2 == true; and

- condition3 == true; and

- condition4 == true

* Exit at Bar Closing when:

- condition1 == true; or

- condition2 == true;

or

* Exit at Indicator value.

or

* Exit at Permanent Stop Loss

or

* Reverse by following the entry rules.


Most of the indicators are standard and the other are pretty simple and can be easily rewritten in MQL4. Once we have the base EA pattern will be no problem to translate the indicators.


The things I'm testing now are:

Open position at "Bar Opening" and close at "Bar closing".


So I hope to develop two new products:

1. FSB - MT data feed and execution bridge

2. Strategy exporter to MQL4


Probably both programs will be open source.

 

(о, думал уже совсем тишина в теме настала... оживим :)?! (буду писать много... постараюсь логично ;), и чтобы не перегружать - разобью на несколько сообщений)


Господа - приветствую!


Мирослав - сначала пару слов "о погоде" (лирическая часть)... (искренне надеюсь, что понимание русского языка у Вас на должном уровне, т.к. излагать свои мысли на английском рискну в последнюю очередь :))).


Продукт, конечно, шикарный! Говорю, опираясь на свой опыт и как бывшего программиста, и как абстрактного пользователя (абстрактным программным обеспечением). Чувствуется любовь к нему (т.к. сделано все очень аккуратно) и есть надежда, что "неожиданно" развитие программы не остановится (не умрет). Да, скорей всего существуют какие-то логические ошибки (показательный пример был с Data Horizon), есть мелкие огрехи в интерфейсе ... Но в целом - ЭТО ПЕСНЯ! Это просто песня!!!


Прошу обратить внимание общественности еще на один показательный факт. Отношение к критике и стилю обсуждения проблем/недостатков/новых возможностей/и т.д. Это я в контексте начала темы, где началась разработка альтернативного продукта, и как автор SSB реагировал на замечания в свой адрес. Не думаю, что у Мирослава тоже "вагон" времени для разработки БЕСПЛАТНОЙ программы (и что он прям весь из себя такой программист). Но он находит время на нас с вами (чтобы пообщаться), дорабатывает по нашим замечаниям и просьбам свой продукт, исправляет ошибки, ПРЕДЛАГАЕТ что-то новое (см. последние посты). И все спокойно, размеренно, без истерии, как в вышеописанном случае с SSB. Это заслуживает (дополнительного) уважения. Мой поклон, Мирослав...


Заканчивая лирическую часть (отвлеченно уже теперь) - что лично я являюсь сторонником теории "случайного движения цены". Т.е в данном вопросе я полностью разделяю точку зрения определенного круга людей (включая создателей сайтов, вроде http://www.bigmany.ru), которые убеждены, что работая на рынке (я сейчас про Forex и "все, что рядом с ним"), где нет возможности узнать второй из (всего-лишь) двух главных показателей самого рынка (я говорю про Объем (Volume)) - просто бесполезно и бессмысленно (лишено всякого разумного смысла) опираться на какую-либо информацию технического и, в меньшей степени, фундаментального анализа...


На этом можно было бы закончить вообще :), но, как известно - Россия славится дураками и дорогами, и используя первый пункт из данного утверждения - я все-таки не оставляю мысль" заработать миллионы" :D, а на самом деле - мне просто интересно. Интересно слушать "мнения аналитиков" (как астрологи со своими гороскопами - "специалистов много", толку мало), интересно просто смотреть на графики (согласитесь - завораживает), интересно ковыряться в коде (начинаешь реально понимать, что пытались люди выразить данным индикатором), ... просто - интересно... Интересно однажды обмануть (или еще лучше - НЕ однажды) "систему"... Поэтому я здесь (в рынке, условно). И надеюсь принести пользу не только себе, но и общественности. Потому что как и Мирослав - некоторый альтруист по жизни.


Мое текущее мнение, что системы технического анализа, которыми в данный момент пользуются по всему миру (и явное большинство) - действительно, ВЛИЯЮТ на рынок. Т.е. толпа людей, смотрящих в мониторы и ориентирующихся по значениям своих индикаторов, дружно ожидает движение в определенную сторону, совершает сделки.. и двигает эту самую цену. Пусть в мелких масштабах, пусть не всегда (все-таки никуда не деваются владельцы "заводов, газет, пароходов", которые плевать хотели на ТА, им просто в какой-то момент времени нужно купить или продать определенный объем). Но это происходит! Иначе выражаясь - находясь "в теме" (того же ТА), можно попытаться сдвинуть вероятность своих положительных случайных движений в рынке в сторону (чуть?) большую, чем 50%. Это не просто... НО возможно! Пока в этом убежден. Как только разочаруюсь в данном постулате - с рынка уйду... (и дело будет не в размере прибылей/убытков, просто, ну действительно, обидно и бессмысленно работать в пределах полностью случайной системы... в общем, смотри выше)

 

Ну что, теперь к делу.

1. Пока тут было затишье - думал. Да, можно подождать Мирослава (когда он сделает или мост между MT и FSB, или вот, аж компилятор стратегий). Но, в конце концов - результат получает тот, кто хотя бы что-то делает сам :). Я исходил из тех соображений, что у меня вот (уже гарантированно) есть данный инструмент (FSB), есть MT, допустим, кроме этих двух сущностей ничего другого не будет - значит оперируем в их рамках, а именно: FSB (на данный момент) замкнутая система; торговать у нас все-равно в любом случае будет MT; код советника (торгового робота) понадобится при любом раскладе - это да, должен быть какой-то универсальный шаблон, которому (грубо) подсовываются значения индикаторов и все, дальше по "утвержденной схеме"; соотв. понадобятся сами индикаторы.


2. Сразу остановлюсь на коде эксперта. Вот я не разделяю оптимизма создателей простых экспертов - ну невозможно представить количество нештатных ситуация при работе терминала и рынка. А ведь речь идет о деньгах, тут шутки не уместны (не проверили код ошибки - посчитали какое-то действие по умолчанию... и приплыли, -$1000 как не бывало (условно)). Т.е. убежден, что любой эксперт реально оперирующий деньгами (или лучше - оперирующий реальными деньгами) должен быть "железобетонным" в плане реакции на внешние события. Код должен предусмотреть максимальное количество вариаций в работе терминала, сервера или движений на самом рынке. Короче - это достаточно серьезно, и с напрыгом не решается (пишется). С удовольствием готов поучаствовать в создании таких pattern'ов. Но...


3. Я решил пойти все-таки с низов. Мысль из области - если у нас нечем будет оперировать эксперту (самих индикаторов) - зачем тогда вообще эксперт нужен :)?! И взялся за индикаторы...

Предпосылка была следующая. Во первых - действительно, никто не даст гарантий, что значения индикаторов в FSB - эквивалентны значениям штатных или дополнительных индикаторов в MT. А чтобы получать "сопоставимые" результаты в обеих программах - значения должны совпадать. Во вторых - количество самих индикаторов (штатных) ВСЕ-ТАКИ отличается. А использовать (и искать) внешние... я как-то люблю или штатное или свое (по жизни)... (спишем на мои "бзики" :)). В третьих - мне представилось, что "перегонка" кода индикаторов из FSB - все-таки не такая уж прям и мегазадача, как упомянул Мирослав - сами алгоритмы достаточно просты, сами индикаторы у Мирослава - очень "организованы" в плане кода (код унифицирован), т.е. грубо говоря - создаем один раз шаблон и "лепим" в него код индюков один за одним (ну это такое - идеальное мироощущение :))). Есть еще в четвертых - мне было Интересно :).

В общем, на выходных и засел. Прежде чем что-то начинать, я обычно "долго запрягаю" (в данном случае - думаю). Переделывать сам шаблон у меня особо времени не будет (это я понимаю). Особенно когда количество индикаторов перевалит за определенную цифру. Так что ключевые моменты должны быть спроектированы сразу. В итоге я исходил из следующих предпосылок:


- Это должны быть именно индикаторы (а не просто функции для будущего кода эксперта). Все-таки визуальное восприятие информации играет не последнюю роль для человека (и в частности для меня), а вызов (в последствии) индикатора из кода эксперта - не такая уж и проблема (на форуме уже много копий сломали по поводу iCustom - когда столько мнений, я обычно предпочитаю проверить все сам, результат моих "полевых испытаний" - пойдет, наверняка есть небольшой overhead, но именно НЕ БОЛЬШОЙ (это я заявляю со всей ответственностью) и в плане универсальности подхода им можно пренебречь)). Но для "особых ценителей" :) (на всякий) случай сами расчеты в индикаторах вынесены в отдельную однотипную функцию (см. ниже).


- Индикаторов должны на выходе давать те-же значения, что и в оригинальном FSB (отдельно оговариваемый пункт ниже). Т.е. за основу берется код из FSB и, по возможности, дорабатывается минимально.


- Код должен быть соптимизирован для корректной работы с IndicatorCounted (т.е. по скорости)


- Параметры индикаторов, а так-же их значения должны быть однотипны и однородны. Я сейчас не в плане типов данных, как таковых. Если взглянуть на код индикаторов у Мирослава - можно увидеть хорошую однородность (однотипность) как входных параметров, так и буферов на выходе. Задача стоит сохранить исходную картину, чтобы пользователям было удобно ориентироваться при указании параметров или взятии значений индикаторов.

- Следствие из предыдущего пункта - ... ммм (внимание - это важно). Ключевой момент в использовании всех индикаторов - это не то, что они порождают какие-то свои значения. Это то, что они порождают СИГНАЛЫ! Ну действительно, для меня, как для человека - какая разница, каково значение какого-то там индекса сейчас или чуть позже(?!) Это все-равно "непонятные цифры". Понятно - это когда или "Покупать" или "Продавать" :). Все остальное - "не понятно"! Мирослав очень изящно использовал эту идею, создав два буфера в каждом индикаторе (для длинных и коротких позиций), которые в зависимости от использования самого индикатора (как Point of the Position или Logic Condition) приобретают соотв. значения либо открытия/закрытия позиции, либо фильтра Да/Нет (если все "Да" в opening logic - открываем, если хотя бы один "Нет" в closing logic - закрываем (в общем RTFM)). Гениально! ;) Я пошел по протаренному пути и сэмулировал данное поведение. В данный момент первых два буфера индикатора (значения которых можно увидеть в Data Window) - это соотв. искомые буферы с фильрами (1/0) или значениями цены для открытия позиций в длинную или короткую стороны соотв. Т.е. в последствии, при использовании самих индикаторов в коде эксперта ему будет все-равно, что-там, где-там и какие-там значения породи конкретный индикатор - достаточно будет анализировать значения первых двух буферов на очень простой предмет (Да/Нет (условно) или прямое взятие ценника оттуда)... И все! Тут есть нюанс - почти 100% "споткнусь" на Ishimoku (там количество собственных буферов индикатора приближается почти к предельному значению самого MT (8)) - ну будем думать, от красивой идеи (с первыми двумя буферами) отказываться не хочется. Совместить их в один не получится (подумывал... там же не только 1/0 может быть (которые можно было бы в битовую маску превратить), еще и ценники). Скорей всего как-то с самими значениями индикатора буду изголяться... Посмотрим... По ходу...

 

В общем, если коротко (тезисы): качество (совместимость с FSB, безглючность и т.п.), удобство дальнейшего использования, скорость, читаемость кода. В таком порядке.

Ну и (собственно) - что получилось... (краткая история)

- Все индикаторы имеют в префиксе имени файла значение "fsb" (пример: "fsbBlaBlaBla.mq4").


- Сами индикаторы брал в псевдослучайном порядке, так-что не обессудте. Пока что есть, то есть. Для дальнейшего обсуждения/анализа и т.п. - думаю, достаточно.


- Мирослав использует три внешних функции (который вынесены в исходниках (в самом низу страницы)) для подсчета Moving Average и значений логических буферов. Пришлось начать с них. Все функции завернуты в один файл ("fsbCommon.mq4"), оформлены как библиотечные функции ("fsbCommon.mqh"). Существует еще один файл из этой оперы ("fsbConstants.mq4"), в котором, соотв., содержатся константы, для удобства использования в коде. С самими функциями особых проблем не возникло (несколько усложнил начальную логику "осцилляторов логики", на предмет дополнительных проверок (выходы за границы массивов, гарантированность корректных начальных значений (первых по истории) (Мирослав, в коде есть логическая ошибка на эту тему)... и долго пытался "сэмулировать" поведение iShift в MovingAverage так, чтобы функция корректно заполняла значения результирующего буфера при любом вменяемом значении данного параметра (а не только при тех ограничениях, которые даны в исходном оригинале кода)... в итоге пока забросил это дело, поставив в начало "заглушку" (с iShift отличным от "0" функция пока не работает, что, впрочем, пока и не понадобилось)). MovingAverage получился громоздким, но зато убивает сразу нескольких зайцев. Поскольку вернуть буфер из функции в качестве значения в MT не представляется возможным (да может и не надо) - появился дополнительный параметр в конце (afTarget). Так-же, учитывая IndicatorCounted(), еще один параметр отвечает за значение первого бара для обработки. Ну и последний дополнительный параметр задает "ценовую константу" в терминах MT, по значению которой значения самого MovingAverage вычисляются на основе существующих массивов серий, либо (если значение iAppliedPrice вне значений "ценовых констант" MT) - на основе afSource. (отсюда и перегруженность кода) Сразу оговорю нюанс программирования - где идут циклы вперемешку с выборками по case - циклы вставляются внутрь выборок, а не (что обычно более логично) наоборот. Сделано не потому, что я не знаю, как правильно - а потому, что я знаю, как быстро :)! (ну и в дальнейшем, на подобном останавливаться не буду, кто захочет проанализировать код - милости прошу, но прежде чем задавать вопрос "по тупизне кода" немного подумайте, чем (потенциально) могло быть вызвано такое программирование).


С MovingAverage связан еще один нюанс (кому-то может будет познавательно) - т.к. значения Скользящей Средней при режимах сглаживания Exponential (включая Smoothed) напрямую зависят от своих же предыдущих значений - очень важным становится выбор "начальной точки отсчета" (какое значение брать за основу для дальнейшихвычислений). Тут обычно существуют несколько подходов. Кто-то берет цену закрытия предыдущего периода. Кто-то среднюю цену за предыдущий период N... Мирослав пошел по второму пути. MT явно идет по первому. Отсюда показательные расхождения на этих двух режимах сглаживания в начале графика (я добавил одну "болванку" для тестирования MovingAverage и всего остального ("fsbTest.mq4"))! И ограничения, наложенные мной внутри функции по наличию данных самой MovingAverage ДО iFirstBar, либо аналогичного объема вычисляемых значений ПОСЛЕ iFirstBar. Т.к. в самих индикаторах используется константа на минимальное значение баров на графике (сейчас 2000) - этого должно хватить для любых ситуаций (т.к. я пока не встречал параметров с периодами больше 200). Если, конечно, не будет использовано более одного MA за раз ;).


- По аналогии с предыдущим пунктом созданы файлы для внешних подфункций, которые уже я использую в своей работе с данным проектом (префикс "st": "stCommon.mq4", "stCommon.mqh", "stConstants.mq4")


- Ну и собственно - сами индикаторы. Если очень коротко (для примера возьмем "Bar Range"):

//extern int     slotType = SLOT_TYPE_LC;
extern int     indLogic = INDICATOR_RISES;   // (INDICATOR_RISES <= indLogic <= INDICATOR_LOWER_LL)
extern int     nBars    = 1;                 // 1 <= nBars <= 200
extern int     fLevel   = 0;                 // 0 <= fLevel <= 500
extern bool    iPrvs    = True;              // True / False

slotType задает типа слота в терминах FSB (Point of the Position или Logic Condition). Те индикаторы, которые могут являться не только фильтрами на вход/выход, но еще и задавать цену открытия/закрытия - этот параметр как раз и определяет, что будет генерировать индикатор в своих буферах логики. Все константы смотрите в fsbConstants.mq4 (там все достаточно понятно)

indLogic - собственно, логическое условие для индикатора (несет разную смысловую нагрузку, в зависимости от значения slotType)

Ну и дальше параметры идут, в порядке, как они фигурируют в исходниках индикаторов на forexsb.com, и как они отображаются в самом FSB. Границы параметров указаны в комментариях и контролируются при вызове init() вызовом подфункции PCheck().

double   LPIndBuffer[];          // Long positions                #1
double   SPIndBuffer[];          // Short positions               #2

double   IndBuffer[];            // Indicator's values            #3

double   IndBufferDD[];          // Additional buffer for drawing #4
double   IndBufferDU[];          // Additional buffer for drawing #5

С буферами так - все, что на глобальном уровне - используется как индикаторные буферы (прикрепляются к самому индикатору). Как раз искомые логические (LPIndBuffer[], SPIndBuffer[]) (всегда и всегда в этом порядке (#0 - длинные позиции, #1 - короткие позиции)), IndBuffer[] - данные самого индикатора. Но в данном случае поскольку используется цветная гистограмма, этот буфер несет только сами значения, а для цветной отрисовки используются два дополнительных буфера (если честно - программить MT начал вот, как раз перенося индикаторы :), и как можно сэмулировать поведение цветных гистограмм в рамках MT по другому - так и не придумал (кто подскажет? если такое вообще возможно)). Они в DataWindow не отображаются никак.

В init() все как обычно (проверяются значения параметров, задаются имена самого индикатора и индексов, прикрепляются буферы и т.п.)


В deinit() подумываю вставить логику на случаи НЕ закрытия индикатора (доп.удобство, чтобы параметры, там, не сбрасывал и т.п.), на досуге (пока не приоритет).


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


Calculate() - собственно расчеты. Код, в общем случае - похож на код Мирослава, исключения делаются на тему оптимизаций, связанных с IndicatorCounted(). Если для расчета индикатора требуются дополнительные индикаторные буферы - они задаются внутри самой функции (static) (чтобы не тратить попусту индексы самого индикатора), и обслуживаются функцией BufferSync(). Тут отдельный прикол - изначально была попытка ограничить вычисления еще по одному константному параметру (iMaxBars). Специально были произведены "полевые испытания" (часть 2) поведения массивов серий при наличии истории, отсутствии, движению в будущее (приход котировок, увеличение массивов ВПРАВО (я сейчас визуально, про графическое представление)), ... движению в прошлое (когда истории не хватает (мы двигаемся по графику влево) и терминал ее подгружает с сервера... и массивы расширяются ВЛЕВО)... Так вот... Обломался. Я то сделал красиво (попытался сделать) - в зависимости от направления расширения BufferSync() и расширяет массив соотв. влево или вправо, заполняя пустые значения EMPTY_VALUE. Вот только сам MT нормально индексные массивы ВЛЕВО не расширяет. Он их ВСЕГДА расширяет вправо (со стороны [0] Бара). Надеюсь понятно, к чему я веду - что при очередном прыжке по истории назад, когда значение баров на графике превысит iMaxBars (прыжком, опять же) - вполне возможны ситуации, когда индикатор не будет рисовать свои значения левее iMaxBars, а вот "странные данные" от него, левее iMaxBars оказаться могут легко. Может их никто и смотреть не будет... Но "не красиво" (не наш метод). А всего-то нужно, чтобы сам MT дополнял буферы пустыми значениями в нужную сторону... Отловить подобную ситуацию потенциально можно, но... В общем, рисуем с самого начала графика... _всегда_. (Ну, насколько это вообще возможно для данного конкретного индикатора)


Очередной нюанс связан с IndicatorCounted() - казалось бы - божественная функция. Возвращай значения посчитанных баров и никаких к тебе претензий не будет... БУДУТ! Думаю, здесь не сам IndicatorCounted() виноват (как и программеры из MQ), а куча программеров кастомных индикаторов, до которых так и не дошло божественное назначение данной функции. Поэтому она принудительно возвращает всегда малое количество потенциальных значений. Либо пересчитываем весь график (IndicatorCounted() == 0), либо первые один ((IndicatorCounted() == Bars - 1) или два (IndicatorCounted() == Bars - 2) бара. ВСЕ! Никаких других значений я от не дождался. Это я к тому, что, например, если оборвалась связь, и график "убежал" более, чем на один бар вперед - все... "деревья умирали стоя" (IndicatorCounted() == 0) - считаем весь график по новой. Зачем? Нельзя было возвращать количество пропущеных баров (3, 4, ... 5... 10...)? (для чего эта функция и предназначалась, как я понимаю, изначально) В общем - вот так...

... "Споткнулся" я на RSI. Во всех смыслах причем. Во первых - я не понял код Мирослава (вопросы к нему пойдут ниже). Во вторых - тестируя индикатор я увидел расхождения в получаемых значениях внутри MT и FSB! Нет, дело вовсе не в том, о чем вы подумали ("криво перенес" - ну признайтесь, подумали же ;)). Дело, к сожалению, по видимому вот в этих декларациях:

float[] afPos       = new float[Bars];
...
float   sum;
...

Короче - float! Немного подумав - пока притормозил, т.к. самый первый тезис (точность и качество) - стал под вопросом (а он первоочередной).


Тут возможны следующие рассуждения: С одной стороны float не плохо, это как-бы "огрубление" значений индикатора, что должно сделать торговую стратегию еще менее восприимчивой к случайным всплескам на рынке. С другой - допустим, при пересечении какого-то там fLevel (1.0, к примеру) - согласитесь: 0.99998 и 1.00001 - это две большие разницы :). А расхождения такие бывают. И если поза откроется в такой-вот момент, а на самом деле уровень по FSB все-таки не дойдет до 1.0 и пойдет вниз - то кого потом винить? (того, кто перенес индикаторы :D?!)


Вариантов решения собственно два (учитывая, что float MT не поддерживается!):


- эмулировать float в самом MT (какими-нибудь душераздирающими конструкциями вроде NormalizeDouble(X, Digits + 2) ) - ну не везде, но считайте, что каждое умножение/деление по любому


- сменить float в FSB на double. Тут нужно понимать и объем изменений, явно конечный, но нужно аккуратно пройтись везде. И что потенциальный результат сгенерированных стратегий у людей может "поплыть". Да и вообще, нужно ли это Мирославу? (мое скромное мнение, что это нужно самому FSB, т.к. лишняя точность еще никому не вредила, а на скорости вычислений (если эта цель преследовалась(?), т.к. больше причин я не вижу) в данном временном разрезе реальности - это не должно каким либо существенным образом сказаться). Соглашусь в данном вопросе с ребятами из MQ - т.к. если уж мы не оперируем с целочисленной математикой (какие-нибудь Decimal), то хотя бы попробуем с максимально-возможной точностью. В общем, тут такой... не простой вопрос...

 

Короче - спать уже пора :). Извините за многословность (больше не буду, только по существу).


Хотелось бы услышать мнение - нужно ли данную тему продолжать (и тогда "понеслись" дальше, остальные индикаторы перелопачивать)? Могу даже в каком-то порядке (т.к. все-равно изначальный беспорядок :)), кому, может, что нужно вперед. Временем, к сожалению, в общем случае обделен (зам.ген.директора в своей конторе - "день пролетает незаметно" :D). Т.е. нахожу время обычно под вечер. Но один-два индикатора в день, думаю, смогу обеспечить...



Ну и вопросы к Мирославу - по теме...

1. Чему равно значение fMicron? (я поставил (поразмыслив) 0.000001, похоже, или разрядность еще меньше?)


2. Что за параметр bIsDescreteValues (в осцилляторе логики). Смысл его я уловил - но каково его значение по умолчанию? И от каких условий зависит изменение? (или, скажем так - с чем он связан (в интерфейсе FSB или где еще))


3. Собственно про RSI, вот это что за конструкция?:

for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
   afPosMA
[iBar] = (afPosMA[iBar - 1] * (iPeriod - 1) + afPos[iBar]) / iPeriod;
   afNegMA
[iBar] = (afNegMA[iBar - 1] * (iPeriod - 1) + afNeg[iBar]) / iPeriod;
}

:)? Мотивация вопроса в следующем: Если мне не изменяет зрение - это smoothed MA. В контексте всего кода - он применяется к уже подсчитанным MA и порождает smoothed MA, где "в живых" остается только первое значение :). Как бы логичный вопрос - что здесь лишнее? Эта конструкция, которая помимо прочего делает НЕ РАБОТОСПОСОБНЫМ(!) выбор режимов сглаживания RSI в самом индикаторе (он всегда получается smoothed), так и в зависимых от него. Или предыдущие вычисления MA (с корректным режимом из параметров) для afPos, afNeg?


Понятно, что классический RSI строится на базе smoothed average. Но существует как минимум разновидность с Simple MA и было бы логичным убрать все-таки приведенный код, сделав рабочим поведение параметра maMethod. Либо убрав вычисления MA перед этим циклом, и удалив параметры MA RSI во всех индикаторах (т.к. все-равно они ни на что не влияют!).


Я бы убрал вот этот код (который выше) :). (В сконвертированном индикаторе данный участок закомментарен, кому нужна оригинальная функциональность - уберите теги комментариев! Код RSI дан для ознакомления... пока мы тут не определимся, я бы его использовал "на свой страх и риск" :))


4. Как уже сказал есть не критичная логическая ошибка в осцилляторах логики при поведении на начальных барах. Сейчас уже мысли в кучу не сложу, завтра отпишу (где и как подправить).


5. Что будем делать с float в FSB? (или с отсутствием оного в MT) :)?


Архив содержит искомые файлы, разнесенные по папкам, распаковать в корень MT (архив пойдет в следующем сообщении)


Все, всем удачи... пишите :)
 

Текущий архив индикаторов (2009-04-15)

Файлы:
experts.rar  101 kb
 

Согласен float не бьется - нужно искать выход. Надо прописать соответствие. Потом создать библиотеку индикаторов. Если смогу помочь - буду рад.

Причина обращения: