Untitled
unknown
plain_text
5 months ago
10 kB
3
Indexable
using cAlgo.API; using cAlgo.API.Internals; using cAlgo.API.Indicators; using System; using System.Collections.Generic; using System.Linq; namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class unknown : Robot { #region Parameters [Parameter("Holdings ", DefaultValue = 5)] public int PosHoldings { get; set; } [Parameter("Risk/Reward Ratio", DefaultValue = 3)] public double RR { get; set; } [Parameter("Max Balance Risk", DefaultValue = 10000)] public int MaxBalanceRisk { get; set; } [Parameter("Cancel Pending After (bars)", DefaultValue = 15)] public int CancelPendingAfter { get; set; } [Parameter("Min SL Pips", DefaultValue = 5)] public double MinSlPips { get; set; } [Parameter("Risk Percentage", DefaultValue = 1)] public double RiskBase { get; set; } [Parameter("Box Start Hour (UTC)", DefaultValue = 19)] public int StartHour { get; set; } [Parameter("Box End Hour (UTC)", DefaultValue = 5)] public int EndHour { get; set; } [Parameter("New York Offset", Group = "Trading Hours", DefaultValue = -5)] public int NyOffset { get; set; } [Parameter("Trading Start Hour (NY)", Group = "Trading Hours", DefaultValue = 9)] public int HourFrom { get; set; } [Parameter("Trading End Hour (NY)", Group = "Trading Hours", DefaultValue = 12)] public int HourTo { get; set; } #endregion #region Private Fields private double todayBoxHigh = double.MinValue; private double todayBoxLow = double.MaxValue; private bool isBuyDay; private bool isSellDay; private bool goLimit; private TradeType? currentTradeType; private double entryPrice; private double stopLossPrice; private readonly Dictionary<string, int> barsSinceOrderCreation = new Dictionary<string, int>(); private DateTime lastTradingDay; #endregion protected override void OnStart() { lastTradingDay = Server.Time.AddDays(-1); ValidateParameters(); } private void ValidateParameters() { if (RR <= 0) throw new ArgumentException("Risk/Reward ratio must be positive"); if (MinSlPips <= 0) throw new ArgumentException("Minimum stop loss pips must be positive"); if (RiskBase <= 0 || RiskBase > 100) throw new ArgumentException("Risk percentage must be between 0 and 100"); if (PosHoldings <= 0) throw new ArgumentException("Holdings must be positive"); } private void DailySetup() { try { DateTime serverTime = Server.Time; DateTime nyStart = serverTime.AddHours(NyOffset).Date.AddHours(StartHour); DateTime nyEnd = serverTime.AddHours(NyOffset).Date.AddHours(EndHour); if (nyEnd < nyStart) { nyEnd = nyEnd.AddDays(1); } CalculateBoxBoundaries(nyStart, nyEnd); UpdateTradingDirection(); DrawBox("TodayBox", nyStart, todayBoxLow, nyEnd, todayBoxHigh, Color.Blue); } catch (Exception ex) { Print($"Error in DailySetup: {ex.Message}"); } } private void CalculateBoxBoundaries(DateTime start, DateTime end) { todayBoxHigh = double.MinValue; todayBoxLow = double.MaxValue; for (int i = 0; i < MarketSeries.Close.Count; i++) { DateTime barTime = MarketSeries.OpenTime[i]; if (barTime >= start && barTime <= end) { double closePrice = MarketSeries.Close[i]; todayBoxHigh = Math.Max(todayBoxHigh, closePrice); todayBoxLow = Math.Min(todayBoxLow, closePrice); } } } private void UpdateTradingDirection() { // Determine if it's a buy or sell day based on box position double currentPrice = Symbol.Bid; double boxMidpoint = (todayBoxHigh + todayBoxLow) / 2; isBuyDay = currentPrice > boxMidpoint; isSellDay = currentPrice < boxMidpoint; } protected override void OnBar() { try { if (IsNewTradingDay()) { DailySetup(); CleanupOldOrders(); } var currentHour = Server.Time.AddHours(NyOffset).Hour; ProcessPendingOrders(); UpdateTradeSignals(); goLimit = currentHour >= HourFrom && currentHour <= HourTo; UpdateDashboard(currentHour); if (CanPlaceNewOrders()) { ExecuteTradeStrategy(); } } catch (Exception ex) { Print($"Error in OnBar: {ex.Message}"); } } private void UpdateTradeSignals() { if (IsBuyModel()) { currentTradeType = TradeType.Buy; entryPrice = Bars.LowPrices.Last(1); stopLossPrice = Bars.LowPrices.Last(2); DrawSignalLines("buy"); } else if (IsSellModel()) { currentTradeType = TradeType.Sell; entryPrice = Bars.HighPrices.Last(1); stopLossPrice = Bars.HighPrices.Last(2); DrawSignalLines("sell"); } } private void DrawSignalLines(string type) { if (type == "buy") { Chart.DrawHorizontalLine("gap-top", Bars.LowPrices.Last(1), Color.DarkRed); Chart.DrawHorizontalLine("gap-bottom", Bars.HighPrices.Last(3), Color.DarkRed); } else { Chart.DrawHorizontalLine("gap-bottom", Bars.HighPrices.Last(1), Color.DarkRed); Chart.DrawHorizontalLine("gap-top", Bars.LowPrices.Last(3), Color.DarkRed); } } private bool CanPlaceNewOrders() { return countExecutingPositions() + countPendingOrders() < PosHoldings && (IsBuyModel() || IsSellModel()) && goLimit; } private void ExecuteTradeStrategy() { if (currentTradeType == TradeType.Buy) { PlaceBuyOrder(); } else if (currentTradeType == TradeType.Sell) { PlaceSellOrder(); } } private void PlaceBuyOrder() { double stoplossPip = CalculateStopLossPips(entryPrice, stopLossPrice); double lots = CalculateLotSize(stoplossPip); string orderLabel = $"order-buy-{Bars.Count}"; PlaceLimitOrder(TradeType.Buy, SymbolName, Symbol.QuantityToVolumeInUnits(lots), entryPrice, orderLabel, stoplossPip, stoplossPip * RR); barsSinceOrderCreation[orderLabel] = 0; } private void PlaceSellOrder() { double stoplossPip = CalculateStopLossPips(entryPrice, stopLossPrice); double lots = CalculateLotSize(stoplossPip); string orderLabel = $"order-sell-{Bars.Count}"; PlaceLimitOrder(TradeType.Sell, SymbolName, Symbol.QuantityToVolumeInUnits(lots), entryPrice, orderLabel, stoplossPip, stoplossPip * RR); barsSinceOrderCreation[orderLabel] = 0; } private double CalculateStopLossPips(double entry, double stopLoss) { return Math.Max(convertToPips(Math.Abs(entry - stopLoss)), MinSlPips); } private double CalculateLotSize(double stopLossPips) { return getRiskLots(stopLossPips, RiskBase); } private void UpdateDashboard(int currentHour) { Chart.DrawStaticText( "dashboard_minix", $"Model: {currentTradeType}\n" + $"Current Hour (NY): {currentHour}\n" + $"Trading Allowed: {goLimit}\n" + $"Box High: {todayBoxHigh:F5}\n" + $"Box Low: {todayBoxLow:F5}", VerticalAlignment.Bottom, HorizontalAlignment.Left, Color.GreenYellow ); } // Rest of your existing helper methods with improved error handling private double getRiskLots(double stopLossPips, double riskPercentage) { if (stopLossPips <= 0) throw new ArgumentException("Stop loss pips must be positive"); double riskAmount = getRiskCash(riskPercentage); return Symbol.VolumeInUnitsToQuantity(Symbol.NormalizeVolumeInUnits( riskAmount / (stopLossPips * Symbol.PipValue) )); } private double convertToPips(double priceDif) { return Math.Round(Math.Abs(priceDif / Symbol.PipSize), 1); } private double getRiskCash(double riskPercentage) { return Math.Min(Account.Balance, MaxBalanceRisk) * (riskPercentage / 100); } private void CleanupOldOrders() { var activeLabels = PendingOrders .Where(o => o.SymbolName == Symbol.Name) .Select(o => o.Label) .ToList(); foreach (var label in barsSinceOrderCreation.Keys.ToList()) { if (!activeLabels.Contains(label)) { barsSinceOrderCreation.Remove(label); } } } } }
Editor is loading...
Leave a Comment