Pipe testing
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
unit Demo.Finance;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
System.SysUtils,
|
||||
System.Math,
|
||||
System.DateUtils,
|
||||
// Framework
|
||||
Myc.Data.Value,
|
||||
Myc.Data.Scalar,
|
||||
Myc.Data.Keyword,
|
||||
Myc.Data.Stream, // IStream
|
||||
Myc.Data.Stream.Pipes, // TRootStream
|
||||
Myc.Ast.Types,
|
||||
Myc.Ast.Scope,
|
||||
Myc.Ast;
|
||||
|
||||
type
|
||||
IFinanceSimulator = interface
|
||||
procedure CreateOHLCSeries(const Scope: IExecutionScope; const VarName: string);
|
||||
procedure AddRandomCandle(const Scope: IExecutionScope; const VarName: string);
|
||||
end;
|
||||
|
||||
TFinanceSimulator = class(TInterfacedObject, IFinanceSimulator)
|
||||
private
|
||||
FLastClose: Double;
|
||||
FLastTime: TDateTime;
|
||||
|
||||
kTime, kOpen, kHigh, kLow, kClose, kVol: IKeyword;
|
||||
|
||||
procedure InitKeywords;
|
||||
public
|
||||
constructor Create;
|
||||
procedure CreateOHLCSeries(const Scope: IExecutionScope; const VarName: string);
|
||||
procedure AddRandomCandle(const Scope: IExecutionScope; const VarName: string);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TFinanceSimulator }
|
||||
|
||||
constructor TFinanceSimulator.Create;
|
||||
begin
|
||||
inherited;
|
||||
FLastClose := 150.00;
|
||||
FLastTime := Now;
|
||||
end;
|
||||
|
||||
procedure TFinanceSimulator.InitKeywords;
|
||||
begin
|
||||
if kTime = nil then
|
||||
begin
|
||||
kTime := TKeywordRegistry.Intern('Time');
|
||||
kOpen := TKeywordRegistry.Intern('Open');
|
||||
kHigh := TKeywordRegistry.Intern('High');
|
||||
kLow := TKeywordRegistry.Intern('Low');
|
||||
kClose := TKeywordRegistry.Intern('Close');
|
||||
kVol := TKeywordRegistry.Intern('Vol');
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TFinanceSimulator.CreateOHLCSeries(const Scope: IExecutionScope; const VarName: string);
|
||||
var
|
||||
Fields: TArray<TScalarRecordField>;
|
||||
Def: IScalarRecordDefinition;
|
||||
Stream: TRootStream;
|
||||
StaticType: IStaticType;
|
||||
begin
|
||||
InitKeywords;
|
||||
|
||||
SetLength(Fields, 6);
|
||||
Fields[0] := TScalarRecordField.Create(kTime, TScalar.TKind.DateTime);
|
||||
Fields[1] := TScalarRecordField.Create(kOpen, TScalar.TKind.Float);
|
||||
Fields[2] := TScalarRecordField.Create(kHigh, TScalar.TKind.Float);
|
||||
Fields[3] := TScalarRecordField.Create(kLow, TScalar.TKind.Float);
|
||||
Fields[4] := TScalarRecordField.Create(kClose, TScalar.TKind.Float);
|
||||
Fields[5] := TScalarRecordField.Create(kVol, TScalar.TKind.Ordinal);
|
||||
|
||||
Def := TKeywordMappingRegistry<TScalar.TKind>.Intern(Fields);
|
||||
|
||||
// Wir erzeugen einen aktiven RootStream
|
||||
Stream := TRootStream.Create(Def);
|
||||
|
||||
// Für den Compiler ist es eine RecordSeries (Typ), zur Laufzeit ein Stream (Wert)
|
||||
StaticType := TTypes.CreateRecordSeries(Def);
|
||||
|
||||
Scope.Define(VarName, TDataValue.FromStream(Stream), StaticType);
|
||||
end;
|
||||
|
||||
procedure TFinanceSimulator.AddRandomCandle(const Scope: IExecutionScope; const VarName: string);
|
||||
var
|
||||
Addr: TResolvedAddress;
|
||||
Val: TDataValue;
|
||||
Stream: TRootStream;
|
||||
Def: IScalarRecordDefinition;
|
||||
RowData: TArray<TScalar.TValue>;
|
||||
i: Integer;
|
||||
Key: IKeyword;
|
||||
|
||||
O, H, L, C: Double;
|
||||
V: Int64;
|
||||
begin
|
||||
InitKeywords;
|
||||
|
||||
Addr := Scope.Resolve(VarName);
|
||||
if Addr.Kind = akUnresolved then
|
||||
raise Exception.CreateFmt('Variable "%s" not found.', [VarName]);
|
||||
|
||||
Val := Scope[Addr];
|
||||
|
||||
// Wir benötigen zwingend einen Stream für sim-tick, um Events zu feuern
|
||||
if Val.Kind <> vkStream then
|
||||
raise Exception.CreateFmt('Variable "%s" is not a Stream.', [VarName]);
|
||||
|
||||
// Sicherer Cast auf TRootStream
|
||||
if not (Val.AsStream is TRootStream) then
|
||||
raise Exception.CreateFmt('Variable "%s" is a Stream, but not a TRootStream (cannot push manually).', [VarName]);
|
||||
|
||||
Stream := TRootStream(Val.AsStream);
|
||||
Def := Stream.Series.Def;
|
||||
|
||||
// --- Simulation ---
|
||||
FLastTime := IncMinute(FLastTime, 5);
|
||||
O := FLastClose;
|
||||
C := O + (Random - 0.5) * 2.0;
|
||||
H := Max(O, C) + Random * 0.5;
|
||||
L := Min(O, C) - Random * 0.5;
|
||||
V := Random(1000) + 100;
|
||||
FLastClose := C;
|
||||
// ------------------
|
||||
|
||||
SetLength(RowData, Def.Count);
|
||||
for i := 0 to Def.Count - 1 do
|
||||
begin
|
||||
Key := Def.Items[i].Key;
|
||||
if Key = kTime then
|
||||
RowData[i] := FLastTime
|
||||
else if Key = kOpen then
|
||||
RowData[i] := O
|
||||
else if Key = kHigh then
|
||||
RowData[i] := H
|
||||
else if Key = kLow then
|
||||
RowData[i] := L
|
||||
else if Key = kClose then
|
||||
RowData[i] := C
|
||||
else if Key = kVol then
|
||||
RowData[i] := V;
|
||||
end;
|
||||
|
||||
// Push triggert das Notify-Event für alle angeschlossenen Pipes
|
||||
Stream.Push(RowData);
|
||||
end;
|
||||
|
||||
procedure RegisterFinanceLibrary(const Scope: IExecutionScope);
|
||||
var
|
||||
Sim: IFinanceSimulator;
|
||||
Sig: IStaticType;
|
||||
begin
|
||||
Sim := TFinanceSimulator.Create;
|
||||
Sig := TTypes.CreateMethod([TTypes.Text], TTypes.Void);
|
||||
|
||||
Scope.Define(
|
||||
'sim-create',
|
||||
function(const Args: TArray<TDataValue>): TDataValue
|
||||
begin
|
||||
if Length(Args) <> 1 then
|
||||
raise Exception.Create('sim-create(Name) expects 1 argument');
|
||||
Sim.CreateOHLCSeries(Scope, Args[0].AsText);
|
||||
Result := TDataValue.Void;
|
||||
end,
|
||||
Sig
|
||||
);
|
||||
|
||||
Scope.Define(
|
||||
'sim-tick',
|
||||
function(const Args: TArray<TDataValue>): TDataValue
|
||||
begin
|
||||
if Length(Args) <> 1 then
|
||||
raise Exception.Create('sim-tick(Name) expects 1 argument');
|
||||
Sim.AddRandomCandle(Scope, Args[0].AsText);
|
||||
Result := TDataValue.Void;
|
||||
end,
|
||||
Sig
|
||||
);
|
||||
|
||||
// Some Demo-Stream
|
||||
Sim.CreateOHLCSeries(Scope, 'btc');
|
||||
end;
|
||||
|
||||
initialization
|
||||
TAst.RegisterLibrary(RegisterFinanceLibrary);
|
||||
|
||||
end.
|
||||
Reference in New Issue
Block a user