Программирование - это просто
Advertisement
Главная arrow C#, Delphi, VB, F#, Web и пр. arrow Прочее программирование arrow Создаем биржевого робота уроки, статьи, идеи arrow Реализуем класс для расчета индикатора momentum (используем библиотеки и AfterConstruction
23.05.2019 г.
Главное меню
Главная
Системный подход
Интернет магазин
Биржевые роботы
Программные продукты
Математика и информатика
1С:Предприятие
C#, Delphi, VB, F#, Web и пр.
Искусственный интеллект
Услуги
Ча. Во. (FAQ)
Платный раздел
Наука для чайников
Разное
Размышления
Карта сайта
Друзья сайта
Excel-это не сложно
Все о финансах
Реализуем класс для расчета индикатора momentum (используем библиотеки и AfterConstruction Печать E-mail
Автор megabax   
30.07.2009 г.
New Page 1

Реализуем класс для расчета индикатора momentum (используем библиотеки и AfterConstruction, наследуемый от TObject)

Все статьи по данной теме.

Сегодня мы займемся реализацией биржевого робота. Точнее будем выполнять задачу, поставленную на уроке "Постановка задачи". Для начала нужно скачать с сайта www.easyprog.ru нужные библиотеки (PASSBaseObj и PASSIndicators). Теперь создадим в Delphi новый проект, скопируем туда закаченные библиотеки и добавим их в проект*:

Delphi 7: биржевой робот библиотеки индикаторы class momentum AfterConstruction

 

В раздел uses добавим подключенные к проекту модули PASSIndicators, PASSBaseObj:

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, PASSIndicators, PASSBaseObj;
 

Для для реализации расчета по заданной в уроке "Математическая модель" формуле нам понадобиться создать новый класс индикатора - TPASSMomentum.  Объявим его:

TPASSMomentum=class(TPASSIndicator)
private
           FDT:integer; // длительность периода в интервалах
           FPriceFieldType:string; //тип ценового поля (Open, High, Low, Close);
           procedure UpdateParameters; virtual;
           procedure AfterConstruction; override;
protected
           FParameters:TPASSParameters; // значения параметров индикатора.
           FPriceSource:TPASSPriceSource; // источник котировок.
public
          constructor Create(ADT:integer; APriceFieldType:string);
          function GetResultByFieldName(AFieldName:string):double; override;
          function GetResultByFieldNameAndIndex(AFieldName:string; Index:LongInt):double; override;
          function GetResultByFieldNum(AFieldNum:integer):double; override;
          function GetResultByFieldNumAndIndex(AFieldNum:integer; Index:LongInt):double; override;
          procedure First; override;
          procedure Last; override;
          function Next:boolean; override;
          function Prev:boolean; override;
          function GetIndicatorName:string; override;
end;
 

Данный класс мы объявили как дочерний от класса TPASSIndicator - это базовый класс индикатора. В модуле PASSIndicators есть еще класса TPASSAverageIndicator, объявленный как дочерний от PASSIndicators,  он служит родительским классом для TPASSMASimple и TPASSADX, которые реализует индикаторы Moving Average. ADX соответственно. Но индикатор momentum, не является индикатором скользящего среднего и для своего расчета не требует буфера расчета среднего значений котировок, поэтому мы используем в качестве родительского класса TPASSIndicator.

Класс TPASSIndicator имеет абстрактный метод UpdateParameters, поэтому мы обязаны переопределить его в нашем классе. Это мы делаем в секции private, так как данная процедура вызывается только из методов класса индикатора и предназначена для переписывания значений параметров из списка параметров в приватные поля класса. Почему именно так? Дело в том, что при создании библиотек PASSBaseObj и PASSIndicators предполагалось, что они будут использованы для серьезного приложения, похожего на Metatrader или Metastock. А приватные поля используются только главным образом для быстродействия, так как если обращаться через имя параметра, то нужно будет искать его в списке, что замедлит работу программы. Это замедление почувствуется, когда нужно будет делать много расчетов во вложенных циклах.

В процедуре AfterConstruction, которая наследуется от TObject, являющийся предком всех классов в библиотеках, будет просто вызвана процедура  UpdateParameters, поскольку в TPASSIndicator это не сделано. Конечно, правильнее было бы переопределить AfterConstruction непосредственно в TPASSIndicator, но рефреймингом кода мы займемся потом, а сейчас наша задача поскорее создать индикатор и исследовать его.

Так мы же определяем конструктор класса, что бы создать объект класса на основании параметров. И переопределяем все абстрактные методы класса  TPASSIndicator . Кроме того, мы поля FParameters и  FPriceSource из секции private переносим в секцию protected, просто объявив их как protected в дочернем классе.  Это нужно для того, что бы эти поля стали доступные в дочернем классе но были по прежнему недоступные извне.

А теперь займемся реализацией. Начнем с UpdateParameters

procedure TPASSMomentum.UpdateParameters;
var i,cn:integer;
begin
  cn:=FParameters.Count-1;
  for i:=0 to cn do
    begin
      if UpperCase(FParameters[i].Name)='DT' then FDT:=FParameters[i].Value else
      begin
          if UpperCase(FParameters[i].Name)='PRICEFIELDTYPE' then FPriceFieldType:=FParameters[i].Value else
                raise Exception.Create('No correct parameter name '+FParameters[i].Name);
      end;
    end;
end;   

Здесь мы просто тупым перебором перебираем параметры и устанавливаем соответствующие приватные поля. В списке есть параметр, которое не соответствует ни одному приватному полю, то это нонсенс. Такого быть не должно. Сразу вызываем исключение.

Далее реализуем метод AfterConstruction и сам конструктор:

procedure TPASSMomentum.AfterConstruction;
begin
    UpdateParameters;
end;

constructor TPASSMomentum.Create(ADT:integer; APriceFieldType:string);
begin
  inherited Create;
  FParameters.Add('DT',ADT);
  FParameters.Add('PriceFieldType',APriceFieldType);
end;

Методы GetResultByFieldName и GetResultByFieldNameAndIndex предназначены для получение значения индикатора по имени функции (у индикаторов может быть несколько функций, например у ADX есть функции DI+, DI- и само ADX). У нашего же индикатора только одна функция - Value. Реализуем получение значения по имени этой функции:

function TPASSMomentum.GetResultByFieldName(AFieldName:string):double;
begin
   if UpperCase(AFieldName)<>'VALUE' then Raise Exception.Create('TPASSMomentum.GetResultByFieldName: Неверное имя поля  - '+AFieldName);
   Result:=GetResultByFieldNum(0);
end;

function TPASSMomentum.GetResultByFieldNameAndIndex(AFieldName:string; Index:LongInt):double;
begin
   if UpperCase(AFieldName)<>'VALUE' then Raise Exception.Create('TPASSMomentum.GetResultByFieldNameAndIndex: Неверное имя поля  - '+AFieldName);
   Result:=GetResultByFieldNumAndIndex(0,index);
end;

А теперь, наконец то добрались и до формулы:

function TPASSMomentum.GetResultByFieldNum(AFieldNum:integer):double;
var Pend,Pbeg:double;
begin
   if FDT=0 then Raise  Exception.Create('TPASSMomentum.GetResultByFieldNum: нулевое значение параметра DT');
   if FPriceSource.CurrentItemIndex<=FDT then raise Exception.Create('TPASSMomentum.GetResultByFieldNum: ошибка выхода за диапазон');
   if AFieldNum<>0 then Raise Exception.Create('TPASSMomentum.GetResultByFieldNum: Неверный номер поля - '+IntToStr(AFieldNum));
   Pend:=FPriceSource.GetDataByFieldName(FPriceFieldType);
   Pbeg:=FPriceSource.GetDataByFieldNameAndIndex('PriceFieldType',FPriceSource.CurrentItemIndex-FDT);
   if Pbeg=0 then raise Exception.Create('TPASSMomentum.GetResultByFieldNum: Обнаружена нулевая котировка по полю '+
        FPriceFieldType+' номер свечи '+IntToStr(FPriceSource.CurrentItemIndex-FDT)+' дата и время свечи '+
        DateTimeToStr(FPriceSource.GetDataByFieldNameAndIndex('DateTime',FPriceSource.CurrentItemIndex-FDT)));
   Result:=(Pend-Pbeg)/Pbeg*100/FDT;
end;

function TPASSMomentum.GetResultByFieldNumAndIndex(AFieldNum:integer; Index:LongInt):double;
var Pend,Pbeg:double;
begin
   if AFieldNum<>0 then Raise Exception.Create('TPASSMomentum.GetResultByFieldNumAndIndex: Неверный номер поля - '+IntToStr(AFieldNum));
   if FDT=0 then raise Exception.Create('TPASSMomentum.GetResultByFieldNumAndIndex: нулевое значение параметра DT');
   if index<=FDT then Raise  Exception.Create('TPASSMomentum.GetResultByFieldNumAndIndex: ошибка выхода за диапазон');
   Pend:=FPriceSource.GetDataByFieldNameAndIndex(FPriceFieldType,Index);
   Pbeg:=FPriceSource.GetDataByFieldNameAndIndex(FPriceFieldType,Index-FDT);
   if Pbeg=0 then raise Exception.Create('TPASSMomentum.GetResultByFieldNumAndIndex: Обнаружена нулевая котировка по полю '+
        FPriceFieldType+' номер свечи '+IntToStr(index-FDT)+' дата и время свечи '+
        DateTimeToStr(FPriceSource.GetDataByFieldNameAndIndex('DateTime',index-FDT)));
   Result:=(Pend-Pbeg)/Pbeg*100/FDT;
end;   

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

Теперь реализуем оставшиеся методы:

procedure TPASSMomentum.Last;
begin
   FPriceSource.Last;
end;

procedure TPASSMomentum.First;
begin
   FPriceSource.CurrentItemIndex:=FDT+1;
end;

function TPASSMomentum.Next:boolean;
begin
   Result:=FPriceSource.NextItem;
end;

function TPASSMomentum.Prev:boolean;
begin
   Result:=FPriceSource.PrevItem;
end;

function TPASSMomentum.GetIndicatorName:string;
begin
  Result:='Momentum';
end;

Подведем итоги. На этом уроке мы разработали класс для расчета индикатора momentum. На следующем уроке будем его тестировать.

 


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

 

Последнее обновление ( 20.07.2013 г. )
 
« След.   Пред. »
 
© 2019 Программирование - это просто
Joomla! - свободное программное обеспечение, распространяемое по лицензии GNU/GPL.
Русская локализация © 2005-2008 Joom.Ru - Русский Дом Joomla!
Design by Mamboteam.com | Powered by Mambobanner.de
Я принимаю Яндекс.Деньги
Мы принимаем
Банковские карты
Оплатите покупку в интернет-магазине банковскими картами VISA и Mastercard любого банка.
узнать больше
Электронный кошелек
Моментальная оплата покупок с помощью вашего электронного кошелька RBK Money.
узнать больше
Банковский платеж
Оплатите покупку в любом российском банке. Срок зачисления средств на счет - 3-5 рабочих дней.
узнать больше
Денежные переводы
Оплата покупок через крупнейшие системы денежных переводов CONTACT и Unistream.
узнать больше
Почтовые переводы
Оплатите покупку в любом отделении Почты России. Срок зачисления платежа - 3-4 рабочих дня.
узнать больше
Платежные терминалы
Оплата покупок в терминалах крупнейших платежных систем в любом городе России - быстро и без комиссии.
узнать больше