Topics
14 Mar 2021, 17:53
 1806
 17
19 Jan 2021, 18:33
 1004
 4
Replies

prosteel1
15 Mar 2021, 20:19 ( Updated at: 15 Mar 2021, 21:28 )

RE: RE:

amusleh said:

rsoudani said:

Hi, i'm working on my own strategy, looks good on demo account and on firts live tests, but i can not backtest it because i need low spreads, and i have raw spread account on icmarkets, but for backtesting in cTrader i can only get tickdata from server where i cant choose spread and it seems to be much to high (i need tick data not bar data). Do you have any suggestions?

Hi,

The tick data is from your broker price feed, you can try other brokers cTrader for backtesting and using their tick data. 

Are you running your bot using OnTick() as opposed to OnBar()? Running OnBar() instread of OnTick() might result in what you are describing.

Most cBots have 3 main methods:

OnStart()

OnTick()

OnStop()

Do you have these? Or do you have..

OnStart()

OnBar()

OnStop()

I use a condition to check if the channel height (ChHt) is large enough compared to the spread: (ChHt > 2 * (Symbol.Ask - Symbol.Bid))

This eliminates charts during high spread events like on the market open in order to ensure there is a small of risk to return. I also keep track of the channel height of successful trades during a backtest and store the highest value which is also as a check to eliminate big gaps creating huge charts that block trades. I run a backtest once to get the highest successful chart height and then run it a second time so that huge charts resulting from gaps are eliminated the second time I do a backtest.

I love ICMarkets data fyi.  From what I have seen it looks like the live spread when using the backtesting setting > Data > 'Tick data from server (accurate') does provide accurate spread, but I haven't verified it. I use the above methods to eliminate high spreads so I don't trade them.

There might be other methods to eliminating trading during high spreads, these are what I use.

Are you consistantly using Symbol.Bid and Symbol.Ask instead of LastBar.High or whatever the old crew use now days. When you are targeting spread as a metric and running OnTick, Symbol.Bid and Symbol.Ask is where it needs to be to use the tick data and thus get the accurate spread. I struggled with this for a while too.

^While I say consistantly reference Symbol.Bid and Symbol.Ask, I do use HighPrices and LowPrices etc for analysis, but then switch to Symbol.Bid and Symbol.Ask for updating OnTick() - this ensures that I am using the latest data for updates while using aggregated data for analysis.

I hope this helps, feel free to ask further questions :)


@prosteel1

prosteel1
15 Mar 2021, 19:30 ( Updated at: 21 Dec 2023, 09:22 )

I note that the name of the Tick1 frame was recently changed from Tick1 to Tick. When I set my chart frame to Tick1 and try to set the backtesting setting > Data to t1 bars it shows as red meaning an error, but when I set it to "Tick data from Server (accurate)", it does not show as red but is technically the same data (I assume). The same red error occurs in 3.8 currently but I never tested this before the name of Tick1 was changed to Tick. In the past few weeks I have needed to change the name of Tick1 to Tick - so perhaps this change in the naming convention could be resulting in these multiple errors, and a similar issue within the backtesting dialog? 

Since I needed to change my code to reflect the new naming convention, it would seem plausible that an obsolete reference may still exist in the ctrader code resulting in these multitude of errors.

The main thing I have changed in my code recently is I am writing lots of data to a .csv but I have a quite low buffer before writing it (5000) lines and doesn't seem to effect the memory usage.


@prosteel1

prosteel1
15 Mar 2021, 18:00 ( Updated at: 15 Mar 2021, 18:35 )

This is a strange error. I am narrowing it down. I can run backtests on normal timeframes like from Monthly to Minute. Once I get into Tick frames I get errors like "Failed to load conversion rates" and a similar error to above #62080512 and system out of memory. However I'm not convinced these other errors are memory errors as I have installed the clickalgo memory manager and it didn't prevent the errors which isn't consistant with my previous results of it successfully preventing out of memory errors and task manager shows there was free ram (even though I am running on 4GB on 32bit).

I'll update when I have more info. What does "Failed to load conversion rates" mean?  I found this thread using a search which suggests it couldn't get the exchange rate when the bot started -

, and this crash occured at the start on the bot. The other crash errors occured during the bot running after about 2.5 years. Tick data goes back to 11/11/2012 and these #62082701 & #62080512 crashes occur around 03/02/2015 but seem to change.


@prosteel1

prosteel1
12 Mar 2021, 11:22 ( Updated at: 12 Mar 2021, 23:19 )

RE:

Hi I have some code to get you started. This closes 20% of the position if the profit is more than 2%, probably just use the GrossProfit based on your strategy with some extra variables to check if you have already taken profit. Hope this helps.

// Take profit if profit is high
if (LongTradeAggressiveProfitTaking == true && (double)pos.GrossProfit >= (Account.Balance * 0.02))
{
    if (pos.VolumeInUnits >= 2000)
    {
        double newVol = Symbol.NormalizeVolumeInUnits((pos.VolumeInUnits / 5), RoundingMode.Up);
        Print("1 pos.Profit = " + pos.GrossProfit + ", Account.Balance = " + Account.Balance + ", " + Math.Round((Account.Balance * 0.02), 2) + ", closing " + newVol + " of " + pos.VolumeInUnits);
        ClosePosition(pos, newVol);
    }
}

 


@prosteel1

prosteel1
12 Mar 2021, 11:08

RE:

PanagiotisCharalampous said:

Hi prosteel1,

No it cannot be standardized since each broker can choose their own symbol names

Best Regards,

Panagiotis 

Join us on Telegram .

Thanks for your reply, I used some code to remove the forward slash from 

DataDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + "\\Documents\\cAlgo\\Sources\\Robots\\" + ToString() + "\\" + ToString();
string symbolname = String.Join("", Symbol.Name.Split('/'));
PathMLActionSec = DataDir + "\\MLActionSec-" + symbolname + ".csv";
File.CreateText(PathMLActionSec);

Seems to work by removing the / from the Symbol.Name


@prosteel1

prosteel1
26 Feb 2021, 17:22 ( Updated at: 26 Feb 2021, 17:53 )

RE: RE:

I think the genius part was using the web server as that gets around the .Net limitations. I suspect it is the web server that is slowing it down. What I really like about this is it is a workaround that actually works whereas every other post about using ML in cTrader I have not been able to get to work.

This works and so allows us to test ML before the upcoming .NET Core upgrade.

I'm looking more to XGBoost methods like Numer.ai are using rather than ML.Net tbh. XGBoost seems to be the state of the art atm.

Lex Fridman interviews Numer.ai founder Richard Craib 

 


@prosteel1

prosteel1
24 Feb 2021, 17:55

You could probably write files with the parameters as the name, haven't tried it yet but makes sense.


@prosteel1

prosteel1
24 Feb 2021, 17:41

RE: RE:

Does 

 have what your looking for? 


@prosteel1

prosteel1
24 Feb 2021, 17:03 ( Updated at: 21 Dec 2023, 09:22 )

RE:

tekASH said:

Hi guys

I need working insight on following issues:

 

1. How to show/tell the system in the code: market being over a particular Moving Average? Like, price/overall market has crossed over a MA at some point and it is still there.

This is useful for entering short when market is below a MA, and buy only when over the MA. What methods can be used?

2. When I tell the system to buy only if price is over a MA, it keeps opening buy positions repeatedly (after previous position is closed) as long as the price is still over that MA :) But I need one entry, only first, cause keeping buying multiple positions is risky. How to fix this? 

Few issues there, lets address the constant opening of buys first: I wrap my trading code in several conditions: Here is my on trade code that allows me to check if I have a current order or something. I have about 6 levels of these checks which all work together to prevent what you mentioned. It takes about 2 years to work out what is required.

The below prevents opening new orders when orders are already placed on the symbol.

int Longpendingorders = 0;
            int Shortpendingorders = 0;
            var LabelLong = "Long";
            var LabelShort = "Short";

            if (PendingOrders.Count(x => x.Label == LabelLong) > 0)
            {
                foreach (var order in PendingOrders)
                {
                    if (order.SymbolName == SymbolName)
                        Longpendingorders = 1;
                }
            }
            if (PendingOrders.Count(x => x.Label == LabelShort) > 0)
            {
                foreach (var order in PendingOrders)
                {
                    if (order.SymbolName == SymbolName)
                        Shortpendingorders = 1;
                }
            }

For your specific question where you want to only trade once when the price is above the MA, I would create a variable to record a metric and prevent trading within a range of that metric. I see this too and is also something I am trying to fix.

I have had success with this by using the Count of the chart, but have also fount that a chart count might be able to be tried more than once if the entry is different from the first entry, but still testing that tbh.

 


@prosteel1

prosteel1
24 Feb 2021, 14:43

RE:

PanagiotisCharalampous said:

Hi prosteel1,

Since the convention is different, any comparison will not make sense. I will have to discuss this with the product team if they are willing to change the convention or if there is a reason that would not allow this to be changed.

Best Regards,

Panagiotis 

Join us on Telegram

The above code shows that it is possible to measure volume in a way that they can be compared. Perhaps another volume metric could be added to time based candles that matches with the tick candle volume within the open and close of the candle on that timeframe. And/Or the difference could be added to the tick based volume as another metric.

With a bit of work it might be possible to compare the volume on 1 minute candle with the number of ticks reported since that 1 minute candle opened, and that difference might be the number of ask ticks.

The ask ticks might be the key to comparing time based and tick based candles it seems.


@prosteel1

prosteel1
24 Feb 2021, 13:39 ( Updated at: 24 Feb 2021, 14:05 )

RE:

PanagiotisCharalampous said:

Hi prosteel1,

The explanation is that while for time based candles both bid and ask ticks are considered for Tick Volume, for tick based candles only bid ticks are considered. This is a necessary convention to avoid empty candles or tick volume that does not match the candle size.

Best Regards,

Panagiotis 

Join us on Telegram

I haven't seen anything to suggest your explanation is not correct. Typically the time based candles have between 1.3 and 1.5 times the number of ticks in tick based candles. The difference could well be ask ticks.

The reason why I posted this is because I would like to be able to compare the number of ticks in tick based candles with the number of ticks in time based candles to be able to sort both time based and tick based candles in a sorted hierarchy based on ticks.

The above robot proves that the number of ticks in time based candles is not equal to the number of ticks in tick based candles within that time - the time based candles contain between 1.3 and 1.5 more ticks based on series[i].TickVolumes of time based candles compared to the number of ticks counted on tick based candles within the open and close times of the time based candles.

It would appear that the liquidity provider is including ask ticks in time based candles but not in tick candles.

I'm testing ways to compare both, but worth asking if this is correct in the first place as it was unexpected.

Further questions might be why can't we have ask ticks in the tick candles so the tick volume of tick candles matches the tick volume of time based candles? While I sort of understand why from a technical perspective (ask ticks might be superfluous), there is a disconnect between the two measurement methods that result in different tick volumes within the same time period.


@prosteel1

prosteel1
23 Feb 2021, 16:22

Here is a robot that counts the ticks in bars on various timeframes. It draws 1 minute bars on tick timeframes so the periods can be counted by dragging the crosshair tool.

It prints the number of counted ticks per bar and compares it to the TickVolume of the bar.

Example output:

The last Minute bar had it's first tick on 23/02/2021 2:17:00 PM, and it's last tick on 23/02/2021 2:17:57 PM for a difference of 51 ticks. The bar opened on 23/02/2021 2:17:00 PM and reports a volume of 71. 71 / 51 = 1.39

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class TickTest : Robot
    {
        [Parameter("Frame0", DefaultValue = "Tick1000")]
        public TimeFrame TF0 { get; set; }
        [Parameter("Frame1", DefaultValue = "Tick750")]
        public TimeFrame TF1 { get; set; }
        [Parameter("Frame2", DefaultValue = "Tick500")]
        public TimeFrame TF2 { get; set; }
        [Parameter("Frame3", DefaultValue = "Tick300")]
        public TimeFrame TF3 { get; set; }
        [Parameter("Frame4", DefaultValue = "Tick250")]
        public TimeFrame TF4 { get; set; }
        [Parameter("Frame5", DefaultValue = "Tick200")]
        public TimeFrame TF5 { get; set; }
        [Parameter("Frame6", DefaultValue = "Tick150")]
        public TimeFrame TF6 { get; set; }
        [Parameter("Frame7", DefaultValue = "Tick100")]
        public TimeFrame TF7 { get; set; }
        [Parameter("Frame8", DefaultValue = "Tick90")]
        public TimeFrame TF8 { get; set; }
        [Parameter("Frame9", DefaultValue = "Tick80")]
        public TimeFrame TF9 { get; set; }
        [Parameter("Frame10", DefaultValue = "Tick60")]
        public TimeFrame TF10 { get; set; }
        [Parameter("Frame11", DefaultValue = "Tick50")]
        public TimeFrame TF11 { get; set; }
        [Parameter("Frame12", DefaultValue = "Tick40")]
        public TimeFrame TF12 { get; set; }
        [Parameter("Frame13", DefaultValue = "Tick30")]
        public TimeFrame TF13 { get; set; }
        [Parameter("Frame14", DefaultValue = "Tick25")]
        public TimeFrame TF14 { get; set; }
        [Parameter("Frame15", DefaultValue = "Tick20")]
        public TimeFrame TF15 { get; set; }
        [Parameter("Frame16", DefaultValue = "Tick15")]
        public TimeFrame TF16 { get; set; }
        [Parameter("Frame17", DefaultValue = "Tick10")]
        public TimeFrame TF17 { get; set; }
        [Parameter("Frame18", DefaultValue = "Tick9")]
        public TimeFrame TF18 { get; set; }
        [Parameter("Frame19", DefaultValue = "Tick8")]
        public TimeFrame TF19 { get; set; }
        [Parameter("Frame20", DefaultValue = "Tick7")]
        public TimeFrame TF20 { get; set; }
        [Parameter("Frame21", DefaultValue = "Tick6")]
        public TimeFrame TF21 { get; set; }
        [Parameter("Frame22", DefaultValue = "Tick5")]
        public TimeFrame TF22 { get; set; }
        [Parameter("Frame23", DefaultValue = "Tick4")]
        public TimeFrame TF23 { get; set; }
        [Parameter("Frame24", DefaultValue = "Tick3")]
        public TimeFrame TF24 { get; set; }
        [Parameter("Frame25", DefaultValue = "Tick2")]
        public TimeFrame TF25 { get; set; }
        [Parameter("Frame26", DefaultValue = "Tick")]
        public TimeFrame TF26 { get; set; }
        [Parameter("Frame27", DefaultValue = "Minute")]
        public TimeFrame TF27 { get; set; }
        [Parameter("Frame28", DefaultValue = "Minute2")]
        public TimeFrame TF28 { get; set; }
        [Parameter("Frame29", DefaultValue = "Minute3")]
        public TimeFrame TF29 { get; set; }
        [Parameter("Frame30", DefaultValue = "Minute4")]
        public TimeFrame TF30 { get; set; }
        [Parameter("Frame31", DefaultValue = "Minute5")]
        public TimeFrame TF31 { get; set; }
        [Parameter("Frame32", DefaultValue = "Minute6")]
        public TimeFrame TF32 { get; set; }
        [Parameter("Frame33", DefaultValue = "Minute7")]
        public TimeFrame TF33 { get; set; }
        [Parameter("Frame34", DefaultValue = "Minute8")]
        public TimeFrame TF34 { get; set; }
        [Parameter("Frame35", DefaultValue = "Minute9")]
        public TimeFrame TF35 { get; set; }
        [Parameter("Frame36", DefaultValue = "Minute10")]
        public TimeFrame TF36 { get; set; }
        [Parameter("Frame37", DefaultValue = "Minute15")]
        public TimeFrame TF37 { get; set; }
        [Parameter("Frame38", DefaultValue = "Minute20")]
        public TimeFrame TF38 { get; set; }
        [Parameter("Frame39", DefaultValue = "Minute30")]
        public TimeFrame TF39 { get; set; }
        [Parameter("Frame40", DefaultValue = "Minute45")]
        public TimeFrame TF40 { get; set; }
        [Parameter("Frame41", DefaultValue = "Hour")]
        public TimeFrame TF41 { get; set; }
        [Parameter("Frame42", DefaultValue = "Hour2")]
        public TimeFrame TF42 { get; set; }
        [Parameter("Frame43", DefaultValue = "Hour3")]
        public TimeFrame TF43 { get; set; }
        [Parameter("Frame44", DefaultValue = "Hour4")]
        public TimeFrame TF44 { get; set; }
        [Parameter("Frame45", DefaultValue = "Hour6")]
        public TimeFrame TF45 { get; set; }
        [Parameter("Frame46", DefaultValue = "Hour8")]
        public TimeFrame TF46 { get; set; }
        [Parameter("Frame47", DefaultValue = "Daily")]
        public TimeFrame TF47 { get; set; }
        [Parameter("Frame48", DefaultValue = "Daily2")]
        public TimeFrame TF48 { get; set; }
        [Parameter("Frame49", DefaultValue = "Daily3")]
        public TimeFrame TF49 { get; set; }
        [Parameter("Frame50", DefaultValue = "Weekly")]
        public TimeFrame TF50 { get; set; }
        [Parameter("Frame51", DefaultValue = "Monthly")]
        public TimeFrame TF51 { get; set; }

        TimeFrame[] Frames = new TimeFrame[52];
        Boolean[] Framesbool = new Boolean[52];
        Bars[] series = new Bars[52];
        int[] serieslast = new int[52];

        protected override void OnStart()
        {
            WriteVariables();

            for (int i = 0; i < Frames.Length; i++)
            {
                if (Framesbool[i] == true)
                {
                    serieslast[i] = series[i].Count - 2;
                    Print(Frames[i] + ", Count = " + (series[i].Count - 2));
                }
            }
        }

        protected override void OnTick()
        {
            for (int i = 0; i < Frames.Length; i++)
            {
                if (Framesbool[i] == true && (series[i].Count - 2) > serieslast[i])
                {
                    int j;
                    int ii;
                    bool Notenoughdata = false;
                    if (i >= 27)
                    {
                        // Find the last tick of the bar
                        for (j = series[26].Count - 1; series[26].OpenTimes[j] > series[i].OpenTimes[series[i].Count - 1]; j--)
                        {
                            if (j == 1)
                                break;
                        }
                        // Find the first tick of the bar
                        for (ii = series[26].Count - 1; series[26].OpenTimes[ii] > series[i].OpenTimes[series[i].Count - 2]; ii--)
                        {
                            if (ii == 1)
                            {
                                Notenoughdata = true;
                                break;
                            }
                        }
                        if (Notenoughdata != true)
                        {
                            Print("The last " + Frames[i] + " bar had it's first tick on " + series[26].OpenTimes[ii + 1] + ", and it's last tick on " + series[26].OpenTimes[j] + " for a difference of " + (j - (ii + 1)) + " ticks. The bar opened on " + series[i].OpenTimes[series[i].Count - 2] + " and reports a volume of " + series[i].TickVolumes[series[i].Count - 2] + ". " + series[i].TickVolumes[series[i].Count - 2] + " / " + (j - (ii + 1)) + " = " + Math.Round((series[i].TickVolumes[series[i].Count - 2] / (j - (ii + 1))), 2));
                            // Draw rectangles of 1 Minute bars on the tick1 chart
                            if (i == 27)
                            {
                                var rect1 = Chart.DrawRectangle(Frames[i] + "-" + j + "-" + ii + 1, series[26].OpenTimes[ii + 1], series[i].LowPrices[series[i].Count - 2], series[26].OpenTimes[j], series[i].HighPrices[series[i].Count - 2], "Blue");
                                rect1.IsInteractive = true;
                            }
                        }
                    }
                    serieslast[i] = series[i].Count - 2;
                }
            }
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
        private void WriteVariables()
        {
            Frames[0] = TF0;
            Frames[1] = TF1;
            Frames[2] = TF2;
            Frames[3] = TF3;
            Frames[4] = TF4;
            Frames[5] = TF5;
            Frames[6] = TF6;
            Frames[7] = TF7;
            Frames[8] = TF8;
            Frames[9] = TF9;
            Frames[10] = TF10;
            Frames[11] = TF11;
            Frames[12] = TF12;
            Frames[13] = TF13;
            Frames[14] = TF14;
            Frames[15] = TF15;
            Frames[16] = TF16;
            Frames[17] = TF17;
            Frames[18] = TF18;
            Frames[19] = TF19;
            Frames[20] = TF20;
            Frames[21] = TF21;
            Frames[22] = TF22;
            Frames[23] = TF23;
            Frames[24] = TF24;
            Frames[25] = TF25;
            Frames[26] = TF26;
            Frames[27] = TF27;
            Frames[28] = TF28;
            Frames[29] = TF29;
            Frames[30] = TF30;
            Frames[31] = TF31;
            Frames[32] = TF32;
            Frames[33] = TF33;
            Frames[34] = TF34;
            Frames[35] = TF35;
            Frames[36] = TF36;
            Frames[37] = TF37;
            Frames[38] = TF38;
            Frames[39] = TF39;
            Frames[40] = TF40;
            Frames[41] = TF41;
            Frames[42] = TF42;
            Frames[43] = TF43;
            Frames[44] = TF44;
            Frames[45] = TF45;
            Frames[46] = TF46;
            Frames[47] = TF47;
            Frames[48] = TF48;
            Frames[49] = TF49;
            Frames[50] = TF50;
            Frames[51] = TF51;

            Framesbool[0] = true;
            Framesbool[1] = true;
            Framesbool[2] = true;
            Framesbool[3] = true;
            Framesbool[4] = true;
            Framesbool[5] = true;
            Framesbool[6] = true;
            Framesbool[7] = true;
            Framesbool[8] = true;
            Framesbool[9] = true;
            Framesbool[10] = true;
            Framesbool[11] = true;
            Framesbool[12] = true;
            Framesbool[13] = true;
            Framesbool[14] = true;
            Framesbool[15] = true;
            Framesbool[16] = true;
            Framesbool[17] = true;
            Framesbool[18] = true;
            Framesbool[19] = true;
            Framesbool[20] = true;
            Framesbool[21] = true;
            Framesbool[22] = true;
            Framesbool[23] = true;
            Framesbool[24] = true;
            Framesbool[25] = true;
            Framesbool[26] = true;
            Framesbool[27] = true;
            Framesbool[28] = true;
            Framesbool[29] = true;
            Framesbool[30] = true;
            Framesbool[31] = true;
            Framesbool[32] = true;
            Framesbool[33] = true;
            Framesbool[34] = true;
            Framesbool[35] = true;
            Framesbool[36] = true;
            Framesbool[37] = true;
            Framesbool[38] = true;
            Framesbool[39] = true;
            Framesbool[40] = true;
            Framesbool[41] = true;
            Framesbool[42] = true;
            Framesbool[43] = true;
            Framesbool[44] = true;
            Framesbool[45] = true;
            Framesbool[46] = true;
            Framesbool[47] = true;
            Framesbool[48] = true;
            Framesbool[49] = true;
            Framesbool[50] = true;
            Framesbool[51] = true;

            for (int i = 0; i < Frames.Length; i++)
            {
                if (Framesbool[i] == true)
                {
                    series[i] = MarketData.GetBars(Frames[i]);
                }
            }
        }
    }
}

 


@prosteel1

prosteel1
22 Feb 2021, 13:54

RE:

PanagiotisCharalampous said:

Hi prosteel1,

The explanation is that while for time based candles both bid and ask ticks are considered for Tick Volume, for tick based candles only bid ticks are considered. This is a necessary convention to avoid empty candles or tick volume that does not match the candle size.

Best Regards,

Panagiotis 

Join us on Telegram

Wow, Very interesting! And not at all what I expected, lets see how far down the rabbit hole goes :)


@prosteel1

prosteel1
22 Feb 2021, 13:26

RE:

PanagiotisCharalampous said:

Hi prosteel1,

There is an explanation but better do the robot to make sure we are talking about the same thing :)

Best Regards,

Panagiotis 

Join us on Telegram

Thanks mate, can you share the potential explanation so I can add it to the robot to check please?

Currently the Tick1 seems to be out of sync with Tick10 etc so will set it up for that.


@prosteel1

prosteel1
18 Feb 2021, 18:48 ( Updated at: 21 Dec 2023, 09:22 )

Tick Timeframes now in the Tick Database!

Great to see the Tick Timeframe Names are now in the database so they can be referenced by name. My previous Workaround for this which I only implimented yesterday was to create an array with the index as the hirachy and during Optimisation mode to check if the analysis timeframe had a lower index than the trading timeframe and if it did to do Stop() so it didn't use up time in the optimization. The result was it iterated through all combinations of timeframes where it analysed on longer timeframe and entered on shorter timeframe.

This update means that tick timeframes can be hard coded without having to manually select them by making them a parameter :) When using my multi time frame method which seperates the chart timeframe from the analysis and trading timeframe, Multi time frame optimization is now quite easy! 

 

 

This will likely help a great deal in making the selection of timeframes to use more plastic during a cbot running - changing timeframes while its running based on volatility for eg. :)

 

In 3.8 the right side of the screenshot would show all the timeframes as 1 hour, and the tick timeframes would have to be selected manually for this to work, but because 4.0 now has the names of the Tick timeframes in the database,  they now map correctly rather than defaulting to 1 hour because the names weren't in the database before:)

I'm looking forward to figuring out dynamic Timeframes now :) Great job Spotware! 

I'll try to post an example multi timeframe optimization cbot in the next few weeks that makes use of this upgrade.


@prosteel1

prosteel1
13 Feb 2021, 20:27 ( Updated at: 13 Feb 2021, 22:05 )

Timeline for Python support

Is there any Timeline estimation for implementing a later version of .Net that would support using Python for Artificial Intelligence cBots?

Previously, Panagiotis and Paul said that 4.0 would implement .Net Core but that got cancelled. 

Current framework is still .Net Framework 4 Client Profile which is extremely old and not compatible with anything current, let alone anything in current use.

Without upgrading to a current .Net Framework I don't see why this version is a major version from 3.8 to 4.0, am I missing something?


@prosteel1

prosteel1
26 Jan 2021, 21:18 ( Updated at: 26 Jan 2021, 21:30 )

RE:

jackhpfilerrowson said:

HI, I was just wondering if there is a way to reference back to a specific bar instead of just .last(x)?

I use the .Count where the zero Count is the earliest bar in the history and as new bars form the .Count increases.

I use this so I can assign charts to a specific Count that doesn't change (unless more history is loaded after the bot is started by scrolling).

Can't find a better example then the below atm sorry. 

Basically declare: Bars series0 = MarketData.GetBars(Daily);

and then you can use series0.Count which is for a specific bar that doesn't change.

 


@prosteel1

prosteel1
26 Jan 2021, 18:29

RE:

sifneos4fx said:

Hello folks, 

When I draw the fibonacci retracement or expansion tool, it is drawn with the standard levels which I dont' like. Is it possible to draw the tools using own levels?

Thanks

Patrick

 

 

I don't think there is in Automate, only in the Trade tab when drawing manually.

In Automate I calculate my levels for trades and then wrap the drawing of them in a check so they are not drawn if it's in Optimization mode.

if (RunningMode != RunningMode.Optimization)
    {
            var rect1 = Chart.DrawRectangle(UniqueName, DateTime1, Price1, DateTime2, Price2, Color.Green);
            rect1.IsInteractive = true;
            if (DrawHorizLines == true)
            {
                var line1 = Chart.DrawHorizontalLine(UniqueName, Price, Color.Green);
                line1.IsInteractive = true;
            }
    }


@prosteel1

prosteel1
20 Jan 2021, 08:37

RE:

Bots4Us said:

Hi prosteel1,

The EntryPrice cannot be null. By contrast, the Take Profit is in the above. A double cannot be nulled.
https://ctrader.com/forum/calgo-support/7806#post-2

Bots4Us

 

Thanks!


@prosteel1

prosteel1
19 Jan 2021, 18:22

RE: RE: RE:

1222Ht said:

prosteel1 said:

PanagiotisCharalampous said:

Hi 1222Ht,

cTrader Automate doesn't support .Net Standard at the moment.

Best Regards,

Panagiotis 

Join us on Telegram

"...PyTorch as Tensorflow is not the bleeding edge anymore."

interestin. any expert has any comment or insight to share as to broaden newbies conception on their differences n possibily individually each ones advantages n drawbacks, thanks

Lex Fridman has a lot of info, start here: 

 

Panagiotis, is there any timeframe for .Net Core? 


@prosteel1