Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
7.2 kB
3
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
    {
        private TimeFrame higherTimeframe = TimeFrame.Weekly;
        private double higherTimeframeThreshold = 0.5;
        
        private double lotSize;

        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 = 10000;
        private double minProfitForTrailing = 10000; // Minimum profit in pips before trailing stop becomes active
        private RelativeStrengthIndex rsi;

        private double _volumeInUnits;
        private AverageDirectionalMovementIndexRating _averageDirectionalMovementIndexRating;
        
        [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;
         
        public Position[] BotPositions {
             get
             {
                 return Positions.FindAll(Label);
             }
        }
             
        protected override void OnStart() {   

            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(25);
             lowestLow = MarketSeries.Low.Minimum(lookbackPeriod);
             highestHigh = MarketSeries.High.Maximum(lookbackPeriod);
        }
        
        protected override void OnBar() { 
            if(calculateHighestHigh == true) {
             highestHigh = MarketSeries.High.Maximum(lookbackPeriod);
             calculateHighestHigh = false;  
            }
            
            if(Symbol.Bid < lowestLow){
                highestHigh = lowestLow;
                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);
            }
            
            if (Bars.OpenTimes.LastValue > lastBarTime) {
                lastBarTime = Bars.OpenTimes.LastValue;
                
                int index = Bars.ClosePrices.Count - 2; // Index of the last closed bar
                bool isHigherTimeframeUptrend = IsHigherTimeframeUptrend(); 
                
                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(!isHigherTimeframeUptrend && Positions.Count > 0)
                    {
                        ClosePosition(position);
                        Chart.RemoveAllObjects();
                    }
                }
                   
                if(Symbol.Bid < highestHigh) 
                   Chart.DrawHorizontalLine("support line", lowestLow, Color.White, 1, LineStyle.LinesDots);
                   Chart.DrawHorizontalLine("resistance line", highestHigh, Color.Gold, 1, LineStyle.LinesDots);
                  
                   if(Symbol.Bid > highestHigh && fastMA.Result.HasCrossedAbove(slowMA.Result, index)&& isHigherTimeframeUptrend) {
                   ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.NormalizeVolumeInUnits(Symbol.LotSize), "Buy Order", 20000, 20000, null );
                   lowestLow = highestHigh;
                   calculateHighestHigh = true;
                 }  
           }
        }

    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, higherTimeframe, 50);
    double[] higherTimeframeSlowMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, higherTimeframe, 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 higherTimeframeSlowMASeries[lastIndex] < higherTimeframeFastMASeries[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;
    }  
  }
}