Information

Username: cAlgoForce
Member since: 15 Oct 2024
Last login: 18 Jan 2025
Status: Active

Activity

Where Created Comments
Algorithms 0 1
Forum Topics 0 0
Jobs 1 0

Last Algorithm Comments

CA
cAlgoForce · 5 days ago

A little closing gift for this forum:

using System.Linq;
using System.ComponentModel.DataAnnotations;
using cAlgo.API;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    public enum TradeDirections
    {
        [Display(Name = "Long Only")]
        LongOnly = 0,

        [Display(Name = "Short Only")]
        ShortOnly = 1,

        [Display(Name = "Both Long & Short")]
        Both = 2
    }

    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class JCSimpleGrid : Robot
    {
        [Parameter("Trade Direction", Group = "Basic Setup", DefaultValue = TradeDirections.Both)]
        public TradeDirections Direction { get; set; }

        [Parameter("First Order Volume", Group = "Basic Setup", DefaultValue = 1000, MinValue = 1, Step = 1)]
        public double InitialVolume { get; set; }

        [Parameter("Grid Size in Points", Group = "Basic Setup", DefaultValue = 200, MinValue = 10)]
        public int GridSizeInPoints { get; set; }

        [Parameter("Volume Multiplier", Group = "Basic Setup", DefaultValue = 1.0, MinValue = 0.01, Step = 0.01)]
        public double VolumeMultiplier { get; set; }

        // -------------------------
        // NEW PARAMETERS:
        // 1) EquityStopBelow:  if Equity <= this => stop
        // 2) EquityStopAbove:  if Equity >= this => stop
        // -------------------------
        [Parameter("Stop if Equity <= This Value", Group = "Risk Management", DefaultValue = 1000, MinValue = 1)]
        public double EquityStopBelow { get; set; }

        [Parameter("Stop if Equity >= This Value", Group = "Risk Management", DefaultValue = 100000, MinValue = 1)]
        public double EquityStopAbove { get; set; }

        private string thiscBotLabel;

        protected override void OnStart()
        {
            // Set position label to cBot name
            thiscBotLabel = GetType().Name;

            // Normalize the initial volume
            var normalizedVolume = Symbol.NormalizeVolumeInUnits(InitialVolume);
            if (InitialVolume != normalizedVolume)
            {
                InitialVolume = normalizedVolume;
                Print("Initial volume was adjusted to ", InitialVolume);
            }

            Print("JCSimpleGrid started. Equity Stop Below: ", EquityStopBelow, 
                  ", Equity Stop Above: ", EquityStopAbove);
        }

        protected override void OnTick()
        {
            // Check equity level for both thresholds
            if (Account.Equity <= EquityStopBelow)
            {
                Print("Equity (", Account.Equity, 
                      ") is BELOW or equal to the stop level (", EquityStopBelow, 
                      "). Closing positions and stopping cBot...");
                StopAndCloseAllTrades();
                return;
            }

            if (Account.Equity >= EquityStopAbove)
            {
                Print("Equity (", Account.Equity, 
                      ") is ABOVE or equal to the stop level (", EquityStopAbove, 
                      "). Closing positions and stopping cBot...");
                StopAndCloseAllTrades();
                return;
            }

            // ---------- BUY LOGIC ----------
            if (Direction == TradeDirections.LongOnly || Direction == TradeDirections.Both)
            {
                var buyPositions = Positions.FindAll(thiscBotLabel, SymbolName, TradeType.Buy);

                // If no buy positions yet, open the first one
                if (!buyPositions.Any())
                {
                    ExecuteMarketOrder(
                        TradeType.Buy,
                        SymbolName,
                        Symbol.NormalizeVolumeInUnits(InitialVolume),
                        thiscBotLabel,
                        null,
                        GridSizeInPoints * Symbol.TickSize / Symbol.PipSize
                    );
                }
                else
                {
                    // For subsequent buy positions, check grid condition
                    var lastBuyPosition = buyPositions.Last();
                    if (Symbol.Ask <= lastBuyPosition.EntryPrice - GridSizeInPoints * Symbol.TickSize)
                    {
                        var nextVolume = Symbol.NormalizeVolumeInUnits(
                            InitialVolume * (buyPositions.Length + 1) * VolumeMultiplier
                        );
                        ExecuteMarketOrder(
                            TradeType.Buy,
                            SymbolName,
                            nextVolume,
                            thiscBotLabel,
                            null,
                            GridSizeInPoints * Symbol.TickSize / Symbol.PipSize
                        );
                    }
                }
            }

            // ---------- SELL LOGIC ----------
            if (Direction == TradeDirections.ShortOnly || Direction == TradeDirections.Both)
            {
                var sellPositions = Positions.FindAll(thiscBotLabel, SymbolName, TradeType.Sell);

                // If no sell positions yet, open the first one
                if (!sellPositions.Any())
                {
                    ExecuteMarketOrder(
                        TradeType.Sell,
                        SymbolName,
                        Symbol.NormalizeVolumeInUnits(InitialVolume),
                        thiscBotLabel,
                        null,
                        GridSizeInPoints * Symbol.TickSize / Symbol.PipSize
                    );
                }
                else
                {
                    // For subsequent sell positions, check grid condition
                    var lastSellPosition = sellPositions.Last();
                    if (Symbol.Bid >= lastSellPosition.EntryPrice + GridSizeInPoints * Symbol.TickSize)
                    {
                        var nextVolume = Symbol.NormalizeVolumeInUnits(
                            InitialVolume * (sellPositions.Length + 1) * VolumeMultiplier
                        );
                        ExecuteMarketOrder(
                            TradeType.Sell,
                            SymbolName,
                            nextVolume,
                            thiscBotLabel,
                            null,
                            GridSizeInPoints * Symbol.TickSize / Symbol.PipSize
                        );
                    }
                }
            }
        }

        protected override void OnStop()
        {
            // Close all open positions for this cBot on stop during backtesting
            if (IsBacktesting)
            {
                foreach (var position in Positions)
                {
                    if (position.SymbolName == SymbolName && position.Label == thiscBotLabel)
                        ClosePosition(position);
                }
            }
        }

        private void StopAndCloseAllTrades()
        {
            // Close all positions in this account
            // If you only want to close cBot-specific trades, then
            // filter by (p => p.Label == thiscBotLabel).

            foreach (var position in Positions)
            {
                ClosePosition(position);
            }

            // Then stop the cBot
            Stop();
        }
    }
}