Untitled
using System; using System.ComponentModel; using System.Linq; using cAlgo.API; using cAlgo.API.Collections; using cAlgo.API.Indicators; using cAlgo.API.Internals; namespace cAlgo.Robots { [Robot(AccessRights = AccessRights.FullAccess, AddIndicators = true, TimeZone = TimeZones.EasternStandardTime)] public class ScalpingUtec : Robot { [Parameter("Hour End", Group = "Box", DefaultValue = 9)] public int HourEnd { get; set; } [Parameter("Minute End", Group = "Box", DefaultValue = 29)] public int MinuteEnd { get; set; } [Parameter("CHour End", Group = "Destroy Limit", DefaultValue = 9)] public int CLimitHourEnd { get; set; } [Parameter("RHour End", Group = "Destroy Limit", DefaultValue = 10)] public int RLimitHourEnd { get; set; } [Parameter("RMinute End", Group = "Destroy Limit", DefaultValue = 30)] public int RLimitMinuteEnd { get; set; } [Parameter("Hour End", Group = "Destroy Position", DefaultValue = 19)] public int PositionHourEnd { get; set; } [Parameter("Minute End", Group = "Destroy Position", DefaultValue = 00)] public int PositionMinuteEnd { get; set; } [Parameter("Hour End", Group = "Ending Session", DefaultValue = 10)] public int SessionHourEnd { get; set; } [Parameter("Minute End", Group = "Ending Session", DefaultValue = 29)] public int SessionMinuteEnd { get; set; } [Parameter("Look Back Bars", Group = "Box", DefaultValue = 89)] public int BoxLookBackBars { get; set; } [Parameter("Breaker After Cont Bars", Group = "Box", DefaultValue = 2)] public int breakerAfterBoxBars { get; set; } [Parameter("Breaker After Reve Bars", Group = "Box", DefaultValue = 21)] public int breakerAfterBoxReversalBars { get; set; } [Parameter("RR", Group = "Risk", DefaultValue = 2)] public double RR { get; set; } [Parameter("SL Gap", Group = "Risk", DefaultValue = 50)] public double stoplossPipsGap { get; set; } [Parameter("Risk percent", Group = "Risk", DefaultValue = 1)] public double riskPercent { get; set; } [Parameter("Apply Balance", Group = "Risk", DefaultValue = 3000)] public double applyBalance { get; set; } [Parameter("Max Limit State", Group = "Risk", DefaultValue = 4)] public double maxLimitState { get; set; } [Parameter("Max Position State", Group = "Risk", DefaultValue = 2)] public double maxPositionState { get; set; } // PRIVATE private double boxHigh, boxLow; private bool isBoxForming = false; private bool isRunSearching = false; private bool isKillSession = false; private string breakerSide = "none"; private string caseBias = "none"; private double EntryPrice, StoplossPips; //private int _breakerAfterBoxBarsCount = 0; private int _positionOpenedCount = 0; private int[] _minutesBreakerContinue = { 30, 31 }; private int[] _minutesBreakerReversal = { 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50 }; protected override void OnStart() { boxHigh = double.MinValue; boxLow = double.MaxValue; Positions.Opened += OnPositionOpened; } private void OnPositionOpened(PositionOpenedEventArgs args) { Print("What Opened"); _positionOpenedCount++; } protected override void OnBar() { // Handle price updates here DateTime lastBarTime = Bars.OpenTimes.Last(1); Chart.DrawStaticText( "dashboard_minix", $"-- Now {lastBarTime.Hour}:{lastBarTime.Minute} \n" + $"-- Position items {_positionOpenedCount} \n" + $"-- Limit items {PendingOrders.Where(pod => pod.SymbolName == Symbol.Name).Count()} \n" + ($"-- Box High {boxHigh} | Low {boxLow} \n") + $"-- Break Side {breakerSide} \n" + $"-- case Bias {caseBias} \n" + $"-- Goodbye Folk ? {isKillSession} \n" , VerticalAlignment.Bottom, HorizontalAlignment.Left, API.Color.OrangeRed ); // --- Start Game Preprocessing --- if (_positionOpenedCount >= maxPositionState) { // Destroy all pending isKillSession = true; deleteAllPendingOrders(); } // 10:00 AM - No finding new trade for Continuous if (caseBias == "Continue") { if ((lastBarTime.Hour > CLimitHourEnd) || (lastBarTime.Hour == SessionHourEnd && lastBarTime.Minute >= SessionMinuteEnd)) { // Destroy all pending isKillSession = true; deleteAllPendingOrders(); // caseBias | breakerSide | boxHigh |boxLow | isBoxForming -- khởi tạo mình gán nó value gì thì giờ mình gõ lại value đấy! a test kĩ lại giúp nha, có thể e sai! isBoxForming = false; isRunSearching = false; isKillSession = true; breakerSide = "none"; caseBias = "none"; boxHigh = double.MinValue; boxLow = double.MaxValue; _positionOpenedCount = 0; } } // 10:30 AM No finding new trade for Reversal if (caseBias == "Reversal") { if (((lastBarTime.Hour == RLimitHourEnd) && (lastBarTime.Minute >= RLimitMinuteEnd)) || (lastBarTime.Hour == SessionHourEnd && lastBarTime.Minute >= SessionMinuteEnd)) { // Destroy all pending isKillSession = true; deleteAllPendingOrders(); // caseBias | breakerSide | boxHigh |boxLow | isBoxForming -- khởi tạo mình gán nó value gì thì giờ mình gõ lại value đấy! a test kĩ lại giúp nha, có thể e sai! isBoxForming = false; isRunSearching = false; isKillSession = true; breakerSide = "none"; caseBias = "none"; boxHigh = double.MinValue; boxLow = double.MaxValue; _positionOpenedCount = 0; } } if ((caseBias == "none") && ((lastBarTime.Hour == PositionHourEnd ) && (lastBarTime.Minute >= PositionMinuteEnd))) { // Destroy all pending isKillSession = true; deleteAllPendingOrders(); // caseBias | breakerSide | boxHigh |boxLow | isBoxForming -- khởi tạo mình gán nó value gì thì giờ mình gõ lại value đấy! a test kĩ lại giúp nha, có thể e sai! isBoxForming = false; isRunSearching = false; isKillSession = true; breakerSide = "none"; caseBias = "none"; boxHigh = double.MinValue; boxLow = double.MaxValue; _positionOpenedCount = 0; } // Kill Postition at 19:00 if(lastBarTime.Hour == PositionHourEnd && lastBarTime.Minute == PositionMinuteEnd) { closeAllPositions(); } // --- End Game Preprocessing --- // Game Start Here // =================== LET GO =================== // Wait Box Forming - finding box at 9.30 (now is 9.30) Bars.OpenTime.Last(1) = 9.30 | Bars.OpenTime.Last(2) = 9.29 if (lastBarTime.Hour == HourEnd && lastBarTime.Minute == MinuteEnd + 1) { isKillSession = false; for (int i = 2; i <= BoxLookBackBars + 1; i++) { boxHigh = Math.Max(boxHigh, Bars.HighPrices.Last(i)); boxLow = Math.Min(boxLow, Bars.LowPrices.Last(i)); } isBoxForming = true; } // Bars.OpenTime.Last(1) = 9.30 | 9.31 with breakerAfterBoxBars = 2 // Wait for Breaker box -- Case Continue // _breakerAfterBoxBarsCount = 0 --> [1,2] // Case Continue thì mô tả xuôi checkvar 30 31 tại phút Last(1) = 30 if (isBoxForming && _minutesBreakerContinue.Contains(lastBarTime.Minute) && lastBarTime.Hour == 9) { if (Bars.HighPrices.Last(1) > boxHigh && breakerSide == "none") { breakerSide = "top"; isRunSearching = true; } if (Bars.LowPrices.Last(1) < boxLow && breakerSide == "none") { breakerSide = "bottom"; isRunSearching = true; } if (isRunSearching) { caseBias = "Continue"; } } if (isBoxForming && breakerSide == "none") { // 9.29 (29 + 21bars = 50) | Heyyy now is 9.51 ; Last(1) = 9.51 if (lastBarTime.Hour == HourEnd && lastBarTime.Minute == 51) // Phut 51 { // look back to 9.50 --> 9.32 (range 19 bars) , break or not ? for (int i = 2; i <= 20; i++) { if (Bars.HighPrices.Last(i) > boxHigh) { breakerSide = "top"; isRunSearching = true; } if (Bars.LowPrices.Last(i) < boxLow) { breakerSide = "bottom"; isRunSearching = true; } } if (isRunSearching) { caseBias = "Reversal"; } } } if (isKillSession) { return; } if (!isRunSearching) return; if (!this.IsImFvgBuy() && !this.IsImFvgSell()) { return; } if (caseBias == "Continue") { if (breakerSide == "top" && this.IsImFvgBuy()) { // Bias BUY EntryPrice = Math.Min(Bars.OpenPrices.Last(1), Bars.ClosePrices.Last(1)) + 3; StoplossPips = convertToPips(Math.Abs(EntryPrice - Bars.LowPrices.Last(3))) + stoplossPipsGap; double lots = this.getRiskLots(StoplossPips, this.riskPercent); PlaceLimitOrder( TradeType.Buy, SymbolName, Symbol.QuantityToVolumeInUnits(lots), EntryPrice, "continue-buy-" + Bars.Count, StoplossPips, StoplossPips * RR ); Print(" --- --- BUY LIMIT --- --- "); } if (breakerSide == "bottom" && this.IsImFvgSell()) { EntryPrice = Math.Max(Bars.OpenPrices.Last(1), Bars.ClosePrices.Last(1)) - 3; StoplossPips = convertToPips(Math.Abs(EntryPrice - Bars.HighPrices.Last(3))) + stoplossPipsGap; double lots = this.getRiskLots(StoplossPips, this.riskPercent); PlaceLimitOrder( TradeType.Sell, SymbolName, Symbol.QuantityToVolumeInUnits(lots), EntryPrice, "continue-sell-" + Bars.Count, StoplossPips, StoplossPips * RR ); Print(" --- --- SELL LIMIT --- --- "); } } if (caseBias == "Reversal") { if (breakerSide == "bottom" && this.IsImFvgBuy()) { // Bias BUY EntryPrice = Math.Min(Bars.OpenPrices.Last(1), Bars.ClosePrices.Last(1)) + 3; StoplossPips = convertToPips(Math.Abs(EntryPrice - Bars.LowPrices.Last(3))) + stoplossPipsGap; double lots = this.getRiskLots(StoplossPips, this.riskPercent); PlaceLimitOrder( TradeType.Buy, SymbolName, Symbol.QuantityToVolumeInUnits(lots), EntryPrice, "reversal-buy-" + Bars.Count, StoplossPips, StoplossPips * RR ); Print(" --- --- BUY LIMIT --- --- "); } if (breakerSide == "top" && this.IsImFvgSell()) { EntryPrice = Math.Max(Bars.OpenPrices.Last(1), Bars.ClosePrices.Last(1)) - 3; StoplossPips = convertToPips(Math.Abs(EntryPrice - Bars.HighPrices.Last(3))) + stoplossPipsGap; double lots = this.getRiskLots(StoplossPips, this.riskPercent); PlaceLimitOrder( TradeType.Sell, SymbolName, Symbol.QuantityToVolumeInUnits(lots), EntryPrice, "reversal-sell-" + Bars.Count, StoplossPips, StoplossPips * RR ); Print(" --- --- SELL LIMIT --- --- "); } } if (caseBias == "none") { return; } } protected override void OnTick() { } protected override void OnStop() { // Handle cBot stop here } private double getRiskLots(double stopLossPips = 20, double riskPercentage = 1) { return Symbol.VolumeInUnitsToQuantity(Symbol.NormalizeVolumeInUnits( this.getRiskCash(riskPercentage) / (stopLossPips * Symbol.PipValue) )); } private double getRiskCash(double riskPercentage) { return riskPercentage * 0.01 * this.getBalance(); } private double getBalance() { return this.applyBalance; } private void deleteAllPendingOrders() { // Loop through each pending order and delete it foreach (var pod in PendingOrders.Where(pod => pod.SymbolName == Symbol.Name)) { CancelPendingOrder(pod); } } private void closeAllPositions() { Print("** closeAllPositions"); foreach (var pos in Positions.Where(pos => pos.SymbolName == Symbol.Name)) { ClosePositionAsync(pos); } } private bool IsImFvgBuy() { bool check1 = Bars.LowPrices.Last(1) > Math.Max(Bars.OpenPrices.Last(3), Bars.ClosePrices.Last(3)); bool check2 = Bars.HighPrices.Last(3) < Math.Min(Bars.OpenPrices.Last(1), Bars.ClosePrices.Last(1)); return check1 && check2; } private bool IsImFvgSell() { bool check1 = Bars.HighPrices.Last(1) < Math.Min(Bars.OpenPrices.Last(3), Bars.ClosePrices.Last(3)); bool check2 = Bars.HighPrices.Last(3) > Math.Max(Bars.OpenPrices.Last(1), Bars.ClosePrices.Last(1)); return check1 && check2; } private double convertToPips(double priceDif) { return Math.Round(Math.Abs(priceDif / Symbol.PipSize), 1); } } }
Leave a Comment