GridSurfer
GridSurfer's avatar

Info

Username:GridSurfer
Name:GridSurfer
Member since: 08 Jun 2019

About

None

Signature

None

Last Forum Posts

@Tick LoadMoreHistory() problem:  16 Jan 2023, 09:38


Hi Support,

thanks, here is the code. No parameters.

-------------------------------------------------------------------------------------------------------------

using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.IO;


namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.GMTStandardTime, AccessRights = AccessRights.FullAccess)]
    public class TickdataExportMultiSymbol : Robot
    {
        private string _dataDirectory = "O:\\_TradingData\\_Data_ICMarkets\\_Source";
        private string[] _symbols = {  "EURAUD", "EURGBP", "EURJPY", "EURUSD", "EURCHF", "EURCAD", "EURNZD", 
                                    "GBPUSD", "GBPJPY", "GBPCHF", "GBPCAD", "GBPAUD","GBPNZD"};

        protected override void OnStart()
        {
            // System.Diagnostics.Debugger.Launch();
        
            foreach (string ticker in _symbols)
            {
                // Read last Tick in file (Load Ticks after that)
                //
                DateTime firstDt = GetLastTickInFiles(ticker);

                // For the initial files use one month more back
                //
                DateTime firstMaxDt = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
                if (firstDt.Year < DateTime.Now.Year - 1)
                    firstDt = firstMaxDt.AddMonths(-1);

                // Load Ticks
                //
                API.Ticks symbolTicks;
                symbolTicks = MarketData.GetTicks(ticker);
                while (symbolTicks[0].Time.CompareTo(firstDt.AddHours(-4)) > 0)
                {
                    symbolTicks.LoadMoreHistory();
                }

                List<TickRec> tickList = new List<TickRec>();
                DateTime lastDt = new DateTime(1970, 1, 1);

                for (int idx = 0; idx < symbolTicks.Count; idx++)
                {
                    // Adjust by 2 hours - forex trade week starts 00:00 (needs addl. 1 hour [e.g. 08.03.2020 - 29.03.2020])
                    //
                    DateTime dt = symbolTicks[idx].Time.AddHours(2);

                    // If by any chance there are two ticks with same time, add 1ms to the second tick
                    //
                    while ((dt - lastDt).TotalMilliseconds <= 0)
                        dt = dt.AddMilliseconds(1);
                    lastDt = dt;

                    if (dt.CompareTo(firstDt) > 0)
                    {
                        TickRec newTick = new TickRec();
                        newTick.Bid = symbolTicks[idx].Bid;
                        newTick.Ask = symbolTicks[idx].Ask;
                        newTick.DateTime = dt;
                        tickList.Add(newTick);
                    }
                }

                SaveTicks(ticker, tickList);
            }

            Notifications.PlaySound("C:/Windows/Media/Ring05.wav");
            
        }

        protected override void OnTick()
        {
        }

        protected override void OnStop()
        {
        }

        private DateTime GetLastTickInFiles(string Ticker)
        {
            DateTime lastTickDt = new DateTime(1970, 1, 1);
            var dirInfo = new DirectoryInfo(_dataDirectory);
            FileInfo[] files = dirInfo.GetFiles(Ticker + "_*.csv");            
            if (files.Length > 0)
            {
                // Locate the last tick file of this symbol
                // Read to the end and return DateTime of last Tick
                //
                FileInfo fInfo = files.OrderByDescending(x => x.Name).First();
                string line = "", lastLine = "";
                DateTime readDt = new DateTime(1970,1,1);
                using (StreamReader file = new StreamReader(fInfo.FullName))
                {
                    while ((line = file.ReadLine()) != null)
                        if (line.Length > 10)
                            lastLine = line;
                }
                string[] parts = lastLine.Split('\t');
                DateTime.TryParse(parts[0], out lastTickDt);
            }
            return lastTickDt;
        }

        private void SaveTicks(string Ticker, List<TickRec>TickList)
        {
            if (TickList.Count == 0)
                return;

            int loopMonth = TickList[0].DateTime.Month;
            int loopYear = TickList[0].DateTime.Year;
            bool finished = false;
            while (!finished)
            {
                string fileName = _dataDirectory + "\\" + Ticker + "_" + loopYear + "-" + loopMonth.ToString("00") + ".csv";

                StreamWriter sw = new StreamWriter(fileName, true);
                foreach (TickRec tick in TickList.Where(x => x.DateTime.Year == loopYear && x.DateTime.Month == loopMonth))
                {
                    sw.WriteLine(tick.DateTime.ToString("dd.MM.yyyy HH:mm:ss.fff") + "\t" + tick.Bid + "\t" + tick.Ask);
                }
                sw.Close();
                loopMonth++;
                if (loopMonth == 13)
                {
                    loopMonth = 1;
                    loopYear++;
                }
                finished = (TickList[TickList.Count - 1].DateTime.CompareTo(new DateTime(loopYear, loopMonth, 1)) < 0);
            }
        }
    }

    public class TickRec
    {
        public DateTime DateTime;
        public double Bid = 0;
        public double Ask = 0;
    }
}

@Tick LoadMoreHistory() problem:  16 Jan 2023, 08:36


Thanks firemyst for your thoughts, but yes it is a valid date. Usually 1 week before, because I update my tick data on the weekend. I have been using the script for years now.

I watched the execution with a debugger as well. The first few times it executes LoadMoreHistory() - which is always a 3 hour chunk of tickdata - works almost fine, then it gets slower and slower until it stops working.

@Tick LoadMoreHistory() problem:  15 Jan 2023, 15:57


Hi Support,

since the last Update (it seems) I barely get any historic tick data anymore.
It takes forever to get any fills and often times simply quits doing anything. If I get data it takes hours for what took seconds before.
I am with ICMarkets and it is the same on Demo and Live account.

I am using a script I have been using for years now and it always worked fine. The past few days it shows this problem.

The script doesn't do anything special

                API.Ticks symbolTicks;
                symbolTicks = MarketData.GetTicks(ticker);
                while (symbolTicks[0].Time.CompareTo(firstDt) > 0)
                {
                    symbolTicks.LoadMoreHistory();
                }

I would blame ICMarkets, but cTrader is running at one Core full CPU, so it must be doing something!
I applied the TLS fix but it didn't solve anything, my access to the platform/broker was always good.

Do you have any idea what could be the problem?

Cheers
GridSurfer

@Bot stops working after Reconnect:  07 Nov 2022, 14:45


Spotware said:

It's a very vague discussion. We will be able to advise if you share your source code and explain in detail the issue you are experiencing.

I will prepare and share, of course, but first I need to know what the desired outcome is supposed to be.

I have a bot running, it has positions, it is waiting for events OnTick() etc. --> If the connection is lost, cTrader logs out and when the connection comes back cTrader reconnects.

It is not a "vague discussion" - actually it is a simple question:Does the bot continue running as if there were no disconnect or is there some reset, re-initialize, break, etc.?

@Bot stops working after Reconnect:  04 Nov 2022, 15:33


Hi Support,

thanks for your quick reply. If "it depends on your cBot's implementation", what do I need to do to keep my bot alive.

Given the simplest of all bots (e.g. your sample of a basic bot), what is supposed to happen, when cTrader loses connection and reconnects with the last account?

If it is anything but the bot keeps running, keeps all previous conditions, session, trades, variables, etc. - what can I do to make sure my bot keeps running, unless I close cTrader completely or stop the bot? Is there a way to ensure the disconnect, reconnect doesn't affect the bot running?

Cheers

@Bot stops working after Reconnect:  04 Nov 2022, 12:11


Spotware said:

Dear GridSurfer,

Can you please share your cBot so that we can investigate further?

Best regards,

cTrader Team

Thank you. Unfortunately the code is huge with lots of necessary setups (files, paths etc.). I will wite a simple bot and test it with it.

For my understanding:

1. When cTrader loses connection (no matter how long) and reconnects, the running bot should continue working as if there were no disruption?
2. The ticks that occured during this time are not re-send. I could get them from the server via MarketData.GetTicks()
3. But basically I wouldn't know that there was a disconnect without data feed during a certain time, right? Or is there a way to verify that all ticks have arrived?

For the time being I am only concerned with 1. I know of this approx. 1 minute disruption of the connection which sends the system sometimes into nirvana.

@Bot stops working after Reconnect:  03 Nov 2022, 22:19


Hi,

my dsl internet provider cuts my connection every night for about 1 minute. In most cases the reconnect doesn't affect the running bot but I have had several times now, that the bot disappears in nirvana. What I mean is that the bot stopps working - doesn't trade anymore etc., but appears still running in cTrader.

I even tried it with debugging: after the reconnect in the night cTrader doesn't send OnTick() or does anything with the bot. I can hit the "Stop Bot" button and the bot stops, but even the OnStop() does not seem to be called.

My questions are: How can I circumvent the state of "nirvana"? cTrader keeps working, so it is the reconnect I need to handle - is this done programmatically? I want the bot keep working when the connection is lost while the bot is running.

Cheers
GridSurfer

@Server.Time Error - Time in Future (October):  02 Sep 2022, 11:31


Hi Support,

for my bot I capture Ticks from various symbols and process them later. With each tick I attach the current Server.Time.
However, every few thousand ticks or so I get a Server.Time sometime in October. This only happens when realtime. In MarketData.GetTicks() time seems o.k.

Below is a little script that isolates the problem. Just a few minutes as expample, it gives the following output for my demo (IC Markets):

02.09.2022 07:41  -- 2.717 Ticks
02.09.2022 07:42  -- 2.590 Ticks
02.09.2022 07:43  -- 2.885 Ticks
02.09.2022 07:44  -- ERROR in minute -->AUDUSD - 22.10.2022 00:47:20
02.09.2022 07:44  -- 2.604 Ticks
02.09.2022 07:45  -- 2.689 Ticks
02.09.2022 07:46  -- 2.277 Ticks
02.09.2022 07:47  -- 2.156 Ticks
02.09.2022 07:48  -- 2.226 Ticks
02.09.2022 07:49  -- ERROR in minute -->AUDJPY - 22.10.2022 00:52:21
02.09.2022 07:49  -- ERROR in minute -->GBPAUD - 22.10.2022 00:52:21
02.09.2022 07:49  -- ERROR in minute -->EURNZD - 22.10.2022 00:52:21
02.09.2022 07:49  -- 2.415 Ticks
02.09.2022 07:50  -- 2.313 Ticks
02.09.2022 07:51  -- 2.110 Ticks
02.09.2022 07:52  -- 2.065 Ticks
02.09.2022 07:53  -- 1.935 Ticks
02.09.2022 07:54  -- ERROR in minute -->AUDJPY - 22.10.2022 00:57:21
02.09.2022 07:54  -- 1.720 Ticks
02.09.2022 07:55  -- 1.898 Ticks
02.09.2022 07:56  -- 2.609 Ticks
02.09.2022 07:57  -- 2.413 Ticks
02.09.2022 07:58  -- 2.078 Ticks
02.09.2022 07:59  -- 2.473 Ticks
02.09.2022 08:00  -- 2.898 Ticks
02.09.2022 08:01  -- 2.242 Ticks
02.09.2022 08:02  -- ERROR in minute -->NZDCHF - 22.10.2022 01:05:21
02.09.2022 08:02  -- ERROR in minute -->EURJPY - 22.10.2022 01:05:21
02.09.2022 08:02  -- 2.405 Ticks
02.09.2022 08:03  -- 2.076 Ticks
02.09.2022 08:04  -- 2.275 Ticks
02.09.2022 08:05  -- ERROR in minute -->GBPJPY - 22.10.2022 01:08:21
02.09.2022 08:05  -- 2.758 Ticks
02.09.2022 08:06  -- 2.189 Ticks

Example PROD (LIVE IC-Markets)

02.09.2022 08:16  -- 2.349 Ticks
02.09.2022 08:17  -- 2.135 Ticks
02.09.2022 08:18  -- 2.580 Ticks
02.09.2022 08:19  -- 2.967 Ticks
02.09.2022 08:20  -- 2.502 Ticks
02.09.2022 08:21  -- ERROR in minute -->GBPJPY - 22.10.2022 01:23:57
02.09.2022 08:21  -- ERROR in minute -->AUDJPY - 22.10.2022 01:23:57
02.09.2022 08:21  -- 2.289 Ticks
02.09.2022 08:22  -- 2.363 Ticks
02.09.2022 08:23  -- 2.467 Ticks
02.09.2022 08:24  -- ERROR in minute -->USDJPY - 22.10.2022 01:26:57
02.09.2022 08:24  -- 2.508 Ticks
02.09.2022 08:25  -- 2.675 Ticks

Do I need to handle Server.Time differently?

Cheers
GridSurfer

using System;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
using System.IO;

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FileSystem)]
    public class TickExample : Indicator
    {
        string[] _strSymbols = 
        {
            "EURAUD", "EURGBP", "EURJPY", "EURUSD", "EURCHF", "EURCAD", "EURNZD", 
            "GBPAUD", "GBPUSD", "GBPJPY", "GBPCHF", "GBPCAD", "GBPNZD",
            "AUDJPY", "AUDUSD", "AUDCAD", "AUDCHF", "AUDNZD",
            "NZDUSD", "NZDCAD", "NZDCHF", "NZDJPY",
            "USDCAD", "USDCHF", "USDJPY", "CADCHF", "CADJPY", "CHFJPY"
        };
        
        string _useFile = @"c:\_Trading\TickError.txt";
        List<TickRec> _tickList = new List<TickRec>();
        List<TickRec> _errorList = new List<TickRec>();
        static object _lockTickList = new object();

        protected override void Initialize()
        {
            foreach (string strSymbol in _strSymbols)
            {
                Symbol symbol = Symbols.GetSymbol(strSymbol);
                symbol.Tick += Symbol_Tick;
            }
            Timer.Start(TimeSpan.FromMinutes(1));
        }

        protected override void OnTimer()
        {
            List<TickRec> checkList = new List<TickRec>();
            lock (_lockTickList)
            {
                checkList = _tickList.GetRange(0, _tickList.Count);
                _tickList = new List<TickRec>();
            }
            
            StreamWriter sw = new StreamWriter(_useFile, true);
            foreach (TickRec tick in checkList)
            {
                if (tick.DateTime.Date.CompareTo(Server.Time.Date) != 0)
                    sw.WriteLine(Server.Time.ToString("dd.MM.yyyy HH:mm") + "  -- ERROR in minute -->" + tick.SymbolName + " - " + tick.DateTime.ToString("dd.MM.yyyy HH:mm:ss"));
            }
            sw.WriteLine(Server.Time.ToString("dd.MM.yyyy HH:mm") + "  -- " + checkList.Count.ToString("#,0") + " Ticks") ;
                
            sw.Close();
	    }
	    
        public override void Calculate(int Index)
        {}
        
        private void Symbol_Tick(SymbolTickEventArgs obj)        
        {
            TickRec newTick = new TickRec();
            newTick.SymbolName = obj.SymbolName;
            newTick.DateTime = Server.Time;
            newTick.Bid = obj.Bid;
            newTick.Ask = obj.Ask;

            lock (_lockTickList)
            {
                _tickList.Add(newTick);
            }
        }
    }

    public class TickRec
    {
        public string SymbolName = "";
        public DateTime DateTime;
        public double Bid = 0;
        public double Ask = 0;
    }
}

@Just a little thing:  06 Aug 2021, 15:06


Hope it explains it in one picture. I have "Change Symbol with Tradewatch" disabled - which is my preferred setting.
But I still want to switch to the chart, which is perfect with the right mouse button menu. However, you need to open the summary, because the switching only works on the individual position and not on the summary line (although it is in the menu).

BTW: Excellent job on the keeping the settings (expanded, sort order, etc. when switching accounts) Thank you for implementing it!
I love how the platform keeps getting better and better!

@Just a little thing:  06 Aug 2021, 11:20


Hope it explains it in one picture. I have "Change Symbol with Tradewatch" disabled - which is my preferred setting.
But I still want to switch to the chart, which is perfect with the right mouse button menu. However, you need to open the summary, because the switching only works on the individual position and not on the summary line (although it is in the menu).

BTW: Excellent job on the keeping the settings (expanded, sort order, etc. when switching accounts) Thank you for implementing it!
I love how the platform keeps getting better and better!

Notification Publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section you may use the Copyright Infringement Notification form to submit a claim.

No uploaded.

Warning! Executing cBots downloaded from this section may result in loss of funds. Use them at your own risk.

No uploaded.