Untitled

mail@pastecode.io avatarunknown
plain_text
14 days ago
11 kB
1
Indexable
Never
using cAlgo.API;
using cAlgo.API.Indicators;
using System;
using System.Collections.Generic;
namespace BTCUSDbot
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class BTCUSDbot: Robot
    {
        [Parameter("ATR Period", DefaultValue = 14)]
        public int ATRPeriod
        {
            get;
            set;
        }
        private TimeFrame higherTimeframe = TimeFrame.Minute15;
        private double higherTimeframeThreshold = 0.5;
        private AverageTrueRange atr;
        private double lotSize;
        private DirectionalMovementSystem dmi;
        private MovingAverage fastMA;
        private MovingAverage slowMA;
        private DateTime lastBarTime;
        private Color regularStopLossColor = Color.Red;
        private Color trailingStopLossColor = Color.Blue;
        private Color currentStopLossColor;
        private double trailingStopDistanceInPips = 30;
        private double minProfitForTrailing = 30; // Minimum profit in pips before trailing stop becomes active
        private RelativeStrengthIndex rsi;
        private double stopLossPercentage = 2; // Set your desired stop loss percentage
        private double takeProfitPercentage = 2;
        private double _volumeInUnits;
        private AverageDirectionalMovementIndexRating _averageDirectionalMovementIndexRating;
        private double last5;
        [Parameter("Volume (Lots)", DefaultValue = 0.01)]
        public double VolumeInLots
        {
            get;
            set;
        }
        [Parameter("Label", DefaultValue = "Sample")]
        public string Label
        {
            get;
            set;
        }
        private int lookbackPeriod = 100;
        double lowestLow;
        double highestHigh;
        bool calculateHighestHigh = false;
        //support/resistance distance
        double distance;
        double distanceThreshold;
        double pipsThreshold = 10000;
        public Position[] BotPositions
        {
            get
            {
                return Positions.FindAll(Label);
            }
        }
        protected override void OnStart()
        {
            atr = Indicators.AverageTrueRange(ATRPeriod, MovingAverageType.Simple);
            dmi = Indicators.DirectionalMovementSystem(ATRPeriod);
            distanceThreshold = pipsThreshold * Symbol.PipSize;
            int fastMAPeriod = 50;
            int slowMAPeriod = 200;
            int rsiPeriod = 14;
            rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, rsiPeriod);
            fastMA = Indicators.MovingAverage(Bars.ClosePrices, fastMAPeriod, MovingAverageType.Simple);
            slowMA = Indicators.MovingAverage(Bars.ClosePrices, slowMAPeriod, MovingAverageType.Simple);
            lastBarTime = Bars.OpenTimes.LastValue;
            _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots);
            _averageDirectionalMovementIndexRating = Indicators.AverageDirectionalMovementIndexRating(30);
            lowestLow = MarketSeries.Low.Minimum(lookbackPeriod);
            highestHigh = MarketSeries.High.Maximum(lookbackPeriod);
        }
        protected override void OnBar()
        {
            last5 = Bars.ClosePrices.Count - 5;
            foreach(var position in Positions)
            {
                double unrealizedProfitInPips = position.Pips;
                if (unrealizedProfitInPips >= minProfitForTrailing)
                {
                    string lineName = $"StopLossLine_{position.Id}";
                    double trailingStopPrice = Symbol.Bid - trailingStopDistanceInPips * Symbol.PipSize;
                    ModifyPosition(position, trailingStopPrice, position.TakeProfit);
                    currentStopLossColor = trailingStopLossColor;
                    Chart.RemoveObject(lineName); //for sl/tp lines
                    Chart.RemoveAllObjects(); //for support/resistance
                    // Draw Stop Loss Line if it exists
                    if (position.StopLoss.HasValue)
                    {
                        double stopLossPrice = position.StopLoss.Value;
                        Chart.DrawHorizontalLine(lineName, stopLossPrice, currentStopLossColor, 1, LineStyle.Solid);
                    }
                }
            }
            //if(calculateHighestHigh == true)
            // {
            highestHigh = MarketSeries.High.Maximum(lookbackPeriod);
            lowestLow = MarketSeries.Low.Minimum(lookbackPeriod);
            Chart.DrawHorizontalLine("resistance line", highestHigh, Color.Gold, 1, LineStyle.LinesDots);
            Chart.DrawHorizontalLine("support line", lowestLow, Color.White, 1, LineStyle.LinesDots);
            //  calculateHighestHigh =false;
            //   }
        }
        protected override void OnTick()
        {
            //         if (!IsPriceAboveWeeklySMAs())
            //  {
            //      Print("Price is below SMAs on the weekly chart. Not trading.");
            //     return;
            //  }
            distanceThreshold = pipsThreshold * Symbol.PipSize;
            distance = highestHigh - lowestLow;
            if (Bars.OpenTimes.LastValue > lastBarTime)
            {
                lastBarTime = Bars.OpenTimes.LastValue;
                int index = Bars.ClosePrices.Count - 2; // Index of the last closed bar
                bool isHigherTimeframeUptrend = IsHigherTimeframeUptrend();
                if (Symbol.Bid < highestHigh) Chart.DrawHorizontalLine("support line", lowestLow, Color.White, 1, LineStyle.LinesDots);
                Chart.DrawHorizontalLine("resistance line", highestHigh, Color.Gold, 1, LineStyle.LinesDots);
                double atrValue = atr.Result[index];
                // Define your threshold for a price spike (e.g., 2 times the ATR)
                double spikeThreshold = 2 * atrValue;
                double currentValue = MarketSeries.Close.LastValue; // Get the current closing price
                double minValue = MarketSeries.Close.LastValue; // Replace YourMinValue with the minimum value of your range
                double maxValue = MarketSeries.Close.LastValue + 10; // Rep
                double pipBuffer = 10.0; // You can adjust this buffer value as needed
                double buffer = Symbol.PipSize * pipBuffer;
                if (rsi.Result[index] < 30 && currentValue > lowestLow && currentValue - lowestLow < buffer && Positions.Count < 5 && highestHigh > spikeThreshold)
                {
                    ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.NormalizeVolumeInUnits(Symbol.LotSize), "Buy Order", 25, 200, null);
                    lowestLow = highestHigh;
                    calculateHighestHigh = true;
                }
                else if (Symbol.Ask < lowestLow)
                {
                    // double stopLossPrice = Symbol.Bid + (Symbol.Bid * stopLossPercentage / 100.0);
                    //  double takeProfitPrice = Symbol.Bid - (Symbol.Bid * takeProfitPercentage / 100.0);
                    // if(Symbol.Bid < lowestLow && dmi.ADX.IsFalling()&&Positions.Count == 0 ) {
                    // ExecuteMarketOrder(TradeType.Sell, SymbolName, Symbol.NormalizeVolumeInUnits(Symbol.LotSize), "Sell Order", 20, 20, null);
                    // }
                    // lowestLow = highestHigh;
                    //  calculateHighestHigh = true;
                }
            }
            distance = highestHigh - lowestLow;
        }
        private void ClosePosition(TradeResult position)
        {
            ClosePosition(position);
        }
        private void ClosePositions(TradeType tradeType)
        {
            foreach(var position in BotPositions)
            {
                if (position.TradeType != tradeType) continue;
                ClosePosition(position);
            }
        }
        private bool IsHigherTimeframeUptrend()
        {
            // Calculate moving averages on the higher timeframe
            double[] higherTimeframeFastMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Daily, 50);
            double[] higherTimeframeSlowMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Daily, 200);
            double[] higherTimeframe1FastMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Hour, 50);
            double[] higherTimeframe1SlowMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Hour, 200);
            double[] higherTimeframe2FastMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Minute15, 50);
            double[] higherTimeframe2SlowMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Minute15, 200);
            int lastIndex = Bars.ClosePrices.Count - 1;
            // Check if the slow MA on higher timeframe is below the fast MA, indicating a potential downtrend
            return higherTimeframe1SlowMASeries[lastIndex] < higherTimeframe1FastMASeries[lastIndex] && higherTimeframe2SlowMASeries[lastIndex] < higherTimeframe2FastMASeries[lastIndex] && higherTimeframeSlowMASeries[lastIndex] < higherTimeframeFastMASeries[lastIndex];
        }
        private bool IsPriceAboveWeeklySMAs()
        {
            // Calculate SMAs on the weekly chart
            double[] day200SMA = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Daily, 200);
            double[] hour200SMA = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Hour, 200);
            double[] min15200SMA = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Minute15, 200);
            int lastIndex = Bars.ClosePrices.Count - 1;
            double currentPrice = MarketSeries.Close[lastIndex];
            // Check if the current price is above all three SMAs
            return currentPrice > day200SMA[lastIndex] && currentPrice > hour200SMA[lastIndex] && currentPrice > min15200SMA[lastIndex];
        }
        private double[] CalculateSimpleMovingAverage(DataSeries source, TimeFrame timeframe, int period)
        {
            double[] smaValues = new double[source.Count];
            for (int i = 0; i < source.Count; i++)
            {
                if (i >= period - 1)
                {
                    double sum = 0;
                    for (int j = i - period + 1; j <= i; j++)
                    {
                        sum += source[j];
                    }
                    smaValues[i] = sum / period;
                }
                else
                {
                    smaValues[i] = source[i];
                }
            }
            return smaValues;
        }
    }
}