Processor-Result

This commit is contained in:
Michael Schimmel
2025-07-11 12:00:36 +02:00
parent 487169afe0
commit 021ff61774
5 changed files with 52 additions and 32 deletions
+18 -16
View File
@@ -41,13 +41,12 @@ type
property Observers: IMycBroadcast<T> read GetObservers; property Observers: IMycBroadcast<T> read GetObservers;
end; end;
TMycConverter<S, T> = class abstract(TInterfacedObject, IMycProcessor<S>, IMycConverter<S, T>) TMycConverter<S, T> = class abstract(TMycProcessor<S>, IMycConverter<S, T>)
private private
FObservers: TMycBroadcast<T>; FObservers: TMycBroadcast<T>;
protected protected
procedure Broadcast(const Value: T); procedure Broadcast(const Value: T);
function GetObservers: IMycBroadcast<T>; function GetObservers: IMycBroadcast<T>;
procedure ProcessData(const Value: S); virtual; abstract;
public public
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
@@ -59,7 +58,7 @@ type
private private
FFunc: TConvertFunc; FFunc: TConvertFunc;
protected protected
procedure ProcessData(const Value: S); override; function ProcessData(const Value: S): Boolean; override;
public public
constructor Create(const AFunc: TConvertFunc); constructor Create(const AFunc: TConvertFunc);
end; end;
@@ -79,7 +78,7 @@ type
TMycIndicator<S, T> = class abstract(TMycConverter<TArray<S>, TArray<T>>, IMycIndicator<S, T>) TMycIndicator<S, T> = class abstract(TMycConverter<TArray<S>, TArray<T>>, IMycIndicator<S, T>)
protected protected
function GetLookback: Integer; virtual; abstract; function GetLookback: Integer; virtual; abstract;
procedure ProcessData(const Value: TArray<S>); override; abstract; function ProcessData(const Value: TArray<S>): Boolean; override; abstract;
public public
property Lookback: Integer read GetLookback; property Lookback: Integer read GetLookback;
end; end;
@@ -92,7 +91,7 @@ type
FFunc: TConvertFunc; FFunc: TConvertFunc;
protected protected
function GetLookback: Integer; override; function GetLookback: Integer; override;
procedure ProcessData(const Value: TArray<S>); override; function ProcessData(const Value: TArray<S>): Boolean; override;
public public
constructor Create(ALookback: Integer; const AFunc: TConvertFunc); constructor Create(ALookback: Integer; const AFunc: TConvertFunc);
end; end;
@@ -120,7 +119,7 @@ type
constructor Create(const ATimeframe: TTimeframe; const AStateText: TWriteable<String>); constructor Create(const ATimeframe: TTimeframe; const AStateText: TWriteable<String>);
// Process new data. This is called concurrently and must not have side effects out of the scope of this class! // Process new data. This is called concurrently and must not have side effects out of the scope of this class!
procedure ProcessData(const Values: TArray<TDataPoint<TAskBidItem>>); override; function ProcessData(const Values: TArray<TDataPoint<TAskBidItem>>): Boolean; override;
property CurrentBar: TDataPoint<TOhlcItem> read GetCurrentBar; property CurrentBar: TDataPoint<TOhlcItem> read GetCurrentBar;
property StateText: TWriteable<String> read GetStateText; property StateText: TWriteable<String> read GetStateText;
@@ -140,7 +139,7 @@ type
// Calculates the Weighted Moving Average for the most recent data. // Calculates the Weighted Moving Average for the most recent data.
function CalculateWMA(const Series: TMycDataArray<Double>; const Period: Integer): Double; function CalculateWMA(const Series: TMycDataArray<Double>; const Period: Integer): Double;
protected protected
procedure ProcessData(const Values: TArray<Double>); override; function ProcessData(const Values: TArray<Double>): Boolean; override;
function GetLookback: Integer; override; function GetLookback: Integer; override;
public public
constructor Create(const APeriod: Integer); constructor Create(const APeriod: Integer);
@@ -175,8 +174,7 @@ begin
FLinkedStrategies.Notify( FLinkedStrategies.Notify(
function(const Processor: IMycProcessor<T>): Boolean function(const Processor: IMycProcessor<T>): Boolean
begin begin
Processor.ProcessData(cValue); Result := Processor.ProcessData(cValue);
Result := true;
end end
); );
finally finally
@@ -242,7 +240,7 @@ begin
Result := FTimeframe; Result := FTimeframe;
end; end;
procedure TTicksToTimeframe.ProcessData(const Values: TArray<TDataPoint<TAskBidItem>>); function TTicksToTimeframe.ProcessData(const Values: TArray<TDataPoint<TAskBidItem>>): Boolean;
var var
point: TDataPoint<TAskBidItem>; point: TDataPoint<TAskBidItem>;
midPrice: Single; midPrice: Single;
@@ -251,6 +249,7 @@ var
currentBar: TOhlcItem; currentBar: TOhlcItem;
producedBars: TList<TDataPoint<TOhlcItem>>; producedBars: TList<TDataPoint<TOhlcItem>>;
begin begin
Result := true;
producedBars := TList<TDataPoint<TOhlcItem>>.Create; producedBars := TList<TDataPoint<TOhlcItem>>.Create;
try try
// Process each incoming data point // Process each incoming data point
@@ -343,7 +342,7 @@ begin
Result := FPeriod + FPeriodSqrt - 1; Result := FPeriod + FPeriodSqrt - 1;
end; end;
procedure THullMovingAverage.ProcessData(const Values: TArray<Double>); function THullMovingAverage.ProcessData(const Values: TArray<Double>): Boolean;
var var
i: Integer; i: Integer;
price: Double; price: Double;
@@ -351,6 +350,8 @@ var
hma: Double; hma: Double;
resultArray: TArray<Double>; resultArray: TArray<Double>;
begin begin
Result := true;
// Pre-allocate the result array since its size is known in advance. // Pre-allocate the result array since its size is known in advance.
SetLength(resultArray, Length(Values)); SetLength(resultArray, Length(Values));
@@ -358,8 +359,8 @@ begin
begin begin
price := Values[i]; price := Values[i];
// Default HMA to 0.0 for the warm-up period. // Default HMA to NaN for the warm-up period.
hma := 0.0; hma := Double.NaN;
// Add new price to the source data array, respecting the lookback period. // Add new price to the source data array, respecting the lookback period.
FSourceData := FSourceData.Add(price, FPeriod); FSourceData := FSourceData.Add(price, FPeriod);
@@ -402,8 +403,9 @@ begin
FFunc := AFunc; FFunc := AFunc;
end; end;
procedure TMycGenericConverter<S, T>.ProcessData(const Value: S); function TMycGenericConverter<S, T>.ProcessData(const Value: S): Boolean;
begin begin
Result := true;
Broadcast(FFunc(Value)); Broadcast(FFunc(Value));
end; end;
@@ -419,11 +421,11 @@ begin
Result := FLookback; Result := FLookback;
end; end;
procedure TMycGenericIndicator<S, T>.ProcessData(const Value: TArray<S>); function TMycGenericIndicator<S, T>.ProcessData(const Value: TArray<S>): Boolean;
var var
Arr: TArray<T>; Arr: TArray<T>;
begin begin
inherited; Result := true;
SetLength(Arr, Length(Value)); SetLength(Arr, Length(Value));
for var i := 0 to High(Arr) do for var i := 0 to High(Arr) do
Arr[i] := FFunc(Value[i]); Arr[i] := FFunc(Value[i]);
+2 -1
View File
@@ -450,8 +450,9 @@ begin
Symbol, Symbol,
terminated, terminated,
TMycGenericProcessor<TArray<TDataPoint<TAuraAskBidFileItem>>>.Create( TMycGenericProcessor<TArray<TDataPoint<TAuraAskBidFileItem>>>.Create(
procedure(const Values: TArray<TDataPoint<TAuraAskBidFileItem>>) function(const Values: TArray<TDataPoint<TAuraAskBidFileItem>>): Boolean
begin begin
Result := true;
Prices := Prices.Add(Values); Prices := Prices.Add(Values);
currLog.Value := Prices.TotalCount.ToString; currLog.Value := Prices.TotalCount.ToString;
+14 -4
View File
@@ -78,7 +78,7 @@ type
FDataSeries: TMycDataArray<T>; FDataSeries: TMycDataArray<T>;
FChanged: Boolean; FChanged: Boolean;
FLock: TSpinLock; FLock: TSpinLock;
procedure ProcessData(const Values: TArray<T>); function ProcessData(const Values: TArray<T>): Boolean;
private private
FData: TMycDataArray<T>; FData: TMycDataArray<T>;
protected protected
@@ -271,8 +271,9 @@ begin
Result := FData.Count; Result := FData.Count;
end; end;
procedure TChartSeriesProcessor<T>.ProcessData(const Values: TArray<T>); function TChartSeriesProcessor<T>.ProcessData(const Values: TArray<T>): Boolean;
begin begin
Result := true;
FLock.Enter; FLock.Enter;
try try
FDataSeries := FDataSeries.Add(Values, 0, Length(Values), Owner.Lookback); FDataSeries := FDataSeries.Add(Values, 0, Length(Values), Owner.Lookback);
@@ -407,8 +408,17 @@ begin
if displayCount < 2 then if displayCount < 2 then
Exit; Exit;
points.MoveTo( TPointF.Create(AXForm(0), AYForm(Data[0])) ); // Skip warmup data
for var i := 1 to displayCount - 1 do var n := 0;
while IsNaN(Data[n]) do
begin
inc( n );
if n >= displaycount-2 then
exit;
end;
points.MoveTo( TPointF.Create(AXForm(n), AYForm(Data[n])) );
for var i := n to displayCount - 1 do
points.LineTo( TPointF.Create(AXForm(i), AYForm(Data[i])) ); points.LineTo( TPointF.Create(AXForm(i), AYForm(Data[i])) );
ACanvas.Stroke.Color := FLineColor; ACanvas.Stroke.Color := FLineColor;
+15 -10
View File
@@ -30,25 +30,30 @@ type
end; end;
IMycProcessor<T> = interface IMycProcessor<T> = interface
procedure ProcessData(const Value: T); function ProcessData(const Value: T): Boolean;
end; end;
TMycGenericProcessor<T> = class(TInterfacedObject, IMycProcessor<T>) TMycProcessor<T> = class abstract(TInterfacedObject, IMycProcessor<T>)
protected
function ProcessData(const Value: T): Boolean; virtual; abstract;
end;
TMycGenericProcessor<T> = class(TMycProcessor<T>)
type type
TProc = reference to procedure(const Value: T); TProc = reference to function(const Value: T): Boolean;
private private
FProc: TProc; FProc: TProc;
procedure ProcessData(const Value: T); function ProcessData(const Value: T): Boolean; override;
public public
constructor Create(const AProc: TProc); constructor Create(const AProc: TProc);
end; end;
TMycContainedProcessor<T> = class(TContainedObject, IMycProcessor<T>) TMycContainedProcessor<T> = class(TContainedObject, IMycProcessor<T>)
type type
TProc = procedure(const Value: T) of object; TProc = function(const Value: T): Boolean of object;
private private
FProc: TProc; FProc: TProc;
procedure ProcessData(const Value: T); function ProcessData(const Value: T): Boolean;
public public
constructor Create(const Controller: IInterface; const AProc: TProc); constructor Create(const Controller: IInterface; const AProc: TProc);
end; end;
@@ -420,9 +425,9 @@ begin
FProc := AProc; FProc := AProc;
end; end;
procedure TMycGenericProcessor<T>.ProcessData(const Value: T); function TMycGenericProcessor<T>.ProcessData(const Value: T): Boolean;
begin begin
FProc(Value); Result := FProc(Value);
end; end;
constructor TMycContainedProcessor<T>.Create(const Controller: IInterface; const AProc: TProc); constructor TMycContainedProcessor<T>.Create(const Controller: IInterface; const AProc: TProc);
@@ -431,9 +436,9 @@ begin
FProc := AProc; FProc := AProc;
end; end;
procedure TMycContainedProcessor<T>.ProcessData(const Value: T); function TMycContainedProcessor<T>.ProcessData(const Value: T): Boolean;
begin begin
FProc(Value); Result := FProc(Value);
end; end;
end. end.
+3 -1
View File
@@ -436,7 +436,9 @@ begin
DataFile.Chain( DataFile.Chain(
function(const Data: TArray<TDataPoint<T>>): TState function(const Data: TArray<TDataPoint<T>>): TState
begin begin
Processor.ProcessData(Data); if not Processor.ProcessData(Data) then
exit( TState.Null );
Result := ProcessFile(nextFileInfo, nextFile, cTerminated, Processor); Result := ProcessFile(nextFileInfo, nextFile, cTerminated, Processor);
end end
); );