Пишем класс статистического анализа индикатора (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; |
- Gauge - ссылка на прогресс бар (TGauge). Если у нас тестирование будет идти долго, то мы сможем видеть прогресс выполнения:
Сам компонент TGauge находиться на закладке Samples*:
Следует так же иметь в виду, что коль мы используем в качестве полей объектов класс TGauge, то в разделе uses модуля, где у нас объявлен данный класс, следует добавить Gauges:
uses PASSIndicators, PASSBaseObj, SysUtils, classes, Gauges; |
- 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.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.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; |
- Нам осталось рассмотреть деструктор:
Destructor TPASSStatAnalizTemplate.Destroy; begin FParameters.Free; inherited Destroy; end; |
Перейдем к следующему классу 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 Очень рекомендую !!!!!