159 lines
4.4 KiB
ObjectPascal
159 lines
4.4 KiB
ObjectPascal
unit Myc.Trade.Broker;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.SysUtils,
|
|
System.Classes,
|
|
System.Generics.Collections,
|
|
Myc.Data.Value,
|
|
Myc.Ast.Types,
|
|
Myc.Ast.Scope,
|
|
Myc.Ast.RTL.TypeRegistry;
|
|
|
|
{$TYPEINFO ON}
|
|
|
|
type
|
|
TSymProc = reference to procedure(const Symbol: String; Amount: Integer);
|
|
|
|
// Das Interface, das im AST-Skript als Record-Struktur verfügbar sein wird.
|
|
// Die Methodennamen dienen als Dokumentation.
|
|
IMycBroker = interface
|
|
['{D8E9F1A2-B3C4-4D5E-F6A7-B8C9D0E1F2A3}']
|
|
|
|
function Buy(const Symbol: string; Amount: Integer; Price: Double): Boolean;
|
|
function Sell(const Symbol: string; Amount: Integer; Price: Double): Boolean;
|
|
|
|
function GetCash: Double;
|
|
function GetPosition(const Symbol: string): Integer;
|
|
|
|
// Iteriert über alle Positionen und ruft für jede den Callback auf.
|
|
procedure ListPositions(const Callback: TSymProc);
|
|
|
|
property Cash: Double read GetCash;
|
|
end;
|
|
|
|
procedure RegisterBroker(const Scope: IExecutionScope);
|
|
|
|
implementation
|
|
|
|
uses
|
|
Myc.Data.Scalar;
|
|
|
|
type
|
|
TMockBroker = class(TInterfacedObject, IMycBroker)
|
|
strict private
|
|
FCash: Double;
|
|
FPositions: TDictionary<string, Integer>;
|
|
public
|
|
constructor Create(const AInitialCash: Double);
|
|
destructor Destroy; override;
|
|
|
|
function Buy(const Symbol: string; Amount: Integer; Price: Double): Boolean;
|
|
function Sell(const Symbol: string; Amount: Integer; Price: Double): Boolean;
|
|
function GetCash: Double;
|
|
function GetPosition(const Symbol: string): Integer;
|
|
procedure ListPositions(const Callback: TSymProc);
|
|
end;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// TMockBroker
|
|
// -----------------------------------------------------------------------------
|
|
|
|
constructor TMockBroker.Create(const AInitialCash: Double);
|
|
begin
|
|
inherited Create;
|
|
FCash := AInitialCash;
|
|
FPositions := TDictionary<string, Integer>.Create;
|
|
end;
|
|
|
|
destructor TMockBroker.Destroy;
|
|
begin
|
|
FPositions.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TMockBroker.Buy(const Symbol: string; Amount: Integer; Price: Double): Boolean;
|
|
var
|
|
cost: Double;
|
|
currentPos: Integer;
|
|
begin
|
|
cost := Amount * Price;
|
|
if FCash < cost then
|
|
exit(False);
|
|
|
|
FCash := FCash - cost;
|
|
|
|
if not FPositions.TryGetValue(Symbol, currentPos) then
|
|
currentPos := 0;
|
|
|
|
FPositions.AddOrSetValue(Symbol, currentPos + Amount);
|
|
Result := True;
|
|
end;
|
|
|
|
function TMockBroker.Sell(const Symbol: string; Amount: Integer; Price: Double): Boolean;
|
|
var
|
|
revenue: Double;
|
|
currentPos: Integer;
|
|
begin
|
|
revenue := Amount * Price;
|
|
FCash := FCash + revenue;
|
|
|
|
if not FPositions.TryGetValue(Symbol, currentPos) then
|
|
currentPos := 0;
|
|
|
|
FPositions.AddOrSetValue(Symbol, currentPos - Amount);
|
|
Result := True;
|
|
end;
|
|
|
|
function TMockBroker.GetCash: Double;
|
|
begin
|
|
Result := FCash;
|
|
end;
|
|
|
|
function TMockBroker.GetPosition(const Symbol: string): Integer;
|
|
begin
|
|
if not FPositions.TryGetValue(Symbol, Result) then
|
|
Result := 0;
|
|
end;
|
|
|
|
procedure TMockBroker.ListPositions(const Callback: TSymProc);
|
|
var
|
|
pair: TPair<string, Integer>;
|
|
begin
|
|
// Safety check: Wenn das Script nil übergibt, nichts tun.
|
|
if not Assigned(Callback) then
|
|
exit;
|
|
|
|
for pair in FPositions do
|
|
begin
|
|
Callback(pair.Key, pair.Value);
|
|
end;
|
|
end;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Registrierung
|
|
// -----------------------------------------------------------------------------
|
|
|
|
procedure RegisterBroker(const Scope: IExecutionScope);
|
|
begin
|
|
// 1. Registrierung des Callback-Typs.
|
|
TRtlTypeRegistry.RegisterType<TSymProc>;
|
|
|
|
// 2. Registrierung des Broker-Interfaces
|
|
TRtlTypeRegistry.RegisterType<IMycBroker>;
|
|
|
|
// 3. Factory registrieren
|
|
var argTypes := TArray<IStaticType>.Create(TTypes.Float);
|
|
|
|
TRtlTypeRegistry.RegisterFactory<IMycBroker>(
|
|
Scope,
|
|
'create-broker',
|
|
argTypes,
|
|
function(const Args: TArray<TDataValue>): IMycBroker begin Result := TMockBroker.Create(Args[0].AsScalar.Value.AsDouble); end,
|
|
'Creates a new mock broker instance with the specified initial cash.' // Doc für das Symbol selbst
|
|
);
|
|
end;
|
|
|
|
end.
|