Code: Select all
using System;
using cAlgo.API;
using cAlgo.API.Internals;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class StrictExecutionEngine : Robot
{
[Parameter("Risk Exposure (%)", Group = "Risk Management", DefaultValue = 1.0)]
public double RiskPct { get; set; }
[Parameter("Strict R:R Gating (Block < 2R)", Group = "Process Controls", DefaultValue = true)]
public bool StrictRR { get; set; }
[Parameter("Max Allowed Spread (Pips)", Group = "Process Controls", DefaultValue = 2.0)]
public double MaxSpreadPips { get; set; }
// UI Elements
private TextBox _invalInput;
private TextBox _targetInput;
private CheckBox _vocalizeCheck;
private Button _executeBtn;
private TextBlock _hudStatus;
private TextBlock _hudSize;
private TextBlock _hudExpectancy;
// Trade State
private double _parsedInval = 0.0;
private double _parsedTarget = 0.0;
private double _exactVolume = 0;
private TradeType _derivedDirection;
protected override void OnStart()
{
BuildInstitutionalTerminal();
}
protected override void OnTick()
{
UpdateEngineMath();
}
private void UpdateEngineMath()
{
double currentSpread = Symbol.Spread / Symbol.PipSize;
// 1. Validate Inputs
bool hasValidInval = double.TryParse(_invalInput.Text, out _parsedInval) && _parsedInval > 0;
double.TryParse(_targetInput.Text, out _parsedTarget);
if (!hasValidInval)
{
LockTerminal("AWAITING STRUCTURAL INVALIDATION");
return;
}
// 2. Deduce Direction from Structure
_derivedDirection = (_parsedInval < Symbol.Ask) ? TradeType.Buy : TradeType.Sell;
double entryPrice = (_derivedDirection == TradeType.Buy) ? Symbol.Ask : Symbol.Bid;
// 3. Risk & Distance Math
double riskPips = Math.Abs(entryPrice - _parsedInval) / Symbol.PipSize;
double riskCap = Account.Balance * (RiskPct / 100.0);
if (riskPips <= 0) return;
// Institutional Volume Normalization
double exactUnits = riskCap / (riskPips * Symbol.PipValue);
_exactVolume = Symbol.NormalizeVolumeInUnits(exactUnits, RoundingMode.Down);
double displayLots = Symbol.VolumeInUnitsToQuantity(_exactVolume);
// 4. Expectancy Math
double netRMultiple = 0;
if (_parsedTarget > 0)
{
double targetPipsRaw = Math.Abs(_parsedTarget - entryPrice) / Symbol.PipSize;
netRMultiple = targetPipsRaw / riskPips; // Net spread naturally accounted for in entryPrice
}
// 5. Hard Gating (The Rules)
bool isOversize = _exactVolume < Symbol.VolumeInUnitsMin;
bool isSpreadViolation = currentSpread > MaxSpreadPips;
bool isRRViolation = StrictRR && _parsedTarget > 0 && netRMultiple < 2.0;
// 6. UI Updates
_hudSize.Text = isOversize ? "VIOLATION (< MIN LOT)" : $"{displayLots:F2} Lots";
_hudSize.ForegroundColor = isOversize ? Color.Red : Color.DeepSkyBlue;
if (_parsedTarget > 0)
{
_hudExpectancy.Text = $"{netRMultiple:F2} R";
_hudExpectancy.ForegroundColor = isRRViolation ? Color.Red : Color.LimeGreen;
}
if (isOversize) LockTerminal("VIOLATION: INVALIDATION TOO WIDE");
else if (isSpreadViolation) LockTerminal($"VIOLATION: SPREAD ({currentSpread:F1}) EXCEEDS MAX");
else if (isRRViolation) LockTerminal("VIOLATION: EXPECTANCY < 2.0 R");
else ArmTerminal(_derivedDirection);
// Render Chart Lines
Chart.DrawHorizontalLine("InvalLine", _parsedInval, Color.Maroon, 1, LineStyle.Lines);
if (_parsedTarget > 0) Chart.DrawHorizontalLine("TargetLine", _parsedTarget, Color.DarkCyan, 1, LineStyle.Lines);
}
private void LockTerminal(string message)
{
_hudStatus.Text = message;
_hudStatus.ForegroundColor = Color.Firebrick;
_executeBtn.IsEnabled = false;
_executeBtn.Text = "SYSTEM LOCKED";
_executeBtn.BackgroundColor = Color.FromArgb(100, 40, 40, 40);
}
private void ArmTerminal(TradeType dir)
{
_hudStatus.Text = "SYSTEM ARMED";
_hudStatus.ForegroundColor = Color.SeaGreen;
// The final circuit breaker
if (_vocalizeCheck.IsChecked == true)
{
_executeBtn.IsEnabled = true;
_executeBtn.Text = $"EXECUTE {dir.ToString().ToUpper()}";
_executeBtn.BackgroundColor = dir == TradeType.Buy ? Color.FromArgb(255, 10, 120, 60) : Color.FromArgb(255, 180, 40, 40);
}
else
{
_executeBtn.IsEnabled = false;
_executeBtn.Text = "PENDING VOCALIZATION";
_executeBtn.BackgroundColor = Color.FromArgb(100, 40, 40, 40);
}
}
private void OnExecuteClick(ButtonClickEventArgs args)
{
if (_exactVolume < Symbol.VolumeInUnitsMin) return;
// Convert prices to pips for StopLoss/TakeProfit parameters
double entryPrice = (_derivedDirection == TradeType.Buy) ? Symbol.Ask : Symbol.Bid;
double slPips = Math.Abs(entryPrice - _parsedInval) / Symbol.PipSize;
double tpPips = _parsedTarget > 0 ? Math.Abs(_parsedTarget - entryPrice) / Symbol.PipSize : 0;
double? finalTpPips = tpPips > 0 ? tpPips : (double?)null;
ExecuteMarketOrder(_derivedDirection, SymbolName, _exactVolume, "StrictEngine", slPips, finalTpPips);
// Reset terminal after execution
_invalInput.Text = "";
_targetInput.Text = "";
_vocalizeCheck.IsChecked = false;
Chart.RemoveObject("InvalLine");
Chart.RemoveObject("TargetLine");
}
private void BuildInstitutionalTerminal()
{
var panel = new StackPanel
{
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Bottom,
BackgroundColor = Color.FromArgb(250, 15, 15, 15),
Margin = new Thickness(20),
Width = 280
};
// Border Header
panel.AddChild(new Border { BackgroundColor = Color.FromArgb(255, 30, 30, 30), Height = 25, Child = new TextBlock { Text = "INSTITUTIONAL EXECUTION PROTOCOL", FontWeight = FontWeight.Bold, ForegroundColor = Color.Silver, TextAlignment = TextAlignment.Center, Margin = new Thickness(0,4,0,0) } });
// Inputs
_invalInput = new TextBox { Margin = new Thickness(10, 10, 10, 5), ForegroundColor = Color.Maroon };
_targetInput = new TextBox { Margin = new Thickness(10, 0, 10, 10), ForegroundColor = Color.DarkCyan };
_invalInput.TextChanged += args => UpdateEngineMath();
_targetInput.TextChanged += args => UpdateEngineMath();
panel.AddChild(CreateInputRow("M15 Invalidation Price:", _invalInput));
panel.AddChild(CreateInputRow("Target Price (Opt):", _targetInput));
// Data Readouts
_hudStatus = new TextBlock { Text = "AWAITING INPUT", ForegroundColor = Color.Firebrick, Margin = new Thickness(10, 5, 10, 2), FontWeight = FontWeight.Bold };
_hudSize = new TextBlock { Text = "---", ForegroundColor = Color.White, Margin = new Thickness(10, 2, 10, 2) };
_hudExpectancy = new TextBlock { Text = "---", ForegroundColor = Color.White, Margin = new Thickness(10, 2, 10, 10) };
panel.AddChild(_hudStatus);
panel.AddChild(_hudSize);
panel.AddChild(_hudExpectancy);
// The Circuit Breaker Checkbox
_vocalizeCheck = new CheckBox { Text = "I have vocalized the invalidation.", Margin = new Thickness(10, 10, 10, 10), ForegroundColor = Color.DimGray };
_vocalizeCheck.Checked += args => UpdateEngineMath();
_vocalizeCheck.Unchecked += args => UpdateEngineMath();
panel.AddChild(_vocalizeCheck);
// Execution Button
_executeBtn = new Button { Text = "SYSTEM LOCKED", IsEnabled = false, Height = 40, Margin = new Thickness(10), BackgroundColor = Color.FromArgb(100, 40, 40, 40), ForegroundColor = Color.White, FontWeight = FontWeight.Bold };
_executeBtn.Click += OnExecuteClick;
panel.AddChild(_executeBtn);
Chart.AddControl(panel);
}
private StackPanel CreateInputRow(string label, TextBox inputField)
{
var row = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(10, 2, 10, 2) };
row.AddChild(new TextBlock { Text = label, Width = 140, ForegroundColor = Color.Gray, VerticalAlignment = VerticalAlignment.Center });
inputField.Width = 110;
row.AddChild(inputField);
return row;
}
}
}