Реклама

вторник, 9 ноября 2010 г.

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

Продолжим писать класс статистического анализа индикатора (repeat, until).

 

Сегодня мы продолжим писать класс для анализа индикатора momentum, который начали на прошлом уроке  Мы уже создали базовые классы. Теперь создадим основные, рабочие классы. Начнем с TPASSStatAnalizMomentum:
TPASSStatAnalizMomentum=class(TPASSStatAnalizTemplate)
     function FindSignal:boolean; override;
     function FindSignalRotate:boolean; override;
     procedure Test;
end;
Как видим, в этом классе мы реализуем абстрактные методы FindSignal и FindSignalRotate родительского класса:
function TPASSStatAnalizMomentum.FindSignal:boolean;
var LastCandleIndex:integer; s:string;
begin
     Result:=false;
     LastCandleIndex:=1;
     repeat
         if FIndicator.GetResultByFieldName('Value')=0 then LastCandleIndex:=2 else LastCandleIndex:=1;
         if (FIndicator.GetResultByFieldName('Value')>=0) and
            (FIndicator.GetResultByFieldNameAndIndex('Value',FIndicator.PriceSource.CurrentItemIndex-LastCandleIndex)<0) then
         begin
             FSignalType:=enBuy;
             Result:=true;
             exit;
         end;
         if (FIndicator.GetResultByFieldName('Value')<0) and
             (FIndicator.GetResultByFieldNameAndIndex('Value',FIndicator.PriceSource.CurrentItemIndex-LastCandleIndex)>=0) then
        begin
            FSignalType:=enSell;
            Result:=true;
            exit;
        end;
    until not FIndicator.Next;
end;

function TPASSStatAnalizMomentum.FindSignalRotate:boolean;
var LastSignalType:TPASSSignalsTypes; toNext:boolean;
begin
    LastSignalType:=FSignalType;
    toNext:=true;
    if not(FIndicator.PriceSource.NextItem) then
    begin
       Result:=false;
       exit;
    end;
    repeat
        if not FindSignal then
        begin
           Result:=false;
           exit;
        end;
        if (LastSignalType=enBuy) and (FSignalType=enSell) then
        begin
          Result:=true;
          exit;
        end;
        if (LastSignalType=enSell) and (FSignalType=enBuy) then
        begin
           Result:=true;
           exit;
        end;
   until toNext;
   Result:=false;
end;
Сигнал ищется следующим образом:
Шаг 1. Проверяем условия сигнала на покупку
          if (FIndicator.GetResultByFieldName('Value')>=0) and
            (FIndicator.GetResultByFieldNameAndIndex('Value',FIndicator.PriceSource.CurrentItemIndex-LastCandleIndex)<0) then
Если это условие выполняется, то считаем, что это сигнал на покупку и завершаем подпрограмму:
             FSignalType:=enBuy;
             Result:=true;
             exit;
Шаг 2. Проверяем условия сигнала на продажу
         if (FIndicator.GetResultByFieldName('Value')<0) and
             (FIndicator.GetResultByFieldNameAndIndex('Value',FIndicator.PriceSource.CurrentItemIndex-LastCandleIndex)>=0) then
Если это условие выполняется, то считеам, что это сигнал на продажу и выходим из подпрограммы:
            FSignalType:=enSell;
            Result:=true;
            exit;
Шаг 3. Если у нас не последняя котировка, то переносим указатель на следующую котировку и повторяем цикл, начина с шага 1 (выполняем еще раз то, что находится между операторами repeat ... until
Как мы ищем обратный сигнал? Сперва запоминаем тип последнего сигнала и проверяем, не последняя ли у нас котировка:
    LastSignalType:=FSignalType;
    toNext:=true;
    if not(FIndicator.PriceSource.NextItem) then
Затем в цикле ищем сигнал, не найдя которого решаем, что у нас нет обратного сигнала:
    repeat
        if not FindSignal then
        begin
           Result:=false;
           exit;
        end;
обратным считаем только тот сигнал, который обратный последнему (для покупки - это продажа, для продажи - это покупка):
        if (LastSignalType=enBuy) and (FSignalType=enSell) then
        begin
          Result:=true;
          exit;
        end;
        if (LastSignalType=enSell) and (FSignalType=enBuy) then
        begin
           Result:=true;
           exit;
        end;
Ну, и наконец, цикл мы повторяем до тех пор, пока не просмотрели все котировки до конца (либо пока не нашли сигнал):
   until toNext;
в принципе, метод FindSignalRotate следовало бы объявить в классе TPASSStatAnalizTemplate, потому что он будет одинаков, скорее всего, для всех типов механических торговых систем. Но сейчас мы не будем ничего переписывать, оптимизацией программы займемся, когда будем делать рефакторинг кода. А пока будем продолжать писать классы, сейчас нам надо создать что то, что позволит протестировать статистический анализатор котировок.
TPASSStatStoreDataList=class(TPASSStatStoreDataTemplate)
protected
   FList:TStrings;
   FCounter:integer;
public
   constructor Create(AList:TStrings);
   procedure AddData(AParameters:TPASSParameters); override;
end;
Как видим, данный класс очень простой. Он предназначен лишь для того, что бы показать пользователю результаты первичного статистического анализа. Реализовов его, мы сможем проверить, правильно ли у нас работает класс TPASSStatAnalizMomentum:
constructor TPASSStatStoreDataList.Create(AList:TStrings);
begin
   inherited Create;
   FList:=AList;
   FCounter:=0;
end;

procedure TPASSStatStoreDataList.AddData(AParameters:TPASSParameters);
var s:string; i,cn:integer;
begin
   s:='';
   cn:=AParameters.Count-1;
   for i:=0 to cn do s:=s+AParameters[i].Name+'='+AParameters.AsStringByNum(i)+';';
   FList.Add(s);
   FCounter:=FCounter+1;
end;
Метод AddData класса TPASSStatStoreDataList простотупо и решительно все параметры засовывает в строку и добавляет в список строк. Этого нам достаточно, что бы отобразить результаты расчетов на экране. На следующем уроке мы этим и займемся. А сейчас мы реализуем последний метод, который еще не реализовали:
procedure TPASSStatAnalizMomentum.Test;
begin
    FIndicator.PriceSource.CurrentItemIndex:=FIndicator.GetParameterByName('DT')+3;
    inherited Test;
end;

Иисточник: http://easyprog.ru/index.php?option=com_content&task=view&id=155&Itemid=44