Untitled

 avatar
unknown
plain_text
2 months ago
9.6 kB
3
Indexable
using System;
using System.Linq;
using System.Reflection;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None, AddIndicators = true, TimeZone= TimeZones.EasternStandardTime)]
    public class Rush1030am : Robot
    {
        [Parameter("Look Back Hour", Group = "Box", DefaultValue = 10)]
        public int HourLookBack { get; set; }

        [Parameter("Look Back Minute", Group = "Box", DefaultValue = 30)]
        public int MinuteLookBack { get; set; }

        [Parameter("Hour", Group = "Opening Range", DefaultValue = 9)]
        public int OpeningRangeHour { get; set; }

        [Parameter("Minute", Group = "Opening Range", DefaultValue = 30)]
        public int OpeningRangeMinute { get; set; }

        [Parameter("Pre Day Hour", Group = "Opening Range", DefaultValue = 16)]
        public int PreDayHour { get; set; }

        [Parameter("Pre Day Minute", Group = "Opening Range", DefaultValue = 13)]
        public int PreDayMinute { get; set; }

        [Parameter("Min Deep Pips 10.30 ", Group = "Bias", DefaultValue = 700)]
        public int MinDeepPipsBias { get; set; }

        private double OpeningRangeHigh = double.NaN, OpeningRangeLow = double.NaN;

        private bool IsFormingOpeningRange = false;
        private double OpenPrice1030AM = double.NaN;
        private string BiasSide = "none";
        private string swingName = "none";

        private double LastSwingHigh = double.NaN, LastSwingLow = double.NaN, 
            LastSwingHighPointOpenPrice = double.NaN, LastSwingLowPointOpenPrice = double.NaN,
            LastSwingHighPointClosePrice = double.NaN, LastSwingLowPointClosePrice = double.NaN;

        private double StoplossPip = 150;
        private double RR = 3;
        private double MaxHoldingPosition = 1;
        private bool OffTrade = false;

        // BIAS Dựa vào vị trí của OpeningRange Gap vs chùm nến từ (10h - 10h29) 30 nến , 80% nến nằm xa Opening Range Gap thì giá có xác suất hút về 
        // 10 - 10h29 --> vị trí box phải xa hơn OpenRange gap 50% GAP

        // 10h30 - 11h29 --> tìm Structure shift của Swing(5) 

        // Nếu box nằm dưới Opening Range Gap thì buy
        // Nếu box nằm trên Opening Range Gap thì sell
        // Giá break close Swing high 
        // RR = 3
        // SL = 15pip
        // Mở Bot lúc 10h để OnBar update Swing High Low 

        // 17/12 : 10h30 Structshift luôn swing high

        protected override void OnStart()
        {
            
        }

        protected override void OnBar()
        {
            // Handle price updates here

            DateTime lastBarTime = Bars.OpenTimes.Last(1);
            UpdateSwingPoints(); // Period = 5

            Chart.DrawStaticText("dashboard",
                $"Now ... {lastBarTime.Hour} : {lastBarTime.Minute} \n" +
                $"BiasSide: {BiasSide} \n" +
                $"Opening Range: H {OpeningRangeHigh} & L {OpeningRangeLow} \n" + 
                $"IsSwingHigh: {LastSwingHigh} ... Open = {LastSwingHighPointOpenPrice}  \n" +
                $"IsSwingLow: {LastSwingLow} ... Open = {LastSwingLowPointOpenPrice}  \n" +
                $".... \n"
                , VerticalAlignment.Bottom,
                HorizontalAlignment.Left,
                API.Color.Yellow);


            if (lastBarTime.Hour == HourLookBack && lastBarTime.Minute == MinuteLookBack)
            {
                (OpeningRangeHigh, OpeningRangeLow) = GetOpeningRangeGap();
                IsFormingOpeningRange = true;
                OpenPrice1030AM = Bars.OpenPrices.Last(1);
            }

            if (!IsFormingOpeningRange) return;

            if (CountExecutingPositions() + CountPendingOrders() >= MaxHoldingPosition) return; 

            double DeepBiasPips = double.NaN;

            if (OpenPrice1030AM < OpeningRangeLow) {
                DeepBiasPips = this.convertToPips(OpeningRangeLow - OpenPrice1030AM);

                if (DeepBiasPips >= MinDeepPipsBias) {
                    BiasSide = "bottom";
                }
            }

            if (OpenPrice1030AM > OpeningRangeHigh)
            {
                DeepBiasPips = this.convertToPips(OpenPrice1030AM - OpeningRangeHigh);

                if (DeepBiasPips >= MinDeepPipsBias)
                {
                    BiasSide = "top";

                    // Find
                }
            }

            if (double.IsNaN(DeepBiasPips) || DeepBiasPips < MinDeepPipsBias) return;

            if (OffTrade) return;

            if (BiasSide == "top" && isStructureShiftByClosePrice("breakLow")) {
                // BUY LIMIT AT Open of SWING HIGH
                PlaceLimitOrder(
                    TradeType.Sell,
                    SymbolName,
                    Symbol.QuantityToVolumeInUnits(1),
                    LastSwingLowPointClosePrice,
                    "order-buy-" + Bars.Count,
                    StoplossPip,
                    StoplossPip * RR
                );
                OffTrade = true;
            }


            if (BiasSide == "bottom" && isStructureShiftByClosePrice("breakHigh"))
            {
                // BUY LIMIT AT Open of SWING HIGH
                PlaceLimitOrder(
                    TradeType.Buy,
                    SymbolName,
                    Symbol.QuantityToVolumeInUnits(1),
                    LastSwingHighPointClosePrice,
                    "order-sell-" + Bars.Count,
                    StoplossPip,
                    StoplossPip * RR
                );
                OffTrade = true;
            }







        }

        protected override void OnStop()
        {
            // Handle cBot stop here
        }

        private double GetPreviousDayClosePrice(int index)
        {
            // Find the close price at 16:14 PM on the previous day
            DateTime previousDayTargetTime = MarketSeries.OpenTime[index].AddHours(PreDayHour).AddMinutes(PreDayMinute).AddDays(-1);

            Print("previous date ", previousDayTargetTime);

            for (int i = 0; i < MarketSeries.OpenTime.Count; i++)
            {
                if (MarketSeries.OpenTime[i] == previousDayTargetTime)
                    return MarketSeries.Close[i];
            }

            return double.NaN; // Return NaN if not found
        }


        public (double highestHigh, double lowestLow) GetOpeningRangeGap() {
            double preDayPrice = GetPreviousDayClosePrice(Bars.Count - 1);
            double openingPrice = 0;

            for (int ii = 1; ii < 65; ii++) {
                if (Bars.OpenTimes.Last(ii).Hour == OpeningRangeHour && Bars.OpenTimes.Last(ii).Minute == OpeningRangeMinute) {

                    openingPrice = Bars.OpenPrices.Last(ii);

                    break;
                }
                
            }


            return (Math.Max(openingPrice, preDayPrice), Math.Min(openingPrice, preDayPrice));
        }


        private double convertToPips(double priceDif)
        {
            return Math.Round(Math.Abs(priceDif / Symbol.PipSize), 1);
        }

        private void UpdateSwingPoints() {
            

            UpdateSwingHigh();
            UpdateSwingLow();
        }

        // top | bottom
        private bool isStructureShiftByClosePrice(string type = "breakHigh") {

            if (type == "breakHigh" && Bars.ClosePrices.Last(1) > LastSwingHigh)
            {
                return true;
            }

            if (type == "breakLow" && Bars.ClosePrices.Last(1) < LastSwingLow)
            {
                return true;
            }

            return false;
        
        }

        private void UpdateSwingHigh()
        {
            bool checker = Bars.HighPrices.Last(3) > Math.Max(Bars.HighPrices.Last(2), Bars.HighPrices.Last(1));
            checker = checker && Bars.HighPrices.Last(3) > Math.Max(Bars.HighPrices.Last(4), Bars.HighPrices.Last(5));

            if(checker)
            {
                LastSwingHigh = Bars.HighPrices.Last(3); // Update the most recent Swing High
                LastSwingHighPointOpenPrice = Bars.OpenPrices.Last(3);
                LastSwingHighPointClosePrice = Bars.ClosePrices.Last(3);
            }
        }

        private void UpdateSwingLow()
        {
            bool checker = Bars.LowPrices.Last(3) < Math.Min(Bars.LowPrices.Last(2), Bars.LowPrices.Last(1));
            checker = checker && Bars.LowPrices.Last(3) < Math.Min(Bars.LowPrices.Last(4), Bars.LowPrices.Last(5));

            if (checker)
            {
                LastSwingLow = Bars.LowPrices.Last(3); // Update the most recent Swing High
                LastSwingLowPointOpenPrice = Bars.OpenPrices.Last(3);
                LastSwingLowPointClosePrice = Bars.ClosePrices.Last(3);
            }
        }

        private int CountExecutingPositions()
        {
            return Positions.Count(position =>
            (position.TradeType == TradeType.Buy || position.TradeType == TradeType.Sell)
            && Symbol.Name == position.SymbolName);
        }

        private int CountPendingOrders()
        {
            return PendingOrders.Count(pod => Symbol.Name == pod.SymbolName);
        }
    }
}
Leave a Comment