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.

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

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

Биржевой симулятор: класс TESBInstrument - симуляция покупки (продажи) акций. 

Исходники к уроку можно скачать здесь.
И так, продолжим писать биржевой симулятор. Сегодня мы реализуем новый класс: TESBInstrument, при помощи которого будем имитировать покупку и продажу акций. Пока, конечно, это будет тоже нечто вроде заготовки, как и в случае с TESBAccount, но в дальнейшем мы соединим эти классы и расширим функционал.
И так, объявление нового класса:
//класс симуляции остатка по биржевому инструменту
TESBInstrument=class(TESBBaseClass)
protected
     FPriceSource:TPASSPriceSource;
     FCount:integer;
     FName:string;
     FCurrentCandle:LongInt;
     FCanShort:boolean;
     procedure SetPriceSource(APriceSource:TPASSPriceSource);
public
     property PriceSource:TPASSPriceSource read FPriceSource write SetPriceSource;
     property Count:integer read FCount; // количество акций
     property Name:string read FName write FName;
     property CanShort:boolean read FCanShort write FCanShort; //можно ли шортит
     constructor Create;
     function CurrentPrice:double; //текущая цена по курсу открытия
     procedure Buy(ACount:integer); //купить
     procedure Sell(ACount:integer); //продать
     procedure Serialize(AStream:TStream); override;
     procedure Unserialize(AStream:TStream); override;
     function Next:boolean;
end;
Так как у нас используется класс TPASSPriceSource, то нам понадобится библиотека PASSBaseObj, ее можно скачать вот здесь Естественно, ее надо будет подключить к проекту, как вы уже научились на предыдущем уроке. Так же в модуле Base нужно добавить эту библиотеку в раздел uses*:

А теперь приступим к реализации класса:
// ************** TESBInstrument *****************
constructor TESBInstrument.Create;
begin
    inherited Create;
    FCanShort:=true;
    FCount:=0;
    FCurrentCandle:=0;
    FPriceSource:=nil;
end;

function TESBInstrument.CurrentPrice:double;
begin
    if FPriceSource<>nil then
    begin
       if FPriceSource.CurrentItemIndex<>FCurrentCandle then FPriceSource.CurrentItemIndex:=FCurrentCandle;
       Result:=FPriceSource.GetBarData.Open;
   end else raise Exception.Create('TESBInstrument.CurrentPrice -нет источника котировок');
end;

procedure TESBInstrument.Buy(ACount:integer);
begin
    FCount:=FCount+ACount;
end;

procedure TESBInstrument.Sell(ACount:integer);
begin
     if (ACount>FCount) and not(FCanShort) then raise Exception.Create('TESBInstrument.Sell - превышен лимит по инструменту');
     FCount:=FCount-ACount;
end;

procedure TESBInstrument.Serialize(AStream:TStream);
begin
    inherited Serialize(AStream);
    AStream.Write(FCanShort,sizeof(FCanShort));
    AStream.Write(FCount,sizeof(FCount));
    AStream.Write(FCurrentCandle,sizeof(FCurrentCandle));
    SerializeString(FName,AStream);
end;

procedure TESBInstrument.Unserialize(AStream:TStream);
begin
     inherited Unserialize(AStream);
    AStream.Read(FCanShort,sizeof(FCanShort));
    AStream.Read(FCount,sizeof(FCount));
    AStream.Read(FCurrentCandle,sizeof(FCurrentCandle));
    FName:=UnserializeString(AStream);
end;

procedure TESBInstrument.SetPriceSource(APriceSource:TPASSPriceSource);
begin
    FPriceSource:=APriceSource;
    FCurrentCandle:=APriceSource.CurrentItemIndex;
end;

function TESBInstrument.Next:boolean;
begin
     Result:=FPriceSource.NextItem;
     FCurrentCandle:=FCurrentCandle+1;
end;
И немного комментариев к коду. В прошлый раз, когда мы проектировали класс TESBAccount, свойство Cash (наличные), мы сделали только для чтения, предполагая, что его можно менять только методами. Аналогично сделаем и свойство Count, метод Buy увеличивает его, а Sell -уменьшает. Если по данной акции допустимы шорты CanShort то мы можем уменьшить Count в минус, иначе у нас при попытке продать больше чем есть будет вызвано исключение. Ну, и конечно же, для того, что бы знать цену акции, нам понадобиться источник котировок TPASSPriceSource. Данный класс  (TPASSPriceSource) позволяет загрузить котировки из текстового файла в формате, скаченного с Финама, а так же получить котировки на заданную свечу.
Теперь немного изменяем форму тестового примера, созданного на прошлом уроке*:
Вносим некоторые изменения в объявление класса TfrmStockBot*:
а затем переписываем обработчики событий:
procedure TfrmStockBot.FormCreate(Sender: TObject);
begin
   Instrument:=TESBInstrument.Create;
   Instrument.CanShort:=false;
   PriceSource:=nil;
end;

procedure TfrmStockBot.FormDestroy(Sender: TObject);
begin
    FreeAndNil(Instrument);
    if PriceSource<>nil then FreeAndNil(PriceSource);
end;

procedure TfrmStockBot.ShowCount;
begin
   mmAccount.Lines.Add(FloatToStr(Instrument.Count));
end;

procedure TfrmStockBot.btnBuyClick(Sender: TObject);
begin
   Instrument.Buy(StrToInt(edCount.Text));
   ShowCount;
end;

procedure TfrmStockBot.btnSellClick(Sender: TObject);
begin
   Instrument.Sell(StrToInt(edCount.Text));
   ShowCount;
end;

procedure TfrmStockBot.itSaveClick(Sender: TObject);
var Stream:TFileStream;
begin
   if SaveDialog.Execute then
   begin
     Stream:=TFileStream.Create(SaveDialog.FileName,fmCreate);
     Instrument.Serialize(Stream);
     FreeAndNil(Stream);
   end;
end;


procedure TfrmStockBot.itOpenClick(Sender: TObject);
var Stream:TFileStream;
begin
   if OpenDialog.Execute then
   begin
       Stream:=TFileStream.Create(OpenDialog.FileName,fmOpenRead);
       FreeAndNil(Instrument);
       Instrument:=TESBInstrument.Create;
       Instrument.PriceSource:=PriceSource;
       Instrument.Unserialize(Stream);
       FreeAndNil(Stream);
       mmAccount.Lines.Clear;
       ShowCount;
       lbPrice.Caption:=FloatToStr(Instrument.CurrentPrice);
   end;
end;

procedure TfrmStockBot.itOpenPricesClick(Sender: TObject);
begin
     if OpenDialogPrices.Execute then
     begin
         if PriceSource<>nil then FreeAndNil(PriceSource);
         PriceSource:=TPASSPriceSource.Create('',false);
         PriceSource.LoadDataFromTextFile(OpenDialogPrices.FileName);
         PriceSource.First;
         Instrument.PriceSource:=PriceSource;
         lbPrice.Caption:=FloatToStr(Instrument.CurrentPrice);
     end;
end;


procedure TfrmStockBot.btnNextClick(Sender: TObject);
begin
    Instrument.Next;
    lbPrice.Caption:=FloatToStr(Instrument.CurrentPrice);
end;
Также готовый тестовый пример можно скачать здесь
Затем запускаем программу, закачиваем котировки и приступаем к тестированию:

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

Поделится

Котировки

Идея