Lenta kotirovok

Some blogs or websites linked from this site may contain objectionable or uncensored content, www.mainru.com is not affiliated with these websites and makes no representations or warranties as to their content.

понедельник, 8 ноября 2010 г.

Пишем робота Урок №8

Пишем класс статистического анализа индикатора (TGauge, virtual, abstract, momentum).

В этом уроке вам понадобиться материал (программные коды) предыдущих уроков:
Сегодня мы реализуем класс для статистического анализа индикатора, согласно постановки задачи, поставленной на прошлом уроке. Для начала объявим шаблон класса:
TPASSStatAnalizTemplate=class(TObject)
protected
     FIndicator:TPASSIndicator;
     FProfitChange:double;
     FDrawdownChange:double;
     FLastSignalPrice:double; // Цена открытия свечи сведущей за прошлым сигналом
     FAnalizCandleCount:LongInt; //Количество анализируемых свечей
     FSignalType:TPASSSignalsTypes;
     FParameters:TPASSParameters;
     FStoreData:TPASSStatStoreDataTemplate;
     procedure SaveTestResult;
public
     Gauge:TGauge;
     constructor Create(AIndicator:TPASSIndicator; AAnalizCandleCount:LongInt; AStoreData:TPASSStatStoreDataTemplate);
     function FindSignal:boolean; virtual; abstract;
     function FindSignalRotate:boolean; virtual; abstract;//поиск сигнала, обратного найденному
     procedure GetChange;
     procedure Test;
     Destructor Destroy;
end;
 
Этот шаблон нужен для того, что бы потом, когда мы будем тестировать другие индикаторы, быстро создать под них нужные классы. А теперь пробежимся по полями и методам. Начнем с защищенных полей:
  • FIndicator - в этом поле у нас храниться ссылка на индикатор. Так как типом является базовый класса TPASSIndicator, то в дальнейшем мы можем хранить в этом поле ссылку на любой индикатор (а не только momentum), примем, как созданный ранее, так и созданный в дальнейшем.
  • FProfitChange - в этом поле мы будем хранить максимальный профит за заданное количество свечей, рассчитанный для текущего сигнала.
  • FDrawdownChange - в этом поле мы будем хранить максимальный убыток за заданное количество свечей, рассчитанный для текущего сигнала.
  • FLastSignalPrice - сигнальная цена текущего сигнала. В качестве сигнальной берем цену открытия интервала, следующего за сигнальным. Иными словами, если у нас интервал равен одному дню, то получив сигнал сегодня вечером мы сделку совершаем завтра утром.
  • FAnalizCandleCount - здесь мы храним то количество свечей, за которое будем анализировать максимальный профит (дродаун).
  • FSignalType - тип сигнала: покупка или продажа. Данный тип у нас объявлен в новой версии модуля PASSBaseObj. Скачать новую версию можно здесь.
  • FParameters - в этом поле храниться список параметров. Каждый параметр это пара имя - значение. Результат работы класса мы помещаем в параметры. Это нужно для того, что бы наша библиотека была более универсальной. Поясню сказанное: при тестировании индикатора у нас результаты вычислений будут передаваться другому объекту для обработки.  Иметь список пар "имя - значение" гораздо универсальнее, чем просто структура с заданными полями.
  • FStoreData - ссылка на класс, который будет обрабатывать результаты вычислений.
Теперь рассмотрим процедуру SaveTestResult. Она то как раз и будет передавать результаты вычисления другому классу. Вот как реализован данный метод:
procedure TPASSStatAnalizTemplate.SaveTestResult;
begin
      FStoreData.AddData(FParameters);
end;
Теперь перейдем к разделу Public:
  • Gauge - ссылка на прогресс бар (TGauge). Если у нас тестирование будет идти долго, то мы сможем видеть прогресс выполнения:
класс статистического анализа индикатора (TGauge, virtual, abstract, momentum)
Сам компонент TGauge находиться на закладке Samples*:
класс статистического анализа индикатора (TGauge, virtual, abstract, momentum)
Следует так же иметь в виду, что коль мы используем в качестве полей объектов класс TGauge, то в разделе uses модуля, где у нас объявлен данный класс, следует добавить Gauges:
uses PASSIndicators, PASSBaseObj, SysUtils, classes, Gauges;
А теперь перейдем к остальным методам класса TPASSStatAnalizTemplate:
  • Create - метод конструктор, создающий объект. Ему мы передаем анализируемый индикатор; количество свечей после сигнала, за которые анализируем индикатор и объект, обрабатывающий результаты вычисления. вот как он реализован:
constructor TPASSStatAnalizTemplate.Create(AIndicator:TPASSIndicator; AAnalizCandleCount:LongInt; AStoreData:TPASSStatStoreDataTemplate);
begin
inherited Create;
    FIndicator:=AIndicator;
    FAnalizCandleCount:=AAnalizCandleCount;
    FStoreData:=AStoreData;
    FParameters:=TPASSParameters.Create;
    FParameters.Add('ProfitChange',0, ptFloat);
    FParameters.Add('DrawdownChange',0, ptFloat);
    FParameters.Add('SignalResult',enBuy, ptSignal);
    FParameters.Add('SignalDate',0, ptData);
    FParameters.Add('ProfitChangeSign',enBuy, ptFloat);
end;
В конструкторе мы инициируем начальные значения полей, которые являются входными параметрами алгоритма. Заполнения начальных значений происходит из переданных параметров. Затем мы создаем объект класса TPASSParameters, где у нас будут храниться результаты вычислений и добавляем туда нужные параметры.
  • FindSignal - данный метод позиционирует указатель на следующий сигнал. Так как мы можем анализировать разные типы сигналов, при чем на одном и том же индикаторе, то данный метод мы пока объявили абстрактным. Его мы реализуем в дочерних классах.
  • FindSignalRotate - указатель позиционируется на сигнал, противоположный только что найденному. Это нужно, так как у нас в постановке задачи есть требование, что нужно подчитать статистку по прибыли (убытку), если мы вошли в позицию по сигналу и вышли по противоположному сигналу.  Данный метод так же реализуем в дочерних класса, здесь он абстрактный.
  • GetChange - этой процедурой мы производим расчет максимальной прибыли и дродауна за указанное количество интервалов FAnalizCandleCount:
procedure TPASSStatAnalizTemplate.GetChange;
var  CurrentItemIndex, I:LongInt; BarData:TBarStructure;
       FMaxPrice, FMinPrice:double;
begin
      CurrentItemIndex:=FIndicator.PriceSource.CurrentItemIndex;
      FLastSignalPrice:=FIndicator.PriceSource.GetDataByFieldNameAndIndex('Open',CurrentItemIndex+1);
      if FLastSignalPrice=0 then raise exception.Create('TPASSStatAnalizTemplate.TPASSStatAnalizTemplate - нулевое значение последней цены. Свеча '+
             DateTimeToStr(FIndicator.PriceSource.GetBarData.DateTime));
      FMinPrice:=FLastSignalPrice;
      FMaxPrice:=FLastSignalPrice;
      for I:=1 to FAnalizCandleCount do
      begin
          if not(FIndicator.Next) then break;
          BarData:=FIndicator.PriceSource.GetBarData;
          if BarData.Hight>FMaxPrice then FMaxPrice:=BarData.Hight;
          if BarData.Lowthen FMinPrice:=BarData.Low;
      end;
      if FSignalType=enBuy then
      begin
          FProfitChange:=(FMaxPrice-FLastSignalPrice)/FLastSignalPrice;
          FDrawdownChange:=(FLastSignalPrice-FMinPrice)/FLastSignalPrice;
      end else
      begin
         FProfitChange:=(FLastSignalPrice-FMinPrice)/FLastSignalPrice;
         FDrawdownChange:=(FMaxPrice-FLastSignalPrice)/FLastSignalPrice;
      end;
      FIndicator.PriceSource.CurrentItemIndex:=CurrentItemIndex;
end;
Эта процедура будет у нас вызываться из алгоритма тестирования в тот момент, когда найден очередной сигнал. Сперва идет поиск минимальной и максимальной котировки в цикле с заданным количество повторений:
      for I:=1 to FAnalizCandleCount do
      begin
          if not(FIndicator.Next) then break;
          BarData:=FIndicator.PriceSource.GetBarData;
          if BarData.Hight>FMaxPrice then FMaxPrice:=BarData.Hight;
          if BarData.Lowthen FMinPrice:=BarData.Low;
      end;
Затем, в зависимости от того, какой был сигнал, на покупку или на продажу, вычисляем максимальную прибыль и дродаун. Если у нас был сигнал на покупку, то максимальная прибыль это разница между максимальной и сигнальной ценой, а дродаун - разница между сигнальной и минимальной. При сигнале на продажу наоборот.
  • Test - а это, у нас, собственно говоря, процедура, производящая расчеты для тестирования  сигналов индикатора:
procedure TPASSStatAnalizTemplate.Test;
var CurrentItemIndex:integer; LastSignalPrice:double; SignalType: TPASSSignalsTypes;
       SignalPrice:double;
begin
    while FindSignal do
    begin
       if FAnalizCandleCount+FIndicator.PriceSource.CurrentItemIndex>FIndicator.PriceSource.CountLoadedBars then exit;
      GetChange; //узнаем изменения на заданный диапазон времени
      Gauge.Progress:=FIndicator.PriceSource.CurrentItemIndex;
      FParameters.SetParameterByName('ProfitChange',FProfitChange);
      FParameters.SetParameterByName('DrawdownChange',FDrawdownChange);
      FParameters.SetParameterByName('SignalResult',FSignalType);
      FParameters.SetParameterByName('SignalDate',FIndicator.PriceSource.GetBarData.DateTime);
      SignalType:=FSignalType;
      CurrentItemIndex:=FIndicator.PriceSource.CurrentItemIndex;
      LastSignalPrice:=FLastSignalPrice;
      if not(FindSignalRotate) then exit;
      if FLastSignalPrice=0 then raise Exception.Create('TPASSStatAnalizTemplate.Test - нулевая цена сигнала');
      FIndicator.PriceSource.NextItem;
      SignalPrice:=FIndicator.PriceSource.GetBarData.Open;
      if SignalType=enBuy then
           FParameters.SetParameterByName('ProfitChangeSign',(SignalPrice-FLastSignalPrice)/FLastSignalPrice)
      else
           FParameters.SetParameterByName('ProfitChangeSign',(FLastSignalPrice-SignalPrice)/FLastSignalPrice);
      FIndicator.PriceSource.CurrentItemIndex:=CurrentItemIndex+1;
      SaveTestResult();
   end;
end;
в данной процедуре мы в цикле перебираем все сигналы и вычисляем результаты тестирования, а потом передаем их объекту FStoreData для обработки.
  • Нам осталось рассмотреть деструктор:
Destructor TPASSStatAnalizTemplate.Destroy;
begin
    FParameters.Free;
    inherited Destroy;
end;
В данном деструкторе мы очищаем объект FParameters - мы его создали, мы его и удалим. А вот что касается FStoreData - то это объект переданный извне, в данном деструкторе его уничтожать не нужно.
Перейдем к следующему классу TPASSStatStoreDataTemplate (его нужно разместить впереди объявления класса TPASSStatAnalizTemplate)- это у нас тоже класс-шаблон:
TPASSStatStoreDataTemplate=class(TObject)
public
     procedure AddData(AParameters:TPASSParameters); virtual; abstract;
end;
Как видим, у него всего лишь один метод, да и тот абстрактный.
Мы закончили писать шаблоны классов статистического анализа индикатора. На следующем уроке мы, на их основе, разработаем уже сами классы

Скриншоты, помеченные знаком * , являются цитатами и иллюстрациями  в соответствии со ст. 1274 ГК РФ программного продукта "Delphi", авторское право на который принадлежит "Borland Software Corporation".

Источник: http://easyprog.ru/index.php?option=com_content&task=view&id=151&Itemid=44  Очень рекомендую !!!!!

Поделится

Котировки

Идея