Chart.DrawStaticText doesn't update text?

Created at 12 Oct 2019, 18:45
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
FI

firemyst

Joined 26.03.2019

Chart.DrawStaticText doesn't update text?
12 Oct 2019, 18:45


HI everyone:

I have the following code in my bot's OnStart() method:

if (_countDownTimer == null)
                        {
                            _countDownTimer = new System.Timers.Timer(1000);
                            _countDownTimer.AutoReset = true;
                            _countDownTimer.Enabled = true;
                            _countDownTimer.Elapsed += CountDownTimerEvent;
                        }
                        _countDownTimer.Start();

Then the CountDownTimerEvent is defined as:

private void CountDownTimerEvent(Object source, System.Timers.ElapsedEventArgs e)
        {
            Chart.DrawStaticText(_positionLabel, _positionLabel + Environment.NewLine + "Server Time: " + Server.Time.TimeOfDay, VerticalAlignment.Top, HorizontalAlignment.Left, Color.Goldenrod);
        }

The text on the chart is never updated with the latest Server.Time after the first second.

Is this intended behavior? If not, how do I get the text to display the server's time every time the CountDownTimerEvent method is called?

Thank you.

 

 


@firemyst
Replies

PanagiotisCharalampous
14 Oct 2019, 09:25

Hi FireMyst,

Can you please post a complete cBot code the reproduces this issue?

Best Regards,

Panagiotis


@PanagiotisCharalampous

firemyst
14 Oct 2019, 11:40

Here you go, although it's working somewhat better today.

It's writing to the log output every second, but the DrawStaticText isn't updated every second.

Why is this?

When I'm running this against a demo account, this is the only bot I have running in cTrader.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

//Demonstrates issue with cTrader timers and drawing text.
//The log is written to every second; the statictext isn't updated every second.
//Run on US30 chart

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class BugBot : Robot
    {
        private string _positionLabel = "Bug bot";
        private System.Timers.Timer _countDownTimer;

        protected override void OnStart()
        {   
            Print("OnStart: Starting \"{0}\"", _positionLabel);
            if (_countDownTimer == null)
            {
                _countDownTimer = new System.Timers.Timer(1000);
                _countDownTimer.AutoReset = true;
                _countDownTimer.Enabled = true;
                _countDownTimer.Elapsed += CountDownTimerEvent;
            }
            _countDownTimer.Start();
        }

        protected override void OnBar()
        {   
        }

        protected override void OnTick()
        {
        }

        /// <summary>
        /// Wait X seconds before reentering a position.
        /// </summary>
        private void CountDownTimerEvent(Object source, System.Timers.ElapsedEventArgs e)
        {
            DateTime dt = Server.Time;

            //This line is updated and prints every second as expcted.
            Print("CDTE01: Server's Time: \"{0}\"", dt.ToString("HH:mm:ss"));

            //This isn't updated every second. In fact, some times it takes 6-10 seconds to update. Why is this?
            Chart.DrawStaticText(_positionLabel, _positionLabel + " Server Time: " + dt.ToString("HH:mm:ss"), VerticalAlignment.Top, HorizontalAlignment.Left, Color.Goldenrod);
        }

    }
}

 


@firemyst

srubtsov
18 Oct 2019, 10:36

It happens because .NET timers (System.Timers.Timer, System.Threading) use and create additional threads and cBot/Indicator can't guarantee successful interaction, not from the main thread with cTrader (drawing, printing log for example).

So, that problem possible to solve with two ways:

1. Use method `BeginInvokeOnMainThread(Action action)` - it synchronizes and executes action in main thread

private void CountDownTimerEvent(Object source, System.Timers.ElapsedEventArgs e)
{
    BeginInvokeOnMainThread(() =>
    {
        DateTime dt = Server.Time;
        Print("CDTE01: Server's Time: \"{0}\"", dt.ToString("HH:mm:ss"));
        Chart.DrawStaticText("staticText", "Server Time: " + dt.ToString("HH:mm:ss"), VerticalAlignment.Top,
            HorizontalAlignment.Right, Color.Goldenrod);
    });
}

2. Use timer from cAlgo.API. It's the best way because of that timer successfully works in backtesting.

protected override void OnStart()
{
    Timer.TimerTick += CountDownTimerEvent;
    var intervalInSeconds = 1;
    Timer.Start(intervalInSeconds);
}

private void CountDownTimerEvent()
{
    DateTime dt = Server.Time;
    Print("CDTE01: Server's Time: \"{0}\"", dt.ToString("HH:mm:ss"));
    Chart.DrawStaticText("staticText", "Server Time: " + dt.ToString("HH:mm:ss"), VerticalAlignment.Top,
        HorizontalAlignment.Right, Color.Goldenrod);
}

 


@srubtsov

firemyst
21 Oct 2019, 03:34

Thank you @srubtsov for your explanation.

Your suggestion #2 has worked for me without any issues thus far.

The only limitation I can see with #2, given that the cTrader Timer implementation is an "interface", is you can't declare and have multiple distinct Timer objects within a cBot?


@firemyst

srubtsov
21 Oct 2019, 10:28

RE:

FireMyst said:

Thank you @srubtsov for your explanation.

Your suggestion #2 has worked for me without any issues thus far.

The only limitation I can see with #2, given that the cTrader Timer implementation is an "interface", is you can't declare and have multiple distinct Timer objects within a cBot?

Yes, you are right, you can't create additional Timer instances and should use Timer property. But I think it possible to create improved timer based on Algo.Timer with some hack.


@srubtsov