815 lines
31 KiB
ObjectPascal
815 lines
31 KiB
ObjectPascal
(*
|
|
---
|
|
## Aura Module API Documentation
|
|
|
|
This unit defines the core interfaces and records for the Aura system, designed for robust algorithmic trading strategy development,
|
|
backtesting, and optimization. It encapsulates key concepts for defining strategies, executing backtests, performing walk-forward
|
|
optimizations, and conducting statistical robustness analysis via Monte Carlo simulations.
|
|
|
|
---
|
|
|
|
### Core Interfaces and Records
|
|
|
|
#### `IAuraObject`
|
|
Base interface for all Aura objects, providing a common `Name` property for identification.
|
|
* `Name`: A writeable string representing the object's name.
|
|
|
|
#### `TAuraArray<T: IAuraObject>`
|
|
A record providing a mutable, observable array-like collection for `IAuraObject` instances. It wraps a `TWriteable<TArray<T>>` and offers basic array manipulation methods.
|
|
* `Items`: A writeable array of `IAuraObject` instances.
|
|
* `Insert(Idx: Integer; const Item: T)`: Inserts an item at a specified index.
|
|
* `Delete(Idx: Integer)`: Deletes an item at a specified index.
|
|
* `IndexOf(const Item: T)`: Returns the index of a given item.
|
|
|
|
#### `IAuraLiveObject`
|
|
Extends `IAuraObject` for entities that are dynamically produced and actively executing operations, providing logging capabilities and a running status.
|
|
* `Log`: A `TStrings` object for logging events and status messages.
|
|
* `IsRunning`: Indicates whether the object is currently active.
|
|
|
|
#### `IAuraNode`
|
|
Extends `IAuraObject` for objects that can be part of a hierarchical structure and can be serialized.
|
|
* `Caption`: A human-readable representation of the object's name.
|
|
* `Serialize(const Write: TJsonWriter)`: Serializes the object's state to a JSON writer.
|
|
|
|
#### `IAuraChilds<T: IAuraNode>`
|
|
A generic interface for `IAuraNode`s that can have child nodes, enabling hierarchical organization within the Aura system.
|
|
* `Items`: A `TAuraArray` containing the child nodes.
|
|
|
|
#### `TAuraParameterDef`
|
|
Defines the metadata for a single strategy parameter, including its name, type, and default value.
|
|
* `Name`: The name of the parameter.
|
|
* `ParamType`: The data type of the parameter (e.g., integer, float, string, UTC time).
|
|
* `DefaultValue`: The default value for the parameter, stored as a `TAuraParameterValue`.
|
|
|
|
#### `TAuraParameterRecordDef`
|
|
Represents a collection of `TAuraParameterDef` records, defining all parameters for a specific strategy. This is an alias for `TArray<TAuraParameterDef>`.
|
|
|
|
#### `IAuraBot`
|
|
An interface representing an instance that executes a trading strategy with given parameters over a specified time period.
|
|
* `PnL`: A mutable data series representing the Profit and Loss (PnL) curve of the bot's execution.
|
|
|
|
#### `IAuraStrategy`
|
|
Defines a trading strategy, providing methods to create `IAuraBot` instances and specifying its parameter structure.
|
|
* `CreateBot(const Parameters: TArray<TAuraParameterValue>; StartTime, EndTime: TDateTime)`: Creates and returns an `IAuraBot` instance configured with the given parameters and time range.
|
|
* `ParameterRecordDef`: Defines the set of parameters expected by this strategy.
|
|
|
|
#### `TAuraTradePerformance`
|
|
A record encapsulating key performance metrics from a backtest or optimization run.
|
|
* `PnL`: Total Profit and Loss.
|
|
* `SharpeRatio`: Risk-adjusted return.
|
|
* `MaxDrawdown`: Maximum peak-to-trough decline.
|
|
* `ProfitFactor`: Ratio of gross profits to gross losses.
|
|
* `CalmarRatio`: Annualized return divided by the maximum drawdown.
|
|
* `WinRate`: Percentage of winning trades.
|
|
|
|
#### `TAuraMonteCarloResult`
|
|
Stores the results of a Monte Carlo simulation, providing a probabilistic distribution of `TAuraTradePerformance` outcomes.
|
|
* `Percentile`: An array of `TAuraTradePerformance` records, sorted by PnL and distributed into 10% percentiles, allowing for statistical risk assessment.
|
|
|
|
#### `IAuraTradeResult`
|
|
Represents the comprehensive outcome of a trade simulation (e.g., from a backtest or optimization), including performance metrics, trade details, and the ability to perform Monte Carlo analysis.
|
|
* `Performance`: The `TAuraTradePerformance` metrics for this result.
|
|
* `Trades`: A `TDataSeries<Double>` representing the PnLs of individual trades, serving as the basis for Monte Carlo simulation.
|
|
* `CalcMonteCarloSimulation(Steps: Integer)`: Asynchronously performs a Monte Carlo simulation on the `Trades` data, returning a `TFuture` that resolves to a `TAuraMonteCarloResult`.
|
|
|
|
#### `TAuraTimeRange`
|
|
A record defining a specific time window with a start and end date/time.
|
|
* `StartTime`: The start of the time range.
|
|
* `EndTime`: The end of the time range.
|
|
|
|
#### `IAuraBacktest`
|
|
An interface for executing a single backtest of a trading strategy.
|
|
* `BacktestResult`: A `TFuture` that resolves to the `IAuraTradeResult` of this backtest.
|
|
* `Bot`: The `IAuraBot` instance executing the backtest.
|
|
* `Parameters`: The specific parameters used for this backtest.
|
|
* `Strategy`: The `IAuraStrategy` being backtested.
|
|
* `TimeRange`: The historical time window over which the backtest is conducted.
|
|
|
|
#### `IAuraParameterOptimization`
|
|
Represents a single optimization slot (window) within a Walk-Forward Optimization process. It manages the execution of multiple in-sample backtests to find optimal parameters, followed by an out-of-sample test.
|
|
* `InSampleTests`: A mutable array of `IAuraBacktest` instances representing the backtests run during the in-sample optimization phase. New tests are added, and less optimal ones may be removed.
|
|
* `OutOfSampleTest`: A mutable `IAuraBacktest` representing the test run with the best-fit parameters from the in-sample optimization on the subsequent out-of-sample data.
|
|
|
|
#### `IAuraWalkForwardOptimizer`
|
|
Orchestrates the entire Walk-Forward Optimization (WFO) process, coordinating multiple `IAuraParameterOptimization` slots sequentially to test strategy adaptability across various market phases.
|
|
* `OptimizationResult`: A `TFuture` that resolves to the aggregated `IAuraTradeResult` representing the combined performance of all out-of-sample tests.
|
|
* `Slot`: An array of `IAuraParameterOptimization` instances, each representing a distinct optimization window.
|
|
|
|
#### `IAuraParameterNode`
|
|
Represents a single configurable parameter for optimization algorithms, allowing its value to be set and observed.
|
|
* `Value`: A mutable `TAuraParameterValue` representing the parameter's current setting.
|
|
|
|
#### `IAuraParameterList`
|
|
An alias for `IAuraChilds<IAuraParameterNode>`, providing a structured way to manage collections of `IAuraParameterNode`s.
|
|
|
|
#### `IAuraStudy`
|
|
Base interface for all types of strategy analysis studies (e.g., single backtests, parameter optimizations, WFOs).
|
|
* `EventLog`: A `TStrings` object for logging events specific to the study.
|
|
* `Strategy`: The `IAuraStrategy` that is the subject of the study.
|
|
|
|
#### `TAuraParameterRange`
|
|
Defines the allowed range for a strategy parameter during optimization.
|
|
* `MinValue`: The minimum allowed value for the parameter, as a `TAuraParameterValue`.
|
|
* `MaxValue`: The maximum allowed value for the parameter, as a `TAuraParameterValue`.
|
|
|
|
#### `IAuraBacktestStudy`
|
|
A specialized `IAuraStudy` for setting up and initiating a single backtest.
|
|
* `TimeRange`: The `TAuraTimeRange` for the backtest.
|
|
* `Start`: Initiates and returns an `IAuraBacktest` instance.
|
|
|
|
#### `IAuraParameterOptimizationStudy`
|
|
A specialized `IAuraStudy` for configuring and initiating a parameter optimization process (e.g., using genetic algorithms) over a specific time range.
|
|
* `Parameters`: An `IAuraChilds` collection of `IAuraParameterNode`s defining the configuration parameters for the optimization algorithm itself (e.g., max generations, population size).
|
|
* `TimeRange`: The `TAuraTimeRange` for the optimization.
|
|
* `Start`: Initiates and returns an `IAuraParameterOptimization` instance.
|
|
|
|
#### `IAuraWFOStudy`
|
|
A specialized `IAuraStudy` for configuring and initiating a Walk-Forward Optimization process.
|
|
* `ParameterRange[Idx: Integer]`: A writeable `TAuraParameterRange` defining the search space for each strategy parameter during the optimization phases.
|
|
* `NumSlots`: A writeable integer indicating the number of time windows (slots) for the WFO.
|
|
* `Start`: Initiates and returns an `IAuraWalkForwardOptimizer` instance.
|
|
|
|
#### `IAuraTradingMode`
|
|
An enumeration defining different operational modes for a trading environment.
|
|
* `tmTesting`: Mode for historical backtesting.
|
|
* `tmSim`: Mode for simulated live trading (paper trading).
|
|
* `tmLive`: Mode for actual live trading.
|
|
|
|
#### `IAuraWorkspace`
|
|
Represents the scope of a complete testing and trading environment, containing various studies and managing the overall trading mode.
|
|
* `WalkForwardAnalysis`: An `IAuraChilds` collection of `IAuraWFOStudy` instances.
|
|
* `Backtests`: An `IAuraChilds` collection of `IAuraBacktestStudy` instances.
|
|
* `ParameterOptimizations`: An `IAuraChilds` collection of `IAuraParameterOptimizationStudy` instances.
|
|
* `TradingMode`: A writeable `IAuraTradingMode` indicating the current operational mode.
|
|
|
|
#### `IAuraModule`
|
|
An interface for creating instances of `IAuraStrategy`. Used for managing available strategy types.
|
|
* `CreateStrategy`: Creates and returns a new `IAuraStrategy` instance.
|
|
|
|
#### `IAuraApplication`
|
|
The application-level singleton, serving as the root for serialization and providing access to all defined strategies and workspaces.
|
|
* `Strategies`: An `IAuraChilds` collection of `IAuraModule` instances.
|
|
* `Workspaces`: An `IAuraChilds` collection of `IAuraWorkspace` instances.
|
|
|
|
---
|
|
*)
|
|
|
|
unit Myc.Aura.Module;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.JSON.Writers,
|
|
System.Classes,
|
|
System.Generics.Collections,
|
|
Myc.Signals,
|
|
Myc.Futures,
|
|
Myc.Mutable,
|
|
Myc.Trade.DataPoint,
|
|
Myc.Aura.Parameter;
|
|
|
|
type
|
|
// Base class of all Aura objects
|
|
IAuraObject = interface
|
|
function GetName: TWriteable<String>;
|
|
property Name: TWriteable<String> read GetName;
|
|
end;
|
|
|
|
TAuraArray<T: IAuraObject> = record
|
|
private
|
|
FArray: TWriteable<TArray<T>>;
|
|
function GetItems: TWriteable<TArray<T>>;
|
|
public
|
|
class operator Initialize(out Dest: TAuraArray<T>);
|
|
procedure Insert(Idx: Integer; const Item: T);
|
|
procedure Delete(Idx: Integer);
|
|
function IndexOf(const Item: T): Integer;
|
|
property Items: TWriteable<TArray<T>> read GetItems;
|
|
end;
|
|
|
|
// Base class for objects that are dynamically produced and are executing
|
|
IAuraLiveObject = interface(IAuraObject)
|
|
function GetLog: TStrings;
|
|
function IsRunning: Boolean;
|
|
property Log: TStrings read GetLog;
|
|
end;
|
|
|
|
IAuraNode = interface(IAuraObject)
|
|
function GetCaption: string;
|
|
// Serialize the whole project
|
|
procedure Serialize(const Write: TJsonWriter);
|
|
// Pretty print of Name
|
|
property Caption: string read GetCaption;
|
|
end;
|
|
|
|
IAuraChilds<T> = interface(IAuraNode)
|
|
function GetItems: TWriteable<TArray<T>>;
|
|
procedure Insert(Idx: Integer; const Item: T);
|
|
procedure Delete(Idx: Integer);
|
|
function IndexOf(const Item: T): Integer;
|
|
// Nodes to add as childs in hierarchical representation
|
|
property Items: TWriteable<TArray<T>> read GetItems;
|
|
end;
|
|
|
|
TAuraChilds<T> = record
|
|
private
|
|
FChilds: IAuraChilds<T>;
|
|
function GetCaption: string;
|
|
public
|
|
constructor Create(const AChilds: IAuraChilds<T>);
|
|
class operator Implicit(const A: IAuraChilds<T>): TAuraChilds<T>; overload;
|
|
class operator Implicit(const A: TAuraChilds<T>): IAuraChilds<T>; overload;
|
|
procedure Serialize(const Write: TJsonWriter);
|
|
procedure Insert(Idx: Integer; const Item: T);
|
|
procedure Delete(Idx: Integer);
|
|
function IndexOf(const Item: T): Integer;
|
|
property Caption: string read GetCaption;
|
|
end;
|
|
|
|
TAuraParameterDef = record
|
|
Name: String;
|
|
ParamType: TAuraParameterType;
|
|
DefaultValue: TAuraParameterValue;
|
|
end;
|
|
|
|
TAuraParameterRecordDef = TArray<TAuraParameterDef>;
|
|
|
|
// A bot executes a strategy
|
|
IAuraBot = interface(IAuraLiveObject)
|
|
function GetPnL: TMutable<TDataSeries<Double>>;
|
|
// Zero-based PnL series
|
|
property PnL: TMutable<TDataSeries<Double>> read GetPnL;
|
|
end;
|
|
|
|
// A strategy creates a bot that executes that strategy with given parameters and within a given time slot.
|
|
IAuraStrategy = interface(IAuraObject)
|
|
function CreateBot(const Parameters: TArray<TAuraParameterValue>; StartTime, EndTime: TDateTime): IAuraBot;
|
|
function GetParameterRecordDef: TAuraParameterRecordDef;
|
|
// Defines the parameters of this strategy
|
|
property ParameterRecordDef: TAuraParameterRecordDef read GetParameterRecordDef;
|
|
end;
|
|
|
|
// The performance of a backtest or walk forward optimization
|
|
TAuraTradePerformance = record
|
|
PnL: Double;
|
|
SharpeRatio, MaxDrawdown, ProfitFactor, CalmarRatio, WinRate: Double;
|
|
end;
|
|
|
|
TAuraMonteCarloResult = record
|
|
// Performance sorted by PnL and distributed to percentiles of 10% each
|
|
Percentile: array[0..10] of TAuraTradePerformance;
|
|
end;
|
|
|
|
IAuraTradeResult = interface
|
|
function GetPerformance: TAuraTradePerformance;
|
|
function GetTrades: TDataSeries<Double>;
|
|
// Perform Monte Carlo Simulation and generate performance distribution
|
|
function CalcMonteCarloSimulation(Steps: Integer): TFuture<TAuraMonteCarloResult>;
|
|
// PnLs of each trade = Equity curve
|
|
property Trades: TDataSeries<Double> read GetTrades;
|
|
// The performance of this equity curve
|
|
property Performance: TAuraTradePerformance read GetPerformance;
|
|
end;
|
|
|
|
TAuraTimeRange = record
|
|
StartTime: TDateTime;
|
|
EndTime: TDateTime;
|
|
end;
|
|
|
|
// Backtesting
|
|
IAuraBacktest = interface(IAuraLiveObject)
|
|
function GetParameters: TArray<TAuraParameterValue>;
|
|
function GetStrategy: IAuraStrategy;
|
|
function GetBot: IAuraBot;
|
|
function GetBacktestResult: TFuture<IAuraTradeResult>;
|
|
function GetTimeRange: TAuraTimeRange;
|
|
// The bot executing the backtest (generated by Strategy.CreateBot with the given parameters).
|
|
property Bot: IAuraBot read GetBot;
|
|
// The backtest result
|
|
property BacktestResult: TFuture<IAuraTradeResult> read GetBacktestResult;
|
|
// The strategy parameters for this backtest
|
|
property Parameters: TArray<TAuraParameterValue> read GetParameters;
|
|
// The strategy to backtest
|
|
property Strategy: IAuraStrategy read GetStrategy;
|
|
// The tested time window
|
|
property TimeRange: TAuraTimeRange read GetTimeRange;
|
|
end;
|
|
|
|
// Generates parameter sets using genetic algorithms (or other techniques).
|
|
// Executes backtests and finds the best run by evaluating the backtest results.
|
|
IAuraParameterOptimization = interface(IAuraLiveObject)
|
|
function GetInSampleTests: TMutable<TArray<IAuraBacktest>>;
|
|
function GetOutOfSampleTest: TMutable<IAuraBacktest>;
|
|
// The running in-sample-tests. New tests will be added until the optimization stops.
|
|
property InSampleTests: TMutable<TArray<IAuraBacktest>> read GetInSampleTests;
|
|
// After in sample testing is finished, the out-of-sample-test with the best parameter set is executed.
|
|
property OutOfSampleTest: TMutable<IAuraBacktest> read GetOutOfSampleTest;
|
|
end;
|
|
|
|
// Walk-Forward-Optimizer
|
|
IAuraWalkForwardOptimizer = interface(IAuraLiveObject)
|
|
function GetOptimizationResult: TFuture<IAuraTradeResult>;
|
|
function GetSlot: TArray<IAuraParameterOptimization>;
|
|
// When optimization is ready, this will contain the result for the combined WFO slots
|
|
property OptimizationResult: TFuture<IAuraTradeResult> read GetOptimizationResult;
|
|
// The concurrently running optimization slots
|
|
property Slot: TArray<IAuraParameterOptimization> read GetSlot;
|
|
end;
|
|
|
|
// A Parameter Value
|
|
IAuraParameterNode = interface(IAuraNode)
|
|
function GetValue: TMutable<TAuraParameterValue>;
|
|
property Value: TMutable<TAuraParameterValue> read GetValue;
|
|
end;
|
|
IAuraParameterList = IAuraChilds<IAuraParameterNode>;
|
|
|
|
// A study on a strategy
|
|
IAuraStudy = interface(IAuraNode)
|
|
function GetEventLog: TStrings;
|
|
function GetStrategy: IAuraStrategy;
|
|
property EventLog: TStrings read GetEventLog;
|
|
// The Strategy to optimize
|
|
property Strategy: IAuraStrategy read GetStrategy;
|
|
end;
|
|
|
|
TAuraParameterRange = record
|
|
MinValue, MaxValue: TAuraParameterValue;
|
|
end;
|
|
|
|
// Study on a single backtest
|
|
IAuraBacktestStudy = interface(IAuraStudy)
|
|
function GetTimeRange: TAuraTimeRange;
|
|
function Start: IAuraBacktest;
|
|
property TimeRange: TAuraTimeRange read GetTimeRange;
|
|
end;
|
|
|
|
// Study parameter optimization
|
|
IAuraParameterOptimizationStudy = interface(IAuraStudy)
|
|
function GetParameters: IAuraChilds<IAuraParameterNode>;
|
|
function GetTimeRange: TAuraTimeRange;
|
|
function Start: IAuraParameterOptimization;
|
|
// Depending on the implementation this may be MaxGenerations, PopulationSize, Mutations, etc
|
|
property Parameters: IAuraChilds<IAuraParameterNode> read GetParameters;
|
|
property TimeRange: TAuraTimeRange read GetTimeRange;
|
|
end;
|
|
|
|
// Walk forward optimization
|
|
IAuraWFOStudy = interface(IAuraStudy)
|
|
function GetParameterRange(Idx: Integer): TWriteable<TAuraParameterRange>;
|
|
function GetNumSlots: TWriteable<Integer>;
|
|
// Starts WalkForwardOptimizer with the given number of NumSlots.
|
|
function Start: IAuraWalkForwardOptimizer;
|
|
// A list of parameter values to test, one for each parameter in the Strategy's parameter definition.
|
|
// This defines the parameter space for optimization algorithms.
|
|
property ParameterRange[Idx: Integer]: TWriteable<TAuraParameterRange> read GetParameterRange;
|
|
// Number of time slots (windows) to test.
|
|
property NumSlots: TWriteable<Integer> read GetNumSlots;
|
|
end;
|
|
|
|
TAuraTradingMode = (tmTesting, tmSim, tmLive);
|
|
|
|
// Repesents the scope of a workspace
|
|
IAuraWorkspace = interface(IAuraNode)
|
|
['{8485F7E7-F097-4CB8-8186-A6C9AE0048AF}']
|
|
// function GetWalkForwardAnalysis: IAuraChilds<IAuraWFOStudy>;
|
|
// function GetBacktests: IAuraChilds<IAuraBacktestStudy>;
|
|
// function GetParameterOptimizations: IAuraChilds<IAuraParameterOptimizationStudy>;
|
|
// function GetWalkForwardAnalysis: IAuraChilds<IAuraWFOStudy>;
|
|
// function GetBacktests: IAuraChilds<IAuraBacktestStudy>;
|
|
// function GetParameterOptimizations: IAuraChilds<IAuraParameterOptimizationStudy>;
|
|
// property WalkForwardAnalysis: IAuraChilds<IAuraWFOStudy> read GetWalkForwardAnalysis;
|
|
// property Backtests: IAuraChilds<IAuraBacktestStudy> read GetBacktests;
|
|
// property ParameterOptimizations: IAuraChilds<IAuraParameterOptimizationStudy> read GetParameterOptimizations;
|
|
// property WalkForwardAnalysis: IAuraChilds<IAuraWFOStudy> read GetWalkForwardAnalysis;
|
|
// property Backtests: IAuraChilds<IAuraBacktestStudy> read GetBacktests;
|
|
// property ParameterOptimizations: IAuraChilds<IAuraParameterOptimizationStudy> read GetParameterOptimizations;
|
|
function GetTradingMode: TWriteable<TAuraTradingMode>;
|
|
function GetStudies: TAuraArray<IAuraStudy>;
|
|
property TradingMode: TWriteable<TAuraTradingMode> read GetTradingMode;
|
|
property Studies: TAuraArray<IAuraStudy> read GetStudies;
|
|
end;
|
|
|
|
IAuraModule = interface
|
|
procedure SetupWorkspace(const Workspace: IAuraWorkspace);
|
|
end;
|
|
|
|
// Application singleton, the root for serialization
|
|
IAuraApplication = interface(IAuraNode)
|
|
function GetModuleNames: TMutable<TArray<String>>;
|
|
function GetModules(const Name: String): IAuraModule;
|
|
function GetWorkspaces: IAuraChilds<IAuraWorkspace>;
|
|
procedure RegisterModule(const Name: String; const Module: IAuraModule);
|
|
property ModuleNames: TMutable<TArray<String>> read GetModuleNames;
|
|
property Modules[const Name: String]: IAuraModule read GetModules;
|
|
property Workspaces: IAuraChilds<IAuraWorkspace> read GetWorkspaces;
|
|
end;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Generic implementation for a collection of child nodes.
|
|
TMycAuraObject = class(TInterfacedObject, IAuraObject)
|
|
private
|
|
FName: TWriteable<String>;
|
|
function GetName: TWriteable<String>;
|
|
procedure Serialize(const Write: TJsonWriter); virtual;
|
|
public
|
|
constructor Create(const AName: string);
|
|
end;
|
|
|
|
// Generic implementation for a collection of child nodes.
|
|
TMycAuraNode = class(TMycAuraObject, IAuraNode)
|
|
private
|
|
protected
|
|
function GetCaption: string; virtual;
|
|
procedure Serialize(const Write: TJsonWriter); override;
|
|
end;
|
|
|
|
// Generic implementation for a collection of child nodes.
|
|
TMycAuraChilds<T: IAuraNode> = class(TInterfacedObject, IAuraChilds<T>)
|
|
private
|
|
FName: TWriteable<String>;
|
|
FItems: TWriteable<TArray<T>>;
|
|
function GetCaption: string;
|
|
function GetItems: TWriteable<TArray<T>>;
|
|
function GetName: TWriteable<String>;
|
|
procedure Serialize(const Write: TJsonWriter);
|
|
public
|
|
constructor Create(const AName: string);
|
|
procedure Delete(Idx: Integer);
|
|
function IndexOf(const Item: T): Integer;
|
|
procedure Insert(Idx: Integer; const Item: T);
|
|
end;
|
|
|
|
TMycAuraWorkspace = class(TMycAuraNode, IAuraWorkspace)
|
|
private
|
|
FTradingMode: TWriteable<TAuraTradingMode>;
|
|
FStudies: TAuraArray<IAuraStudy>;
|
|
function GetStudies: TAuraArray<IAuraStudy>;
|
|
function GetTradingMode: TWriteable<TAuraTradingMode>;
|
|
protected
|
|
function GetCaption: string; override;
|
|
public
|
|
constructor Create(const AName: string; TradingMode: TAuraTradingMode);
|
|
end;
|
|
|
|
TMycAuraApplication = class(TInterfacedObject, IAuraApplication)
|
|
private
|
|
FName: TWriteable<String>;
|
|
FModules: TDictionary<String, IAuraModule>;
|
|
FModulesChanged: TEvent;
|
|
FModuleNames: TMutable<TArray<String>>;
|
|
FWorkspaces: TAuraChilds<IAuraWorkspace>;
|
|
function GetCaption: string;
|
|
function GetName: TWriteable<String>;
|
|
function GetModuleNames: TMutable<TArray<String>>;
|
|
function GetModules(const Name: String): IAuraModule;
|
|
function GetWorkspaces: IAuraChilds<IAuraWorkspace>;
|
|
procedure Serialize(const Write: TJsonWriter);
|
|
public
|
|
constructor Create;
|
|
procedure RegisterModule(const Name: String; const Module: IAuraModule);
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ TMycAuraObject }
|
|
|
|
constructor TMycAuraObject.Create(const AName: string);
|
|
begin
|
|
inherited Create;
|
|
FName := TWriteable<String>.CreateWriteable;
|
|
FName.Value := AName;
|
|
end;
|
|
|
|
function TMycAuraObject.GetName: TWriteable<String>;
|
|
begin
|
|
Result := FName;
|
|
end;
|
|
|
|
procedure TMycAuraObject.Serialize(const Write: TJsonWriter);
|
|
begin
|
|
Write.WriteStartObject;
|
|
Write.WritePropertyName('Name');
|
|
Write.WriteValue(FName.Value);
|
|
Write.WriteEndObject;
|
|
end;
|
|
|
|
{ TMycAuraNode }
|
|
|
|
function TMycAuraNode.GetCaption: string;
|
|
begin
|
|
Result := FName.Value;
|
|
end;
|
|
|
|
procedure TMycAuraNode.Serialize(const Write: TJsonWriter);
|
|
begin
|
|
Write.WriteStartObject;
|
|
inherited;
|
|
Write.WriteEndObject;
|
|
end;
|
|
|
|
{ TAuraArray<T> }
|
|
|
|
class operator TAuraArray<T>.Initialize(out Dest: TAuraArray<T>);
|
|
begin
|
|
Dest.FArray := TWriteable<TArray<T>>.CreateWriteable;
|
|
end;
|
|
|
|
procedure TAuraArray<T>.Delete(Idx: Integer);
|
|
var
|
|
oldArray: TArray<T>;
|
|
newArray: TArray<T>;
|
|
oldCount: Integer;
|
|
begin
|
|
oldArray := FArray.Value;
|
|
oldCount := Length(oldArray);
|
|
|
|
if (Idx < 0) or (Idx >= oldCount) then
|
|
exit;
|
|
|
|
SetLength(newArray, oldCount - 1);
|
|
|
|
// Copy elements before the index
|
|
if Idx > 0 then
|
|
TArray.Copy<T>(oldArray, newArray, 0, 0, Idx);
|
|
|
|
// Copy elements after the index
|
|
if Idx < oldCount - 1 then
|
|
TArray.Copy<T>(oldArray, newArray, Idx + 1, Idx, oldCount - Idx - 1);
|
|
|
|
FArray.Value := newArray;
|
|
end;
|
|
|
|
procedure TAuraArray<T>.Insert(Idx: Integer; const Item: T);
|
|
var
|
|
oldArray: TArray<T>;
|
|
newArray: TArray<T>;
|
|
oldCount: Integer;
|
|
begin
|
|
oldArray := FArray.Value;
|
|
if not Assigned(oldArray) then
|
|
SetLength(oldArray, 0);
|
|
oldCount := Length(oldArray);
|
|
|
|
if Idx < 0 then
|
|
Idx := 0;
|
|
if Idx > oldCount then
|
|
Idx := oldCount;
|
|
|
|
SetLength(newArray, oldCount + 1);
|
|
|
|
// Copy elements before the index
|
|
if Idx > 0 then
|
|
TArray.Copy<T>(oldArray, newArray, 0, 0, Idx);
|
|
|
|
newArray[Idx] := Item;
|
|
|
|
// Copy elements after the index
|
|
if Idx < oldCount then
|
|
TArray.Copy<T>(oldArray, newArray, Idx, Idx + 1, oldCount - Idx);
|
|
|
|
FArray.Value := newArray;
|
|
end;
|
|
|
|
function TAuraArray<T>.GetItems: TWriteable<TArray<T>>;
|
|
begin
|
|
Result := FArray;
|
|
end;
|
|
|
|
function TAuraArray<T>.IndexOf(const Item: T): Integer;
|
|
begin
|
|
Result := TArray.IndexOf<T>(FArray.Value, Item);
|
|
end;
|
|
|
|
{ TMycAuraChilds<T> }
|
|
|
|
constructor TMycAuraChilds<T>.Create(const AName: string);
|
|
begin
|
|
inherited Create;
|
|
FName := TWriteable<String>.CreateWriteable(AName);
|
|
FItems := TWriteable<TArray<T>>.CreateWriteable;
|
|
end;
|
|
|
|
procedure TMycAuraChilds<T>.Delete(Idx: Integer);
|
|
var
|
|
oldArray: TArray<T>;
|
|
newArray: TArray<T>;
|
|
oldCount: Integer;
|
|
begin
|
|
oldArray := FItems.Value;
|
|
oldCount := Length(oldArray);
|
|
|
|
if (Idx < 0) or (Idx >= oldCount) then
|
|
exit;
|
|
|
|
SetLength(newArray, oldCount - 1);
|
|
|
|
// Copy elements before the index
|
|
if Idx > 0 then
|
|
TArray.Copy<T>(oldArray, newArray, 0, 0, Idx);
|
|
|
|
// Copy elements after the index
|
|
if Idx < oldCount - 1 then
|
|
TArray.Copy<T>(oldArray, newArray, Idx + 1, Idx, oldCount - Idx - 1);
|
|
|
|
FItems.Value := newArray;
|
|
end;
|
|
|
|
function TMycAuraChilds<T>.GetCaption: string;
|
|
begin
|
|
Result := FName.Value;
|
|
end;
|
|
|
|
function TMycAuraChilds<T>.GetItems: TWriteable<TArray<T>>;
|
|
begin
|
|
Result := FItems;
|
|
end;
|
|
|
|
function TMycAuraChilds<T>.GetName: TWriteable<String>;
|
|
begin
|
|
Result := FName;
|
|
end;
|
|
|
|
function TMycAuraChilds<T>.IndexOf(const Item: T): Integer;
|
|
begin
|
|
Result := TArray.IndexOf<T>(FItems.Value, Item);
|
|
end;
|
|
|
|
procedure TMycAuraChilds<T>.Insert(Idx: Integer; const Item: T);
|
|
var
|
|
oldArray: TArray<T>;
|
|
newArray: TArray<T>;
|
|
oldCount: Integer;
|
|
begin
|
|
oldArray := FItems.Value;
|
|
if not Assigned(oldArray) then
|
|
SetLength(oldArray, 0);
|
|
oldCount := Length(oldArray);
|
|
|
|
if Idx < 0 then
|
|
Idx := 0;
|
|
if Idx > oldCount then
|
|
Idx := oldCount;
|
|
|
|
SetLength(newArray, oldCount + 1);
|
|
|
|
// Copy elements before the index
|
|
if Idx > 0 then
|
|
TArray.Copy<T>(oldArray, newArray, 0, 0, Idx);
|
|
|
|
newArray[Idx] := Item;
|
|
|
|
// Copy elements after the index
|
|
if Idx < oldCount then
|
|
TArray.Copy<T>(oldArray, newArray, Idx, Idx + 1, oldCount - Idx);
|
|
|
|
FItems.Value := newArray;
|
|
end;
|
|
|
|
procedure TMycAuraChilds<T>.Serialize(const Write: TJsonWriter);
|
|
var
|
|
Item: T;
|
|
arr: TArray<T>;
|
|
begin
|
|
Write.WriteStartObject;
|
|
inherited;
|
|
Write.WritePropertyName('Items');
|
|
Write.WriteStartArray;
|
|
arr := FItems.Value;
|
|
for Item in arr do
|
|
Item.Serialize(Write);
|
|
Write.WriteEndArray;
|
|
Write.WriteEndObject;
|
|
end;
|
|
|
|
{ TMycAuraApplication }
|
|
|
|
constructor TMycAuraApplication.Create;
|
|
begin
|
|
inherited Create;
|
|
FName := TWriteable<String>.CreateWriteable('Application');
|
|
FModules := TDictionary<String, IAuraModule>.Create;
|
|
FModulesChanged := TEvent.CreateEvent;
|
|
FModuleNames :=
|
|
TMutable<TArray<String>>.Construct(FModulesChanged.Signal, function: TArray<String> begin Result := FModules.Keys.ToArray; end);
|
|
FWorkspaces := TMycAuraChilds<IAuraWorkspace>.Create('Workspaces');
|
|
end;
|
|
|
|
function TMycAuraApplication.GetCaption: string;
|
|
begin
|
|
Result := FName.Value;
|
|
end;
|
|
|
|
function TMycAuraApplication.GetName: TWriteable<String>;
|
|
begin
|
|
Result := FName;
|
|
end;
|
|
|
|
function TMycAuraApplication.GetModuleNames: TMutable<TArray<String>>;
|
|
begin
|
|
Result := FModuleNames;
|
|
end;
|
|
|
|
function TMycAuraApplication.GetModules(const Name: String): IAuraModule;
|
|
begin
|
|
if not FModules.TryGetValue(Name, Result) then
|
|
Result := nil;
|
|
end;
|
|
|
|
function TMycAuraApplication.GetWorkspaces: IAuraChilds<IAuraWorkspace>;
|
|
begin
|
|
Result := FWorkspaces;
|
|
end;
|
|
|
|
procedure TMycAuraApplication.RegisterModule(const Name: String; const Module: IAuraModule);
|
|
begin
|
|
FModules.Add(Name, Module);
|
|
FModulesChanged.Notify;
|
|
end;
|
|
|
|
procedure TMycAuraApplication.Serialize(const Write: TJsonWriter);
|
|
begin
|
|
Write.WriteStartObject;
|
|
Write.WritePropertyName('Name');
|
|
Write.WriteValue(FName.Value);
|
|
Write.WritePropertyName('Workspaces');
|
|
FWorkspaces.Serialize(Write);
|
|
Write.WriteEndObject;
|
|
end;
|
|
|
|
function CreateAuraApplication: IAuraApplication;
|
|
begin
|
|
Result := TMycAuraApplication.Create;
|
|
end;
|
|
|
|
constructor TMycAuraWorkspace.Create(const AName: string; TradingMode: TAuraTradingMode);
|
|
begin
|
|
inherited Create(AName);
|
|
FTradingMode := TWriteable<TAuraTradingMode>.CreateWriteable(TradingMode);
|
|
end;
|
|
|
|
function TMycAuraWorkspace.GetCaption: string;
|
|
begin
|
|
var mode := '';
|
|
case FTradingMode.Value of
|
|
tmTesting: mode := ' (Test)';
|
|
tmSim: mode := ' (Sim)';
|
|
tmLive: mode := ' (Live)';
|
|
end;
|
|
Result := inherited GetCaption + mode;
|
|
end;
|
|
|
|
function TMycAuraWorkspace.GetStudies: TAuraArray<IAuraStudy>;
|
|
begin
|
|
Result := FStudies;
|
|
end;
|
|
|
|
function TMycAuraWorkspace.GetTradingMode: TWriteable<TAuraTradingMode>;
|
|
begin
|
|
Result := FTradingMode;
|
|
end;
|
|
|
|
constructor TAuraChilds<T>.Create(const AChilds: IAuraChilds<T>);
|
|
begin
|
|
FChilds := AChilds;
|
|
end;
|
|
|
|
procedure TAuraChilds<T>.Delete(Idx: Integer);
|
|
begin
|
|
FChilds.Delete(Idx);
|
|
end;
|
|
|
|
function TAuraChilds<T>.GetCaption: string;
|
|
begin
|
|
Result := FChilds.Caption;
|
|
end;
|
|
|
|
function TAuraChilds<T>.IndexOf(const Item: T): Integer;
|
|
begin
|
|
Result := FChilds.IndexOf(Item);
|
|
end;
|
|
|
|
procedure TAuraChilds<T>.Insert(Idx: Integer; const Item: T);
|
|
begin
|
|
FChilds.Insert(Idx, Item);
|
|
end;
|
|
|
|
procedure TAuraChilds<T>.Serialize(const Write: TJsonWriter);
|
|
begin
|
|
FChilds.Serialize(Write);
|
|
end;
|
|
|
|
class operator TAuraChilds<T>.Implicit(const A: IAuraChilds<T>): TAuraChilds<T>;
|
|
begin
|
|
Result.Create(A);
|
|
end;
|
|
|
|
class operator TAuraChilds<T>.Implicit(const A: TAuraChilds<T>): IAuraChilds<T>;
|
|
begin
|
|
Result := A.FChilds;
|
|
end;
|
|
|
|
end.
|