Untitled

mail@pastecode.io avatarunknown
plain_text
a month ago
6.3 kB
1
Indexable
Never
using cAlgo.API;
using cAlgo.API.Indicators;
using System;
using System.Collections.Generic;


namespace MovingAverageCrossoverBot
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class MovingAverageCrossoverBot : Robot
    {
        private TimeFrame higherTimeframe = TimeFrame.Daily; // Define the higher timeframe
        private double higherTimeframeThreshold = 0.5;
        
        private double desiredTradeVolume = 10000.0; // Desired trade volume in base currency units (e.g., for EURUSD)
        private double lotSize;

        private MovingAverage fastMA;
        private MovingAverage slowMA;
        private DateTime lastBarTime;
        
        private RelativeStrengthIndex rsi;
        
        private double riskPercentage = 2.0;
     
        private TradeResult  openBuyPosition = null;
        private TradeResult  openSellPosition = null;

        protected override void OnStart()
        {   
        
             int rsiPeriod = 14; // Period for RSI calculation
             rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, rsiPeriod);
      
            // Configure your symbols and timeframes
           // TimeFrame timeframe = TimeFrame.HeikinHour;

            // Configure your moving average periods
            int fastMAPeriod = 50;
            int slowMAPeriod = 200;

            // Initialize moving averages
            fastMA = Indicators.MovingAverage(Bars.ClosePrices, fastMAPeriod, MovingAverageType.Simple);
            slowMA = Indicators.MovingAverage(Bars.ClosePrices, slowMAPeriod, MovingAverageType.Simple);

            lastBarTime = Bars.OpenTimes.LastValue;
            
            lotSize = Symbol.NormalizeVolumeInUnits(desiredTradeVolume);
        }

        protected override void OnTick()
        {
        if(Positions.Count == 0)
        {
        openBuyPosition = null;
        openSellPosition = null;

        }
   
            // Check if a new bar has formed
            if (Bars.OpenTimes.LastValue > lastBarTime)
            {
                lastBarTime = Bars.OpenTimes.LastValue;
                
                int index = Bars.ClosePrices.Count - 1; // Index of the last closed bar
                  
               
                if (CrossesOnMultipleTimeframes() && fastMA.Result.HasCrossedAbove(slowMA.Result, index)&& openBuyPosition == null)
                {
                
                    openBuyPosition = ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.NormalizeVolumeInUnits(Symbol.LotSize), "Buy Order", 30, 10, null );

                }
                
               if (CrossesOnMultipleTimeframesForSell() &&fastMA.Result.HasCrossedBelow(slowMA.Result, index)&& openSellPosition == null)
                {
                   
                     openSellPosition = ExecuteMarketOrder(TradeType.Sell, SymbolName, lotSize, "Sell Order", 30, 10, null);
                }
            }
        }
      
        private void ClosePosition(TradeResult  position)
        {
            ClosePosition(position);
        }
    
        
         private bool CrossesOnMultipleTimeframes()
        {
            bool crossesOnFast = fastMA.Result.HasCrossedAbove(slowMA.Result, Bars.ClosePrices.Count - 1);
            bool crossesOnHigherTimeframe = CrossesOnTimeframe(higherTimeframe);

            // Confirm the signal by checking if both timeframes have a crossover
            return crossesOnFast && crossesOnHigherTimeframe;
        }

      private bool CrossesOnTimeframe(TimeFrame timeframe)
        {
            // Calculate moving averages on the specified timeframe manually
           double[] fastMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, 50);
         double[] slowMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, 200);

            int lastIndex = Bars.ClosePrices.Count - 1;

            bool crossesAbove = fastMASeries[lastIndex] > slowMASeries[lastIndex] && fastMASeries[lastIndex - 1] <= slowMASeries[lastIndex - 1];
            bool crossesBelow = fastMASeries[lastIndex] < slowMASeries[lastIndex] && fastMASeries[lastIndex - 1] >= slowMASeries[lastIndex - 1];

            // Use a threshold to confirm the crossover
            return crossesAbove && fastMASeries[lastIndex] > higherTimeframeThreshold ||
                   crossesBelow && fastMASeries[lastIndex] < 1 - higherTimeframeThreshold;
        }
        private bool CrossesOnMultipleTimeframesForSell()
{
    bool crossesOnFast = fastMA.Result.HasCrossedBelow(slowMA.Result, Bars.ClosePrices.Count - 1);
    bool crossesOnHigherTimeframe = CrossesOnTimeframeForSell(higherTimeframe);

    // Confirm the signal by checking if both timeframes have a crossover
    return crossesOnFast && crossesOnHigherTimeframe;
}

private bool CrossesOnTimeframeForSell(TimeFrame timeframe)
{
    // Calculate moving averages on the specified timeframe manually
    double[] fastMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, 50);
         double[] slowMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, 200);
    int lastIndex = Bars.ClosePrices.Count - 1;

    bool crossesAbove = fastMASeries[lastIndex] < slowMASeries[lastIndex] && fastMASeries[lastIndex - 1] >= slowMASeries[lastIndex - 1];
    bool crossesBelow = fastMASeries[lastIndex] > slowMASeries[lastIndex] && fastMASeries[lastIndex - 1] <= slowMASeries[lastIndex - 1];

    // Use a threshold to confirm the crossover
    return crossesAbove && fastMASeries[lastIndex] < 1 - higherTimeframeThreshold ||
           crossesBelow && fastMASeries[lastIndex] > higherTimeframeThreshold;
}

private double[] CalculateSimpleMovingAverage(DataSeries source, 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;
}
       
    }
}