Replies

sue.bugg
19 Jun 2023, 12:52

RE: RE: RE:

pick said:

sue.bugg said:

pick said:

The first "obvious" issue I see in that code is that in "CanTradeBuyDaily", "CanTradeBuyFourHour", "CanTradeBuyHourly" and "CanTradeBuyFiveMinute" you're using "_close" for comparisons - which, at a quick glance, looks like it is always equal to the timeframe on which the bot is loaded. I see you've loaded the bars for the relevant timeframe for each method, but you're not using those bars? 

Yes, I am thinking that is the issue also, but when you say I’m not using the bars, that is the problem. I don’t know how to use them. When I do the following, (put them in the right section and repeat for 4hour & 1hour), I believe I’m just changing the name from _close to _closeDaily. I’m missing something to connect _closeDaily to the actual Daily bars

private DataSeries _closeDaily;

_closeDaily = Bars.ClosePrices;

if (_closeDaily.Last(1) > _ichimokuKinkoHyoDaily.SenkouSpanA.Last(27)

&& _closeDaily.Last(1) > _ichimokuKinkoHyoDaily.SenkouSpanB.Last(27)

 

If I use Ichimoku as example… In the bracket, the standard to put in is 9,26,52… But it accepted _dailyBars as additional entry. Which I think is what’s connecting it to the bars. The following works for Ichimoku

_ichimokuKinkoHyoDaily = Indicators.IchimokuKinkoHyo(_dailyBars,9, 26, 52);

 

If I do the following for the Close, it errors out and says “non invocable member, cannot be used like a method”

_closeDaily = Bars.ClosePrices(_dailyBars);

Basically, I don’t know how to connect the _closeDaily to the bars. Do you know what I’m missing?

Thankyou

Have you tried using the bars you've already loaded like this?

private bool CanTradeBuyHourly(BuyMethod method)
{
	if (_hourlyBars.ClosePrices.Last(1) > _ichimokuKinkoHyoHourly.SenkouSpanA.Last(27)
		&& _hourlyBars.ClosePrices.Last(1) > _ichimokuKinkoHyoHourly.SenkouSpanB.Last(27))
		return true;
	else
		return false;
}

You are an absolute champion. Thankyou so much. This appears to have worked. Incorrect trades have disappeared. I will test more thoroughly. But looking very good so far. Thanks again. Totally appreciate your help. 


@sue.bugg

sue.bugg
19 Jun 2023, 12:27

RE:

pick said:

The first "obvious" issue I see in that code is that in "CanTradeBuyDaily", "CanTradeBuyFourHour", "CanTradeBuyHourly" and "CanTradeBuyFiveMinute" you're using "_close" for comparisons - which, at a quick glance, looks like it is always equal to the timeframe on which the bot is loaded. I see you've loaded the bars for the relevant timeframe for each method, but you're not using those bars? 

Yes, I am thinking that is the issue also, but when you say I’m not using the bars, that is the problem. I don’t know how to use them. When I do the following, (put them in the right section and repeat for 4hour & 1hour), I believe I’m just changing the name from _close to _closeDaily. I’m missing something to connect _closeDaily to the actual Daily bars

private DataSeries _closeDaily;

_closeDaily = Bars.ClosePrices;

if (_closeDaily.Last(1) > _ichimokuKinkoHyoDaily.SenkouSpanA.Last(27)

&& _closeDaily.Last(1) > _ichimokuKinkoHyoDaily.SenkouSpanB.Last(27)

 

If I use Ichimoku as example… In the bracket, the standard to put in is 9,26,52… But it accepted _dailyBars as additional entry. Which I think is what’s connecting it to the bars. The following works for Ichimoku

_ichimokuKinkoHyoDaily = Indicators.IchimokuKinkoHyo(_dailyBars,9, 26, 52);

 

If I do the following for the Close, it errors out and says “non invocable member, cannot be used like a method”

_closeDaily = Bars.ClosePrices(_dailyBars);

Basically, I don’t know how to connect the _closeDaily to the bars. Do you know what I’m missing?

Thankyou


@sue.bugg

sue.bugg
19 Jun 2023, 09:57 ( Updated at: 19 Jun 2023, 10:06 )

RE: full code

Hi PanagiotisChar

My apologies, I didn't think you would require full code. I was thinking the error was in the section I posted. Please see below full code. I hope you can help

Thanks

 

using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using System;
using System.Linq;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class OriginalPAandMultiTimeFrameBuy : Robot
    {
        #region Parameters

        [Parameter()]
        public DataSeries SourceSeries { get; set; }

        [Parameter("Risk Per Trade (%)", DefaultValue = 0.2, Step = 0.1, Group = "Risk Management")]
        public double RiskPerTrade { get; set; }

        [Parameter("Spread", DefaultValue = 1.0, Group = "Risk Management")]
        public double Spread { get; set; }

        [Parameter("Take Profit", DefaultValue = 3.1, Group = "Risk Management")]
        public double TP { get; set; }

        [Parameter("Max Open Trades", DefaultValue = 1, Group = "Risk Management")]
        public int MaxOpenTrades { get; set; }

        [Parameter("Operation Type", Group = "Risk Management")]
        public OperationType OpType { get; set; }

        [Parameter("ATR Periods", DefaultValue = 12, Group = "ATR")]
        public int ATRPeriods { get; set; }

        [Parameter("ATR Multiplier", DefaultValue = 1.5, Step = 0.1, Group = "ATR")]
        public double ATRMultiplier { get; set; }

        [Parameter("ATR MA Type", Group = "ATR")]
        public MovingAverageType MAType { get; set; }

        [Parameter("Fast EMA", DefaultValue = 9, Group = "EMA")]
        public int FastEMAPeriod { get; set; }

        [Parameter("Slow EMA", DefaultValue = 21, Group = "EMA")]
        public int SlowEMAPeriod { get; set; }

        [Parameter("Use Trading Time", Group = "Trading Time")]
        public bool UseTradingTime { get; set; }

        [Parameter("Start Time", DefaultValue = "09:55", Group = "Trading Time")]
        public string StartTime { get; set; }

        [Parameter("Stop Time", DefaultValue = "21:05", Group = "Trading Time")]
        public string StopTime { get; set; }

        [Parameter("Timezone", Group = "Trading Time")]
        public Timezone UserTimeZone { get; set; }

        [Parameter("Email Address", Group = "Notifications")]
        public string EmailAddress { get; set; }

        [Parameter("Instance", DefaultValue = "MTF PartialWorking 5")]
        public string Instance { get; set; }

        #endregion Parameters

        #region Private Variables

        private AverageTrueRange _atr;
        private bool _tradeTriggered;
        private DataSeries _high, _low, _open, _close;
        private IchimokuKinkoHyo _ichimokuKinkoHyoDaily;
        private IchimokuKinkoHyo _ichimokuKinkoHyoFourH;
        private IchimokuKinkoHyo _ichimokuKinkoHyoHourly;
        private IchimokuKinkoHyo _ichimokuKinkoHyoFiveM;
        private ExponentialMovingAverage _fastEMADaily, _slowEMADaily;
        

        #endregion Private Variables

        #region Public Variables

        public enum OperationType
        {
            Alert,
            Trade,
            Both
        }

        public enum Timezone
        {
            UTC10,
            UTC11
        }

        public enum BuyMethod
        {
            Traditional,
            NonTraditional,
            Both
        }

        #endregion Public Variables

        #region Private Variables
        Bars _dailyBars;
        Bars _h4Bars;
        Bars _hourlyBars;
        Bars _m5Bars;
        #endregion

        protected override void OnStart()
        {
            // Put your initialization logic here
            _dailyBars = MarketData.GetBars(TimeFrame.Daily);
            _h4Bars = MarketData.GetBars(TimeFrame.Hour4);
            _hourlyBars = MarketData.GetBars(TimeFrame.Hour);
            _m5Bars = MarketData.GetBars(TimeFrame.Minute5);
            _atr = Indicators.AverageTrueRange(ATRPeriods, MAType);
            _high = Bars.HighPrices;
            _low = Bars.LowPrices;
            _open = Bars.OpenPrices;
            _close = Bars.ClosePrices;
            _ichimokuKinkoHyoDaily = Indicators.IchimokuKinkoHyo(_dailyBars,9, 26, 52);
            _ichimokuKinkoHyoFourH = Indicators.IchimokuKinkoHyo(_h4Bars,9, 26, 52);
            _ichimokuKinkoHyoHourly = Indicators.IchimokuKinkoHyo(_hourlyBars,9, 26, 52);
            _ichimokuKinkoHyoFiveM = Indicators.IchimokuKinkoHyo(_m5Bars,9, 26, 52);
            _fastEMADaily = Indicators.ExponentialMovingAverage(SourceSeries, FastEMAPeriod);
            _slowEMADaily = Indicators.ExponentialMovingAverage(SourceSeries, SlowEMAPeriod);

        }

        protected override void OnBar()
        {
            _tradeTriggered = false;
            if (RunningMode != RunningMode.Optimization)
                Chart.RemoveAllObjects();

            if (Positions.Count(x => x.Label == Instance) < MaxOpenTrades)
            {
                if (CanTradeBuyDaily(BuyMethod.Traditional) && CanTradeBuyFourHour(BuyMethod.Traditional) && CanTradeBuyHourly(BuyMethod.Traditional) && CanTradeBuyFiveMinute(BuyMethod.Traditional))
                {
                    if (!_tradeTriggered)
                        Print("BUY " + Symbol.Name);
                    if (!_tradeTriggered && (OpType == OperationType.Trade || OpType == OperationType.Both) && !ShutDown())
                    {
                        // Stop Loss based on ATR x #. Eg. ATR x 1.0, ATR x 1.5, ATR x 2.0, with ability for user to change
                        // Stop Loss = plus spread, with ability for user to change spread
                        // Stop Loss = round Up
                        // Stop Loss = ATR say 15, x 1.5 = 22.5, plus spread say 0.7 = 23.2, Round Up = 24 pip SL

                        var sl = Math.Ceiling((_atr.Result.Last(1) * ATRMultiplier / Symbol.PipSize) + Spread);

                        // Stop Loss based on ATR x #. Eg. ATR x 1.0, ATR x 1.5, ATR x 2.0, with ability for user to change
                        // Stop Loss = plus spread, with ability for user to change spread
                        // Stop Loss = round Up
                        // Stop Loss = ATR say 15, x 1.5 = 22.5, plus spread say 0.7 = 23.2, Round Up = 24 pip SL
                        // Stop(); stops the cBot from trading any further once a trade has entered

                        var tp = Math.Floor((sl * TP) - Spread);
                        var volume = GetVolume(sl);
                        ExecuteMarketOrder(TradeType.Buy, Symbol.Name, volume, Instance, sl, tp);
                        // Stop();
                    }

                    if (OpType == OperationType.Alert || OpType == OperationType.Both)
                    {
                        if (!IsBacktesting && !_tradeTriggered)
                        {
                            string message = string.Empty;
                            string nl = "\n";

                            message += "Symbol: " + Symbol.Name + nl;
                            message += "Time: " + Server.Time.ToShortTimeString() + nl;
                            message += "Price: " + this.Symbol.Bid.ToString() + nl;
                            message += "Signal: Buy" + nl;

                            Notifications.SendEmail(EmailAddress, EmailAddress, "BUY " + Symbol.Name, message);
                        }
                        if (RunningMode != RunningMode.Optimization)
                        {
                            Chart.DrawStaticText("Buy Text", "Buy", VerticalAlignment.Center, HorizontalAlignment.Center, Color.Green);
                            Chart.DrawVerticalLine("Buy", Bars.OpenTimes.Last(1), Color.Green);
                        }
                    }
                    _tradeTriggered = true;
                }
            }
        }
        private bool BuyPriceAction(BuyMethod method, Bars bars)
        {
            // Check the relevant method 
            switch (method)
            {
                case BuyMethod.Traditional:
                    return BuyTraditional(bars);
                case BuyMethod.NonTraditional:
                    return BuyNonTraditional(bars);
                case BuyMethod.Both:
                    return BuyBoth(bars);
            }

            return false;
        }

        private bool CanTradeBuyDaily(BuyMethod method)
        {

            // Get the daily timeframe bars
               var bars = MarketData.GetBars(TimeFrame.Daily);
                    

            // Check the relevant indicator conditions 
            if (_close.Last(1) > _ichimokuKinkoHyoDaily.SenkouSpanA.Last(27)
                && _close.Last(1) > _ichimokuKinkoHyoDaily.SenkouSpanB.Last(27)
                && _fastEMADaily.Result.Last(1) > _slowEMADaily.Result.Last(1))
                return true;
            else
                return false;
        }

        private bool CanTradeBuyFourHour(BuyMethod method)
        {

            // Get the 4 hour timeframe bars
            var bars = MarketData.GetBars(TimeFrame.Hour4);

            // Check the relevant indicator conditions 


            if (_close.Last(1) > _ichimokuKinkoHyoFourH.SenkouSpanA.Last(27)
                && _close.Last(1) > _ichimokuKinkoHyoFourH.SenkouSpanB.Last(27))
                return true;
            else
                return false;
        }
        private bool CanTradeBuyHourly(BuyMethod method)
        {

            // Get the hourly timeframe bars
            var bars = MarketData.GetBars(TimeFrame.Hour);

            // Check the relevant indicator conditions 
            

            if (_close.Last(1) > _ichimokuKinkoHyoHourly.SenkouSpanA.Last(27)
                && _close.Last(1) > _ichimokuKinkoHyoHourly.SenkouSpanB.Last(27))
                return true;
            else
                return false;
        }

        private bool CanTradeBuyFiveMinute(BuyMethod method)
        {

            // Get the minute timeframe bars
            var bars = MarketData.GetBars(TimeFrame.Minute5);

            // Check the relevant indicator conditions 
            if (!(_close.Last(1) > _ichimokuKinkoHyoFiveM.SenkouSpanA.Last(27)
                && _close.Last(1) > _ichimokuKinkoHyoFiveM.SenkouSpanB.Last(27)))
                return false;

            return BuyPriceAction(method, bars);
        }

        private bool BuyBoth(Bars bars)
        {

            if (BuyTraditional(bars))
                return true;

            if (BuyNonTraditional(bars))
                return true;

            return false;
        }

        private bool BuyNonTraditional(Bars bars)
        {
            if (bars.HighPrices.Last(2) > bars.HighPrices.Last(1) && bars.LowPrices.Last(2) < bars.LowPrices.Last(1) && bars.OpenPrices.Last(2) < bars.ClosePrices.Last(2) && bars.OpenPrices.Last(1) < bars.ClosePrices.Last(1))
                return true;

            if (bars.HighPrices.Last(2) < bars.HighPrices.Last(1) && bars.LowPrices.Last(2) > bars.LowPrices.Last(1) && bars.OpenPrices.Last(2) > bars.ClosePrices.Last(2) && bars.OpenPrices.Last(1) < bars.ClosePrices.Last(1))
                return true;

            if (bars.HighPrices.Last(3) > bars.HighPrices.Last(2) && bars.LowPrices.Last(3) > bars.LowPrices.Last(2) && bars.HighPrices.Last(1) > bars.HighPrices.Last(2) && bars.LowPrices.Last(1) > bars.LowPrices.Last(2) && bars.OpenPrices.Last(1) < bars.ClosePrices.Last(1))
                return true;

            return false;
        }

        private bool BuyTraditional(Bars bars)
        {

            if (bars.HighPrices.Last(2) > bars.HighPrices.Last(1) && bars.LowPrices.Last(2) < bars.LowPrices.Last(1) && bars.OpenPrices.Last(2) > bars.ClosePrices.Last(2) && bars.OpenPrices.Last(1) < bars.ClosePrices.Last(1))
                return true;

            if (bars.HighPrices.Last(2) < bars.HighPrices.Last(1) && bars.LowPrices.Last(2) > bars.LowPrices.Last(1) && bars.OpenPrices.Last(2) > bars.ClosePrices.Last(2) && bars.OpenPrices.Last(1) < bars.ClosePrices.Last(1))
                return true;

            return false;
        }

        protected override void OnTick()
        {
        }

        private double GetVolume(double pips)
        {
            // The volume is calculated based on the expected net loss if all SL levels trigger.
            var maxAmountRisked = Account.Balance * (RiskPerTrade / 100);
            return Symbol.NormalizeVolumeInUnits(maxAmountRisked / (pips * Symbol.PipValue), RoundingMode.Down);
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }

        private bool ShutDown()
        {
            TimeSpan tradingStarts;
            TimeSpan tradingStops;

            tradingStarts = TimeSpan.ParseExact(StartTime, "hh\\:mm", null);
            tradingStops = TimeSpan.ParseExact(StopTime, "hh\\:mm", null);

            var time = UserTimeZone == Timezone.UTC10 ? Server.Time.AddHours(10) : Server.Time.AddHours(11);
            if (tradingStarts < tradingStops)
            {
                if (time.TimeOfDay >= tradingStarts && time.TimeOfDay < tradingStops)
                {
                    //Print("cBot is shut down");
                    return false;
                }
            }
            else
            {
                if (!(time.TimeOfDay <= tradingStarts && time.TimeOfDay > tradingStops))
                {
                    //Print("cBot is shut down");
                    return false;
                }
            }

            return UseTradingTime;
        }
    }
}

 


@sue.bugg

sue.bugg
21 Jan 2022, 07:50

No need to respond, I've figured it out


@sue.bugg

sue.bugg
03 Jan 2022, 10:36

RE: RE: Was anything done about this

amusleh said:

sue.bugg said:

Hi, was anythng ever done about this? I want my 1HR cBot to start a 5min cBot with specific instance name.

Eg AUDUSD 1 HR chart has cBot running. If all logic in this is met, I don't want it to trade, but I want it start the AUDUSD cBot on the 5 min chart. Say it's instance name is "S1AU"

Can this now be done? 

Thanks

Sue

Hi,

Why you need such a feature? I don't get this at all.

Can't you put the logic of your 5 min cBot inside your 1h cBot? If conditions met in your 1h cBot then it will execute the logic of 5 min cBot.

Why you want to make it more complicated?

You can access different time frames data inside a single cBot/indicator instance, you don't have to run multiple instances to get multiple time frames data.

You can also access other symbols data, not just the current symbol other time frames data.

Hi Amusleh

I'm not meaning to complicate things, I just have very limited knowledge of coding. My 1HR logic is different to the 5min logic. I'll look into it and see if I can figure out how to use multiple timeframes

Thanks, Sue


@sue.bugg

sue.bugg
01 Jan 2022, 01:27

Was anything done about this

Hi, was anythng ever done about this? I want my 1HR cBot to start a 5min cBot with specific instance name.

Eg AUDUSD 1 HR chart has cBot running. If all logic in this is met, I don't want it to trade, but I want it start the AUDUSD cBot on the 5 min chart. Say it's instance name is "S1AU"

Can this now be done? 

Thanks

Sue


@sue.bugg

sue.bugg
03 Dec 2021, 04:56

RE:

PanagiotisCharalampous said:

Hi Sue,

Are you just looking for the Stop() method?

Best Regards,

Panagiotis 

Join us on Telegram and Facebook

Hi Panagiotis

Thank you. I had a brief look last night, looks like what I need. I'll see if I can figure out how & where it should go in the code. Very limited knowledge, so not sure I'll be able to do it

Thanks

Sue


@sue.bugg

sue.bugg
02 Dec 2021, 03:49 ( Updated at: 05 Dec 2021, 02:09 )

RE: RE: RE:

amusleh said:

sue.bugg said:

amusleh said:

Hi,

You can limit the number of orders your cBot opens programmatically, there are lots of different ways you can do such a thing with code.

Use Positions opened/closed events and when a position got opened by your cBot you can put your cBot on a sleep mode by using a boolean flag until the position is closed.

Hi Amusleh

Thank you for the information. The cBot already goes to sleep once a position is opened. It awakens once the position is closed, if still in the trading time frame. Most losses occur much quicker than a profit. If it closes in a Loss before the 1.5 hours is up (the set trading times), it will take another trade if triggered (all parameters of cBot met). I don't want it to take another trade. Just one trade per asset in total for the trading period. So, once a postion is opened, I want it to go to sleep, turn off, stop completely until I manually turn it back on again the next trading day. Does that make sense?

Thanks

Sue

Hi,

You can code this behavior easily, you can limit your cBot to not open more than one trade during specific time period.

If you know how to code then you can do it easily, otherwise you can post your cBot code and I will help or you can post a job request or ask our consultants to do it for you.

 



            

 


@sue.bugg

sue.bugg
01 Dec 2021, 10:10

RE:

amusleh said:

Hi,

You can limit the number of orders your cBot opens programmatically, there are lots of different ways you can do such a thing with code.

Use Positions opened/closed events and when a position got opened by your cBot you can put your cBot on a sleep mode by using a boolean flag until the position is closed.

Hi Amusleh

Thank you for the information. The cBot already goes to sleep once a position is opened. It awakens once the position is closed, if still in the trading time frame. Most losses occur much quicker than a profit. If it closes in a Loss before the 1.5 hours is up (the set trading times), it will take another trade if triggered (all parameters of cBot met). I don't want it to take another trade. Just one trade per asset in total for the trading period. So, once a postion is opened, I want it to go to sleep, turn off, stop completely until I manually turn it back on again the next trading day. Does that make sense?

Thanks

Sue


@sue.bugg

sue.bugg
14 Aug 2021, 07:56

I figured it out, no need to reply, thanks


@sue.bugg

sue.bugg
10 Apr 2021, 02:22

Thank you Panagiotis. That might explain the amazing results, there are probably multiple trades that didn't close. I had re run another Optimize and didn't record results, so can't check, but at least know what to look for if it happens again. Do you know why a trade or trades would not close if I have clear stop loss rules in the cBot? I had asked another question previously about the fixed spread in Opt & Back test v's live trade. All my cBots are On Bar (not tick). Based on response, I included the fixed spread in Opt. Could this have anything to do with it?

Thanks

Sue


@sue.bugg

sue.bugg
08 Mar 2021, 08:42

Novice

I'm a novice, so can't give you the actual code and forgive me if I'm completely wrong & of no help to you.

I can't see anything in your code to reflect the open & close prices of the candle. I THINK I can only see you referencing the VWAP

You would have to declare variables. Bars open prices, bars close prices

Then do the math. If open is less than close = Buy. If open is more than close = Sell

Hope this helps in some way & apologies if the info is useless.


@sue.bugg