TSeries + DataEndpoint
This commit is contained in:
@@ -17,22 +17,22 @@ uses
|
||||
type
|
||||
TChartSeriesReceiver<T> = class(TMycProcessor<T>)
|
||||
strict private
|
||||
FCurrData: TMycDataArray<T>;
|
||||
FCurrData: TSeries<T>;
|
||||
FLookback: TMutable<Int64>;
|
||||
private
|
||||
FData: TWriteable<TMycDataArray<T>>;
|
||||
FData: TWriteable<TSeries<T>>;
|
||||
protected
|
||||
function ProcessData(const Value: T): TState; override;
|
||||
public
|
||||
constructor Create(const ALookback: TMutable<Int64>);
|
||||
property Data: TWriteable<TMycDataArray<T>> read FData;
|
||||
property Data: TWriteable<TSeries<T>> read FData;
|
||||
end;
|
||||
|
||||
TChartSeriesProcessor<T> = class(TMycChart.TSeries)
|
||||
strict private
|
||||
FDataSeries: TMycDataArray<T>;
|
||||
FDataSeries: TSeries<T>;
|
||||
private
|
||||
FData: TMycDataArray<T>;
|
||||
FData: TSeries<T>;
|
||||
FDataProvider: TDataProvider<T>;
|
||||
FReceiver: TChartSeriesReceiver<T>;
|
||||
FReceiverTag: TDataProvider<T>.TTag;
|
||||
@@ -44,7 +44,7 @@ type
|
||||
public
|
||||
constructor Create(const ADataProvider: TDataProvider<T>; const ALookback: TMutable<Int64>);
|
||||
destructor Destroy; override;
|
||||
property Data: TMycDataArray<T> read FData;
|
||||
property Data: TSeries<T> read FData;
|
||||
end;
|
||||
|
||||
{ TChartCustomLayer }
|
||||
@@ -146,8 +146,7 @@ constructor TChartSeriesReceiver<T>.Create(const ALookback: TMutable<Int64>);
|
||||
begin
|
||||
inherited Create;
|
||||
FLookback := ALookback;
|
||||
FCurrData := TMycDataArray<T>.CreateEmpty;
|
||||
FData := TWriteable<TMycDataArray<T>>.CreateWriteable(FCurrData).Protect;
|
||||
FData := TWriteable<TSeries<T>>.CreateWriteable(FCurrData).Protect;
|
||||
end;
|
||||
|
||||
function TChartSeriesReceiver<T>.ProcessData(const Value: T): TState;
|
||||
@@ -163,7 +162,6 @@ constructor TChartSeriesProcessor<T>.Create(const ADataProvider: TDataProvider<T
|
||||
begin
|
||||
inherited Create;
|
||||
FDataProvider := ADataProvider;
|
||||
FDataSeries := TMycDataArray<T>.CreateEmpty;
|
||||
FData := FDataSeries;
|
||||
|
||||
FReceiver := TChartSeriesReceiver<T>.Create(ALookback);
|
||||
|
||||
+21
-20
@@ -6,7 +6,7 @@ type
|
||||
// A series is an array of values with the newest ite at index=0. Each series counts the total of added items since creation, but
|
||||
// it actually may contain less items, because the array size is limited by the lookback parameter, when adding items.
|
||||
// Series are immutable.
|
||||
TMycDataArray<T> = record
|
||||
TSeries<T> = record
|
||||
private
|
||||
const
|
||||
ChunkSize = 1024;
|
||||
@@ -21,13 +21,14 @@ type
|
||||
function GetItems(Idx: Int64): T; inline;
|
||||
public
|
||||
constructor Create(const AChunks: TArray<TChunk>; ACount, ATotalCount: Int64);
|
||||
|
||||
class operator Initialize(out Dest: TSeries<T>);
|
||||
// Add a singe item
|
||||
function Add(const Data: T; Lookback: Int64): TMycDataArray<T>; overload;
|
||||
function Add(const Data: T; Lookback: Int64): TSeries<T>; overload;
|
||||
// Add a ranmge of items
|
||||
function Add(const Data: array of T; First, Count, Lookback: Int64): TMycDataArray<T>; overload;
|
||||
class function CreateEmpty: TMycDataArray<T>; static;
|
||||
function Add(const Data: array of T; First, Count, Lookback: Int64): TSeries<T>; overload;
|
||||
// Helper to create a data array from a raw TArray.
|
||||
class function CreateFromArray(const AData: TArray<T>; First, Count: Integer): TMycDataArray<T>; static;
|
||||
class function CreateFromArray(const AData: TArray<T>; First, Count: Integer): TSeries<T>; static;
|
||||
property Count: Int64 read FCount;
|
||||
property TotalCount: Int64 read FTotalCount;
|
||||
property Items[Idx: Int64]: T read GetItems; default;
|
||||
@@ -35,28 +36,22 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
{ TMycDataArray<T> }
|
||||
{ TSeries<T> }
|
||||
|
||||
constructor TMycDataArray<T>.Create(const AChunks: TArray<TChunk>; ACount, ATotalCount: Int64);
|
||||
constructor TSeries<T>.Create(const AChunks: TArray<TChunk>; ACount, ATotalCount: Int64);
|
||||
begin
|
||||
FChunks := AChunks;
|
||||
FCount := ACount;
|
||||
FTotalCount := ATotalCount;
|
||||
end;
|
||||
|
||||
class function TMycDataArray<T>.CreateEmpty: TMycDataArray<T>;
|
||||
begin
|
||||
Result.FChunks := nil;
|
||||
Result.FCount := 0;
|
||||
end;
|
||||
|
||||
class function TMycDataArray<T>.CreateFromArray(const AData: TArray<T>; First, Count: Integer): TMycDataArray<T>;
|
||||
class function TSeries<T>.CreateFromArray(const AData: TArray<T>; First, Count: Integer): TSeries<T>;
|
||||
begin
|
||||
// Use the Add method on an empty array to perform the chunking logic.
|
||||
Result := CreateEmpty.Add(AData, First, Count, Count);
|
||||
Result.Add(AData, First, Count, Count);
|
||||
end;
|
||||
|
||||
function TMycDataArray<T>.Add(const Data: array of T; First, Count, Lookback: Int64): TMycDataArray<T>;
|
||||
function TSeries<T>.Add(const Data: array of T; First, Count, Lookback: Int64): TSeries<T>;
|
||||
var
|
||||
destPhysicalIdx, sourcePhysicalIdx: Int64;
|
||||
itemsToSkip: Int64;
|
||||
@@ -103,15 +98,15 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
Result := TMycDataArray<T>.Create(newChunks, newCount, FTotalCount + Count);
|
||||
Result := TSeries<T>.Create(newChunks, newCount, FTotalCount + Count);
|
||||
end;
|
||||
|
||||
function TMycDataArray<T>.Add(const Data: T; Lookback: Int64): TMycDataArray<T>;
|
||||
function TSeries<T>.Add(const Data: T; Lookback: Int64): TSeries<T>;
|
||||
begin
|
||||
Result := Add([Data], 0, 1, Lookback);
|
||||
end;
|
||||
|
||||
function TMycDataArray<T>.GetItems(Idx: Int64): T;
|
||||
function TSeries<T>.GetItems(Idx: Int64): T;
|
||||
var
|
||||
physicalIndex: Int64;
|
||||
begin
|
||||
@@ -120,9 +115,15 @@ begin
|
||||
Result := FChunks[physicalIndex div ChunkSize][physicalIndex mod ChunkSize];
|
||||
end;
|
||||
|
||||
function TMycDataArray<T>.LogicalToPhysicalIndex(LogicalIndex: Int64): Int64;
|
||||
function TSeries<T>.LogicalToPhysicalIndex(LogicalIndex: Int64): Int64;
|
||||
begin
|
||||
Result := FCount - LogicalIndex - 1;
|
||||
end;
|
||||
|
||||
class operator TSeries<T>.Initialize(out Dest: TSeries<T>);
|
||||
begin
|
||||
Dest.FCount := 0;
|
||||
Dest.FTotalCount := 0;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@@ -5,9 +5,11 @@ interface
|
||||
uses
|
||||
System.SysUtils,
|
||||
Myc.Signals,
|
||||
Myc.Mutable,
|
||||
Myc.Core.Notifier,
|
||||
Myc.Trade.Types,
|
||||
Myc.Trade.DataPoint,
|
||||
Myc.Core.Notifier;
|
||||
Myc.Trade.DataArray,
|
||||
Myc.Trade.DataPoint;
|
||||
|
||||
type
|
||||
// Abstract base class for data consumers.
|
||||
@@ -126,6 +128,23 @@ type
|
||||
constructor Create(const Controller: IInterface; const AProc: TProc);
|
||||
end;
|
||||
|
||||
// Endpoint that collects data into a series.
|
||||
TMycDataEndpoint<T> = class(TInterfacedObject, TMutable<TSeries<T>>.IMutable)
|
||||
private
|
||||
FProcessor: TMycContainedProcessor<T>;
|
||||
FTag: TDataProvider<T>.TTag;
|
||||
FDataProvider: TDataProvider<T>;
|
||||
FLookback: Int64;
|
||||
FData: TSeries<T>;
|
||||
FChanged: TEvent;
|
||||
function GetChanged: TSignal;
|
||||
function GetValue: TSeries<T>;
|
||||
function ProcessData(const Value: T): TState;
|
||||
public
|
||||
constructor Create(const ADataProvider: TDataProvider<T>; ALookback: Int64);
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
@@ -354,4 +373,42 @@ begin
|
||||
Result := FProc(Value);
|
||||
end;
|
||||
|
||||
{ TMycDataEndpoint<T> }
|
||||
|
||||
constructor TMycDataEndpoint<T>.Create(const ADataProvider: TDataProvider<T>; ALookback: Int64);
|
||||
begin
|
||||
inherited Create;
|
||||
FDataProvider := ADataProvider;
|
||||
FLookback := ALookback;
|
||||
|
||||
FProcessor := TMycContainedProcessor<T>.Create(Self, ProcessData);
|
||||
FTag := FDataProvider.Link(FProcessor);
|
||||
end;
|
||||
|
||||
destructor TMycDataEndpoint<T>.Destroy;
|
||||
begin
|
||||
FDataProvider.Unlink(FTag);
|
||||
FProcessor.Free;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TMycDataEndpoint<T>.GetChanged: TSignal;
|
||||
begin
|
||||
Result := FChanged.Signal;
|
||||
end;
|
||||
|
||||
function TMycDataEndpoint<T>.GetValue: TSeries<T>;
|
||||
begin
|
||||
Result := FData;
|
||||
end;
|
||||
|
||||
function TMycDataEndpoint<T>.ProcessData(const Value: T): TState;
|
||||
begin
|
||||
Result := TState.Null;
|
||||
|
||||
// Add new data point, respecting the lookback period.
|
||||
FData := FData.Add(Value, FLookback);
|
||||
FChanged.Notify;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
+26
-36
@@ -4,21 +4,19 @@ interface
|
||||
|
||||
uses
|
||||
Myc.Signals,
|
||||
Myc.Trade.Types;
|
||||
Myc.Mutable,
|
||||
Myc.Trade.Types,
|
||||
Myc.Trade.DataArray;
|
||||
|
||||
type
|
||||
// Represents a time-stamped data point in a series.
|
||||
TDataPoint<T> = record
|
||||
Time: TDateTime;
|
||||
Data: T;
|
||||
constructor Create(ATime: TDateTime; const AData: T);
|
||||
end;
|
||||
|
||||
// A generic interface for components that process data of type T.
|
||||
IMycProcessor<T> = interface
|
||||
function ProcessData(const Value: T): TState;
|
||||
end;
|
||||
|
||||
// Interface helper for IDataProvider providing the null object pattern.
|
||||
TDataProvider<T> = record
|
||||
public
|
||||
type
|
||||
TTag = Pointer;
|
||||
IDataProvider = interface
|
||||
@@ -26,14 +24,14 @@ type
|
||||
procedure Unlink(Tag: TTag);
|
||||
end;
|
||||
|
||||
{$REGION 'private'}
|
||||
strict private
|
||||
class var
|
||||
FNull: IDataProvider;
|
||||
class constructor CreateClass;
|
||||
|
||||
private
|
||||
FDataProvider: IDataProvider;
|
||||
{$ENDREGION}
|
||||
|
||||
public
|
||||
constructor Create(const ADataProvider: IDataProvider);
|
||||
|
||||
@@ -50,15 +48,18 @@ type
|
||||
class property Null: IDataProvider read FNull;
|
||||
end;
|
||||
|
||||
// Interface helper for IMycConverter<S,T> providing the null object pattern.
|
||||
// Interface helper for IConverter<S,T> providing the null object pattern.
|
||||
TConverter<S, T> = record
|
||||
public
|
||||
type
|
||||
IConverter = interface(IMycProcessor<S>)
|
||||
{$region 'private'}
|
||||
function GetSender: TDataProvider<T>.IDataProvider;
|
||||
{$endregion}
|
||||
property Sender: TDataProvider<T>.IDataProvider read GetSender;
|
||||
end;
|
||||
|
||||
{$REGION 'private'}
|
||||
{$region 'private'}
|
||||
strict private
|
||||
class var
|
||||
FNull: IConverter;
|
||||
@@ -66,7 +67,7 @@ type
|
||||
private
|
||||
FConverter: IConverter;
|
||||
function GetSender: TDataProvider<T>; inline;
|
||||
{$ENDREGION}
|
||||
{$endregion}
|
||||
public
|
||||
constructor Create(const AConverter: IConverter);
|
||||
|
||||
@@ -83,18 +84,21 @@ type
|
||||
function Chain<R>(const Next: TConverter<T, R>): TConverter<T, R>; overload; inline;
|
||||
function Chain<R>(const Func: TConstFunc<T, R>): TConverter<T, R>; overload; inline;
|
||||
|
||||
// Extracts the field of a record by it's name (using RTTI).
|
||||
function Field<R>(const FieldName: String): TConverter<T, R>; overload; inline;
|
||||
|
||||
// Provides access to the null object instance.
|
||||
class property Null: IConverter read FNull;
|
||||
// Wrapper for IMycConverter.Sender
|
||||
// Wrapper for IConverter.Sender
|
||||
property Sender: TDataProvider<T> read GetSender;
|
||||
end;
|
||||
|
||||
// Factory for creating specific converter instances.
|
||||
TConverter = record
|
||||
class function CreateCounter<T>: TConverter<T, Int64>; static;
|
||||
class function CreateTicker<T>: TConverter<TArray<T>, T>; static;
|
||||
class function CreateRecordField<S, T>(const FieldName: String): TConverter<S, T>; static;
|
||||
class function CreateEndpoint<T>(const DataProvider: TDataProvider<T>; Lookback: Int64): TMutable<TSeries<T>>; static;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@@ -102,14 +106,6 @@ implementation
|
||||
uses
|
||||
Myc.Trade.DataPoint.Impl;
|
||||
|
||||
{ TDataPoint<T> }
|
||||
|
||||
constructor TDataPoint<T>.Create(ATime: TDateTime; const AData: T);
|
||||
begin
|
||||
Time := ATime;
|
||||
Data := AData;
|
||||
end;
|
||||
|
||||
{ TDataProvider<T> }
|
||||
|
||||
class constructor TDataProvider<T>.CreateClass;
|
||||
@@ -121,38 +117,32 @@ end;
|
||||
constructor TDataProvider<T>.Create(const ADataProvider: IDataProvider);
|
||||
begin
|
||||
FDataProvider := ADataProvider;
|
||||
// Ensure that the internal interface is never nil.
|
||||
if not Assigned(FDataProvider) then
|
||||
FDataProvider := FNull;
|
||||
end;
|
||||
|
||||
class operator TDataProvider<T>.Initialize(out Dest: TDataProvider<T>);
|
||||
begin
|
||||
// Initialize new record instances with the null object.
|
||||
Dest.FDataProvider := FNull;
|
||||
end;
|
||||
|
||||
class operator TDataProvider<T>.Implicit(const A: IDataProvider): TDataProvider<T>;
|
||||
begin
|
||||
// Allow implicit conversion from the interface to the helper.
|
||||
Result.Create(A);
|
||||
end;
|
||||
|
||||
class operator TDataProvider<T>.Implicit(const A: TDataProvider<T>): IDataProvider;
|
||||
begin
|
||||
// Allow implicit conversion from the helper to the interface.
|
||||
Result := A.FDataProvider;
|
||||
end;
|
||||
|
||||
function TDataProvider<T>.Link(const Receiver: IMycProcessor<T>): TTag;
|
||||
begin
|
||||
// Forward the call to the wrapped interface.
|
||||
Result := FDataProvider.Link(Receiver);
|
||||
end;
|
||||
|
||||
procedure TDataProvider<T>.Unlink(Tag: TTag);
|
||||
begin
|
||||
// Forward the call to the wrapped interface.
|
||||
FDataProvider.Unlink(Tag);
|
||||
end;
|
||||
|
||||
@@ -160,14 +150,12 @@ end;
|
||||
|
||||
class constructor TConverter<S, T>.CreateClass;
|
||||
begin
|
||||
// Create the singleton null object instance.
|
||||
FNull := TNullConverter<S, T>.Create;
|
||||
end;
|
||||
|
||||
constructor TConverter<S, T>.Create(const AConverter: IConverter);
|
||||
begin
|
||||
FConverter := AConverter;
|
||||
// Ensure that the internal interface is never nil.
|
||||
if not Assigned(FConverter) then
|
||||
FConverter := FNull;
|
||||
end;
|
||||
@@ -190,44 +178,46 @@ end;
|
||||
|
||||
function TConverter<S, T>.Field<R>(const FieldName: String): TConverter<T, R>;
|
||||
begin
|
||||
Result := Chain<R>(TMycRecordFieldReader<T, R>.Create(FieldName));
|
||||
Result := Chain<R>(TConverter.CreateRecordField<T, R>(FieldName));
|
||||
end;
|
||||
|
||||
function TConverter<S, T>.GetSender: TDataProvider<T>;
|
||||
begin
|
||||
// Forward the call to the wrapped interface.
|
||||
Result := FConverter.Sender;
|
||||
end;
|
||||
|
||||
class operator TConverter<S, T>.Initialize(out Dest: TConverter<S, T>);
|
||||
begin
|
||||
// Initialize new record instances with the null object.
|
||||
Dest.FConverter := FNull;
|
||||
end;
|
||||
|
||||
class operator TConverter<S, T>.Implicit(const A: IConverter): TConverter<S, T>;
|
||||
begin
|
||||
// Allow implicit conversion from the interface to the helper.
|
||||
Result.Create(A);
|
||||
end;
|
||||
|
||||
class operator TConverter<S, T>.Implicit(const A: TConverter<S, T>): IConverter;
|
||||
begin
|
||||
// Allow implicit conversion from the helper to the interface.
|
||||
Result := A.FConverter;
|
||||
end;
|
||||
|
||||
function TConverter<S, T>.ProcessData(const Value: S): TState;
|
||||
begin
|
||||
// Forward the call to the wrapped interface.
|
||||
Result := FConverter.ProcessData(Value);
|
||||
end;
|
||||
|
||||
{ TConverter }
|
||||
|
||||
class function TConverter.CreateCounter<T>: TConverter<T, Int64>;
|
||||
begin
|
||||
Result := TMycDataCounter<T>.Create;
|
||||
end;
|
||||
|
||||
class function TConverter.CreateEndpoint<T>(const DataProvider: TDataProvider<T>; Lookback: Int64): TMutable<TSeries<T>>;
|
||||
begin
|
||||
Result := TMycDataEndpoint<T>.Create(DataProvider, Lookback);
|
||||
end;
|
||||
|
||||
class function TConverter.CreateRecordField<S, T>(const FieldName: String): TConverter<S, T>;
|
||||
begin
|
||||
Result := TMycRecordFieldReader<S, T>.Create(FieldName);
|
||||
|
||||
@@ -11,6 +11,7 @@ uses
|
||||
Myc.Futures,
|
||||
Myc.Signals,
|
||||
Myc.Mutable,
|
||||
Myc.Trade.Types,
|
||||
Myc.Trade.DataPoint,
|
||||
Myc.Core.FileCache;
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ type
|
||||
|
||||
TIndicators = record
|
||||
private
|
||||
class function CalculateSMA(const Series: TMycDataArray<Double>; const Period: Integer): Double; static;
|
||||
class function CalculateStdDev(const Series: TMycDataArray<Double>; const Period: Integer): Double; static;
|
||||
class function CalculateWMA(const Series: TMycDataArray<Double>; const Period: Integer): Double; static;
|
||||
class function CalculateSMA(const Series: TSeries<Double>; const Period: Integer): Double; static;
|
||||
class function CalculateStdDev(const Series: TSeries<Double>; const Period: Integer): Double; static;
|
||||
class function CalculateWMA(const Series: TSeries<Double>; const Period: Integer): Double; static;
|
||||
public
|
||||
// Simple Moving Average
|
||||
class function CreateSMA(Period: Integer): TConstFunc<Double, Double>; static;
|
||||
@@ -55,7 +55,7 @@ implementation
|
||||
|
||||
{ TIndicators }
|
||||
|
||||
class function TIndicators.CalculateSMA(const Series: TMycDataArray<Double>; const Period: Integer): Double;
|
||||
class function TIndicators.CalculateSMA(const Series: TSeries<Double>; const Period: Integer): Double;
|
||||
var
|
||||
i: Integer;
|
||||
sum: Double;
|
||||
@@ -70,7 +70,7 @@ begin
|
||||
Result := sum / Period;
|
||||
end;
|
||||
|
||||
class function TIndicators.CalculateStdDev(const Series: TMycDataArray<Double>; const Period: Integer): Double;
|
||||
class function TIndicators.CalculateStdDev(const Series: TSeries<Double>; const Period: Integer): Double;
|
||||
var
|
||||
i: Integer;
|
||||
mean, sumOfSquares: Double;
|
||||
@@ -86,7 +86,7 @@ begin
|
||||
Result := Sqrt(sumOfSquares / Period);
|
||||
end;
|
||||
|
||||
class function TIndicators.CalculateWMA(const Series: TMycDataArray<Double>; const Period: Integer): Double;
|
||||
class function TIndicators.CalculateWMA(const Series: TSeries<Double>; const Period: Integer): Double;
|
||||
var
|
||||
i: Integer;
|
||||
numerator: Double;
|
||||
@@ -114,7 +114,7 @@ end;
|
||||
|
||||
class function TIndicators.CreateBollingerBands(Period: Integer; Multiplier: Double): TConstFunc<Double, TBollingerBandsResult>;
|
||||
begin
|
||||
var sourceData := TMycDataArray<Double>.CreateEmpty;
|
||||
var sourceData: TSeries<Double>;
|
||||
Result :=
|
||||
function(const Value: Double): TBollingerBandsResult
|
||||
var
|
||||
@@ -138,7 +138,7 @@ end;
|
||||
class function TIndicators.CreateEMA(Period: Integer): TConstFunc<Double, Double>;
|
||||
begin
|
||||
var lastEma: Double := Double.NaN;
|
||||
var sourceData := TMycDataArray<Double>.CreateEmpty;
|
||||
var sourceData: TSeries<Double>;
|
||||
var multiplier := 2 / (Period + 1);
|
||||
|
||||
Result :=
|
||||
@@ -170,8 +170,8 @@ class function TIndicators.CreateHMA(Period: Integer): TConstFunc<Double, Double
|
||||
begin
|
||||
var periodHalf := Period div 2;
|
||||
var periodSqrt := Round(Sqrt(Period));
|
||||
var sourceData := TMycDataArray<Double>.CreateEmpty;
|
||||
var diffSeries := TMycDataArray<Double>.CreateEmpty;
|
||||
var sourceData: TSeries<Double>;
|
||||
var diffSeries: TSeries<Double>;
|
||||
|
||||
Result :=
|
||||
function(const Value: Double): Double
|
||||
@@ -244,7 +244,7 @@ class function TIndicators.CreateRSI(Period: Integer): TConstFunc<Double, Double
|
||||
begin
|
||||
var avgGain: Double := Double.NaN;
|
||||
var avgLoss: Double := Double.NaN;
|
||||
var sourceData := TMycDataArray<Double>.CreateEmpty;
|
||||
var sourceData: TSeries<Double>;
|
||||
|
||||
Result :=
|
||||
function(const Value: Double): Double
|
||||
@@ -301,7 +301,7 @@ end;
|
||||
|
||||
class function TIndicators.CreateSMA(Period: Integer): TConstFunc<Double, Double>;
|
||||
begin
|
||||
var sourceData := TMycDataArray<Double>.CreateEmpty;
|
||||
var sourceData: TSeries<Double>;
|
||||
Result :=
|
||||
function(const Value: Double): Double
|
||||
begin
|
||||
@@ -315,7 +315,7 @@ end;
|
||||
|
||||
class function TIndicators.CreateStochastic(KPeriod, DPeriod: Integer): TConstFunc<TOhlcItem, TStochasticResult>;
|
||||
begin
|
||||
var sourceData := TMycDataArray<TOhlcItem>.CreateEmpty;
|
||||
var sourceData: TSeries<TOhlcItem>;
|
||||
var smaD := CreateSMA(DPeriod);
|
||||
|
||||
Result :=
|
||||
|
||||
@@ -21,6 +21,13 @@ type
|
||||
constructor Create(AOpen, AHigh, ALow, AClose, AVolume: Double);
|
||||
end;
|
||||
|
||||
// Represents a time-stamped data point in a series.
|
||||
TDataPoint<T> = record
|
||||
Time: TDateTime;
|
||||
Data: T;
|
||||
constructor Create(ATime: TDateTime; const AData: T);
|
||||
end;
|
||||
|
||||
TConstFunc<S, T> = reference to function(const Value: S): T;
|
||||
|
||||
implementation
|
||||
@@ -44,4 +51,12 @@ begin
|
||||
Volume := AVolume;
|
||||
end;
|
||||
|
||||
{ TDataPoint<T> }
|
||||
|
||||
constructor TDataPoint<T>.Create(ATime: TDateTime; const AData: T);
|
||||
begin
|
||||
Time := ATime;
|
||||
Data := AData;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
Reference in New Issue
Block a user