Topics
Replies

firemyst
31 Oct 2019, 02:47

It seems to me your issue is referencing the dll class file.

I don't believe CsvWriter is standard issue C# .Net library.

I'm guessing you want CsvHelper.CsvWriter class? If so, you need to add a reference to your project for the CsvHelper dll assembly.

The only way you can do that is if you've downloaded and installed the CsvHelper dll file somewhere on your computer.

Do a google search, and you'll see you can download it here: https://joshclose.github.io/CsvHelper/


@firemyst

firemyst
30 Oct 2019, 09:20

RE:

Panagiotis Charalampous said:

Hi FireMyst,

Thanks I got it. It has been forwarded to the product team.

Best Regards,

Panagiotis

HI @Panagiotis:

Any updates on this issue? I'm hoping to be able to use those indicators in templates again soon.

Thanks!


@firemyst

firemyst
23 Oct 2019, 10:39

RE:

Panagiotis Charalampous said:

Hi tentcows,

cBot instances run on different threads but they are still controlled by the main UI thread. So if a high number of cBot instances is running on one cTrader instance then this might cause some bottlenecks. I would propose a hybrid solution, to have 3-4 cBot instances running on each cTrader instance.

Best Regards,

Panagiotis

Great tip for everyone @Panagiotis ! Thanks for sharing!


@firemyst

firemyst
22 Oct 2019, 16:18

RE:

Panagiotis Charalampous said:

Hi FireMyst,

Just take them of the charts.

Best Regards,

Panagiotis

HI @Panagiotis:

I've sent a message with how to reproduce the issue, along with the necessary indicators attached and a screen capture too showing the indicators on the screen.

Hopefully your team can reproduce it too.

 


@firemyst

firemyst
22 Oct 2019, 10:30

RE:

Panagiotis Charalampous said:

Hi FireMyst,

It seems you are using a number of custom indicators which might be the root of the problem. We will need to have these indicators to determine if they are causing this. In the meanwhile, can you please remove them and let us know if the issue persists?

Best Regards,

Panagiotis

I can try. Would you be able to clarify what you mean by "remove them"?

1) take them off all charts?

2) remove them from the C:\Users\<username>\Documents\cAlgo\Sources\Indicators folder?

3) something else?

Thank you.


@firemyst

firemyst
22 Oct 2019, 09:44 ( Updated at: 19 Mar 2025, 08:57 )

RE:

Panagiotis Charalampous said:

Hi FireMyst,

To check what happens we will need you to send us troubleshooting information and your settings file. For troubleshooting information, please press Ctrl+Alt+Shift+T, paste the link to the discussion in the text box and press submit. Settings file is found at C:\Users\User\AppData\Roaming\broker-cTrader\Settings. You can send it at support@ctrader.com.

Best Regards,

Panagiotis

Submitted twice - one from VPS; one from another laptop. Hopefully with the emails I've sent in I've made it clear which is which.

I also detailed other issues I've encountered with this latest version as well.

Let me know if you need any more information.

Thanks!


@firemyst

firemyst
22 Oct 2019, 07:40 ( Updated at: 21 Dec 2023, 09:21 )

And here's the memory resource consumption of running cTrader 3.6 on a machine with 8GB of memory. No bot instances running yet. 

Each cTrader instance is using up at least 2GB of memory. So 2 instances of cTrader is using up half the machine's memory. A Windows 2012 Server uses less memory than cTrader now.

@Panagiotis, it seems users will not be able to implement/utilize your suggestion you mentioned here (https://ctrader.com/forum/calgo-support/22114) when we need to run multiple bot instances now because just having 1-4 instances of cTrader running will use up all our computer's/VPS' physical memory on its own without doing anything else.


@firemyst

firemyst
21 Oct 2019, 04:24

RE:

Panagiotis Charalampous said:

Hi FireMyst

Indicator.Calculate(MarketSeries.Close.Count - 1)

will call your indicator's Calculate function for that specific index

Indicator.Result.Last(0);

Will return the last value of the Result series and call the Calculate function for all required indexes if it hasn't been called yet.

Best Regards,

Panagiotis

Thank you @Panagiotis.

A point of clarification  then regarding the 'lazy loading' of indicators.

Let's use the BollingerBands as an example. That has "Top", "Main", and "Bottom" IndicatorDataSeries objects.

Question #1:

if I call BollingerBands.Main.Last(0), will that update the required indexes for BollingerBands.Top and BollingerBands.Bottom too since it calls the Calculate function? Or only update BollingerBands.Main? For example:

//That is, is this sufficient?
double a = bb.Main.Last(0);
//do the other IndicatorDataSeries objects within the same indicator get updated
//as well from the above call to bb.Main.Last(0) so we can use their latest values?
if (bb.Bottom.Last(0) > 3 && bb.Top.Last(0) > 4) { //... }

//
//**** Or do we still have to call Last(0) for every other IndicatorDataSeries object within 
//an indicator as shown below to have them updated with the latest values too?
//
double a = bb.Top.Last(0);
a = bb.Bottom.Last(0);
if (bb.Bottom.Last(0) > 3 && bb.Top.Last(0) > 4) { //... }

 

Question #2:

if we call Indicator.Calculate(MarketSeries.Close.Count - 1), that will force the latest values to be loaded for all IndicatorDataSeries objects within an Indicator?

For example, are both of these functionally equivalent?

//are these two code examples functionally equivalent?
// #1
double a = bb.Bottom.Last(0);
            a = bb.Main.Last(0);
            a = bb.Top.Last(0);
if (bb.Bottom.Last(0) > 1 && bb.Main.Last(0) > 2 && bb.Top.Last(0) > 3) { //... }

// #2
double a = bb.Calculate(MarketSeries.Close.Count - 1)
if (bb.Bottom.Last(0) > 1 && bb.Main.Last(0) > 2 && bb.Top.Last(0) > 3) { //... }

 

Question #3:

I've done some preliminary performance testing using the C# StopWatch, and doing the following:

//This code runs faster
if (bb.Bottom[latestIndex] > 1&& bb.Main[latestIndex] > 2 && bb.Top[latestIndex] > 3) { //... }

//..than calling the .Last(0) or .LastValue function
if (bb.Bottom.Last(0) > 1&& bb.Main.Last(0) > 2 && bb.Top.Last(0) > 3) { //... }

gives some performance speed increases I'm guessing because of the overhead incurred running the "Last" and "LastValue" functions as opposed to directly accessing the array index.

Given what your team knows of the underlying indicator architecture implementation within cTrader, is this assessment correct?

 

Thank you :-)


@firemyst

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

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

firemyst
09 Oct 2019, 18:09

RE: Close the open position at a certain time

davidp13 said:

Hi,

What code should one add to close the open positions at lets say 3pm?

Thank you

//Rough sample to give you an idea to close at 3pm server time.
if (ServerTime.Hour == 15)
{
    foreach (Position p in Positions)
        ClosePosition(p);
}

//Rough sample to give you an idea to close 3pm according to your computer's time that's running the bot
if (DateTime.Now.Hour == 15)
{
    foreach (Position p in Positions)
        ClosePosition(p);
}

 


@firemyst

firemyst
09 Oct 2019, 18:02

RE:

augrust said:

hi would like to know if cbot availabel to code on Mac OS

thank you 

Probably only if you can run cTrader on MacOS, or have an emulator where you can run Windows based programs.


@firemyst

firemyst
09 Oct 2019, 17:40

Thanks for the feedback.

Your particular point:

_longDividend = Indicators.MovingAverage(_dataSeries, 14, MaType);

is where I was getting stuck the most, wondering how I can change the time frames.

Your other points about the indexes are well taken, and was me putzing around in the code trying to get something to debug and work with.

Anyway, I appreciate your time and feedback. I'll see what I can come up with since an EMA shouldn't be too hard to program up. :-)


@firemyst

firemyst
09 Oct 2019, 09:57

RE:

Panagiotis Charalampous said:

Hi FireMyst,

As explained above, data series are not "attached" to any timeframe. It is just a series of doubles. If you want to feed them with data from a lower timeframe, you can do it. There is no time property on anything else that relates an item of the data series to a timeframe.

Best Regards,

Panagiotis

So with the example code below, what am I doing wrong?

 

Compile and run the code. Add the indicator on your current chart twice: the first instance, add it with the chart's timeframe. Works fine. Add it a second time with a different timeframe, and nothing shows. All the values seem to return NaN, which I think is because it's not getting the values from the secondary timeframe parameter when it differs from the chart's time frame.

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

namespace cAlgo.Indicators
{
    [Levels(-25, 0, 25)]
    [Indicator("True Strength Index (Dave Loz)", AccessRights = AccessRights.None)]
    public class TSI : Indicator
    {
        [Parameter()]
        public TimeFrame SourceTimeFrame { get; set; }

        [Parameter("ShortPeriod", DefaultValue = 13, MinValue = 1)]
        public int ShortPeriod { get; set; }

        [Parameter("LongPeriod", DefaultValue = 21, MinValue = 1)]
        public int LongPeriod { get; set; }

        [Parameter("SignalPeriod", DefaultValue = 8, MinValue = 1)]
        public int SignalPeriod { get; set; }
        
        [Parameter("MA Type", DefaultValue = MovingAverageType.Exponential)]
        public MovingAverageType MaType { get; set; }

        [Output("Tsi", LineColor = "Green", LineStyle = LineStyle.Solid, PlotType =PlotType.Line, Thickness = 2)]
        public IndicatorDataSeries Tsi { get; set; }
        [Output("Signal", LineColor = "Red", LineStyle = LineStyle.Solid, PlotType = PlotType.Line, Thickness = 2)]
        public IndicatorDataSeries Signal { get; set; }
        [Output("Diff", LineColor = "Cyan", LineStyle = LineStyle.Solid, PlotType = PlotType.Histogram, Thickness = 3)]
        public IndicatorDataSeries Diff { get; set; }

        private MovingAverage _divisor;
        private MovingAverage _longDivisor;
        private MovingAverage _dividend;
        private MovingAverage _longDividend;

        private MarketSeries _marketSeries;
        private IndicatorDataSeries _dataSeries;
        private IndicatorDataSeries _dataSeriesAbs;
        private MovingAverage _signal;
        private IndicatorDataSeries _tsiSeries;

        protected override void Initialize()
        {
            if (SourceTimeFrame != null)
                _marketSeries = MarketData.GetSeries(Symbol.Name, SourceTimeFrame);
            else
                _marketSeries = MarketData.GetSeries(Symbol.Name, MarketSeries.TimeFrame);

            _dataSeries = CreateDataSeries();
            _dataSeriesAbs = CreateDataSeries();
            
            _longDividend = Indicators.MovingAverage(_dataSeries, LongPeriod, MaType);
            _dividend = Indicators.MovingAverage(_longDividend.Result, ShortPeriod, MaType);

            _longDivisor = Indicators.MovingAverage(_dataSeriesAbs, LongPeriod, MaType);
            _divisor = Indicators.MovingAverage(_longDivisor.Result, ShortPeriod, MaType);

            _tsiSeries = CreateDataSeries();
            _signal = Indicators.MovingAverage(_tsiSeries, SignalPeriod, MaType);
           
        }
        
        public override void Calculate(int index)
        {
            if (index < 1)
            {
                Tsi[index] = 0;
                return;
            }

            int altIndex = index;
            if (MarketSeries.TimeFrame != _marketSeries.TimeFrame)
            {
                altIndex = _marketSeries.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index]);
            }

            _dataSeries[index] = _marketSeries.Close[altIndex] - _marketSeries.Close[altIndex - 1];
            _dataSeriesAbs[index] = Math.Abs(_marketSeries.Close[altIndex] - _marketSeries.Close[altIndex - 1]);

            double tsiDivisor = _divisor.Result[altIndex];
            double tsiDividend = _dividend.Result[altIndex];

            if (Math.Abs(tsiDivisor) < double.Epsilon)
                _tsiSeries[index] = 0;
            else
                _tsiSeries[index] = 100.0 * tsiDividend / tsiDivisor;

            Tsi[index] = _tsiSeries[index];
            Signal[index] = _signal.Result[index];
            Diff[index] = _tsiSeries[index] - Signal[index];
        }
    }
}

 


@firemyst

firemyst
09 Oct 2019, 04:38

RE:

Panagiotis Charalampous said:

Hi FireMyst,

I am not sure what do you mean with

"I want to "attach" these dataseries to the _marketSeries timeframe, not the current chart's time frame"

DataSeries is not attached to any timeframe, it is just a series of doubles. Can you please elaborate?

Best Regards,

Panagiotis

I'll try to elaborate... this indicator is going to be displayed on a 2-Hour chart.

However, I also want the indicator, based on 1 hour chart data, to also be displayed on the 2 hour chart.

So essentially I'll have two instances of this indicator on the same chart -- one showing 1-hour time frame; the other based on 2-hour time frame data.

However, there appears to be no way to attached "_dataSeries" or "_dataSeriesAbs" to a timeframe other than the charts time frame. The reason for this appears to be because when I "CreateDataSeries()", it only creates a dataseries in the current chart's timeframe that the indicator is attached to, with no way to specify that I want a data series created with a timeframe that isn't the same timeframe as the one the chart is on.

Does that help?


@firemyst

firemyst
07 Oct 2019, 03:59

RE:

alex_mihail said:

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

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    [Levels(25)]
    public class ADXR : Indicator
    {

        [Parameter(DefaultValue = 14)]
        public int interval { get; set; }

        [Output("ADXR", Color = Colors.Orange)]
        public IndicatorDataSeries adxr { get; set; }

        [Output("DiMinus", Color = Colors.Red)]
        public IndicatorDataSeries diminus { get; set; }

        [Output("DiPlus", Color = Colors.Green)]
        public IndicatorDataSeries diplus { get; set; }

        [Output("Up", PlotType = PlotType.DiscontinuousLine, LineColor = "Green")]
        public IndicatorDataSeries Up { get; set; }

        [Output("Down", PlotType = PlotType.DiscontinuousLine, LineColor = "Red")]
        public IndicatorDataSeries Down { get; set; }

        [Output("Neutral", PlotType = PlotType.DiscontinuousLine, LineColor = "Gray")]
        public IndicatorDataSeries Neutral { get; set; }

        private DirectionalMovementSystem _dmi;

        protected override void Initialize()
        {
            _dmi = Indicators.DirectionalMovementSystem(interval);
        }

        public override void Calculate(int index)
        {
            var trend = _dmi.DIPlus.LastValue > _dmi.DIMinus.LastValue ? "Uptrend" : "Downtrend";
            var trend2 = _dmi.ADX.LastValue <= 20 ? "Ranging" : "Ranging";
            var upc = ((_dmi.DIPlus.IsRising()) && (_dmi.ADX.LastValue > 25)) ? Color.Green : Color.Gray;
            var downc = ((_dmi.DIPlus.IsFalling()) && (_dmi.ADX.LastValue > 25)) ? "Downtrend" : "Ranging";

            //adxr[index] = (_dmi.ADX[index] + _dmi.ADX[index - interval]) / 2;
            //diminus[index] = _dmi.DIMinus[index];
            //diplus[index] = _dmi.DIPlus[index];

            // Calculate value at specified index

                if (_dmi.ADX.LastValue > 25 && (_dmi.DIPlus.LastValue > _dmi.DIMinus.LastValue))
                {
                    Up[index - 1] = _dmi.ADX[index - 1];
                    Up[index] = _dmi.ADX[index];

                }

                else if (_dmi.ADX.LastValue > 25 && (_dmi.DIMinus.LastValue > _dmi.DIPlus.LastValue))
                {
                    Down[index - 1] = _dmi.ADX[index - 1];
                    Down[index] = _dmi.ADX[index];

                }

                else
                {
                    Neutral[index - 1] = _dmi.ADX[index - 1];
                    Neutral[index] = _dmi.ADX[index];
                }
        }
    }
}

Here is what I have so far but I would like to draw an X or some sort of marker when the price crosses below or above the MA - anyone got an example I could work off?

If you want to draw text on a chart, Chart.DrawText is your friend:

Example:

Chart.DrawText("X text", "X", MarketSeries.Close.Count - 1, Symbol.Bid, Color.Goldenrod);

You can also search for examples:

https://ctrader.com/search?q=DrawText


@firemyst

firemyst
07 Oct 2019, 03:52

Two Brokers, Pepperstone and IC Markets, have their cTrader servers based in London.

If you sign up with NYC Servers, you can arrange to have your VPS based in their London data center for best possible speed. If you are a Pepperstone Client and you trade 15 lots or more per month you are eligible for their free VPS service. They also offer 20% - 25% off all their VPS services regardless of how much you trade with Pepperstone.

 


@firemyst

firemyst
07 Oct 2019, 03:42

RE:

Be Rich said:

Where are the symbol digits stored? I need to work with them but I do not find. Thanks. 

Symbol.Digits ?


@firemyst

firemyst
07 Oct 2019, 03:38 ( Updated at: 21 Dec 2023, 09:21 )

RE:

GoldnOil750 said:

Hi,

the new version is highly unstable and eating around 1.3 GB Memory and upto 40% of CPU time (it fluctuates a lot)....   ver 3.5 was ok and more stable.  Have attached the screen shot of the cTrader ver 3.6 from TradersWay compared to ver 3.5 from IC Market and FxPro and you can see how much memory and CPU % each is using....

 

only one chart is opened on TradersWay cTrader Platform ver 3.5 while FxPRo and IC Markets have many charts and indicators attached. Have un-installed and re-installed the TradersWay cTrader ver 3.6 platform also but no improvement...  right now the market is very calm but still it is highly CPU hungry....

I am using core i7 4th gen CPU with 16GB mem and a SSD hard drive.  

 

hope Spotware fixes this issue before more Broker release this version or if Spotware and others can attach a screen shot of the memory usage from different brokers and maybe something is wrong at TradersWay Brokers cTrader platform...

 

Regards,

SKhan

I think what SpotWare should consider implementing is a way to clear out previous indicator data when running bots, or limit the range of data stored.

For example, create a bot and load any indicator. It will possible have data from well over 2000 ticks ago in the IndicatorDataSeries object. Now imagine your bot uses at least 3 indicators. That sucks up memory, and subsequently CPU time to navigate the object to find data.

The majority of bots I've seen don't bother or even look at data from more than 8 hours ago, so we should be given a way to clear that data out to reduce memory and cpu footprint.


@firemyst

firemyst
04 Oct 2019, 10:52

RE: RE:

Anka Software said:

Panagiotis Charalampous said:

Hi GammaQuant,

Thanks for the links. There is a mention in one of them that you could use static collections to share variables between cBots but this is not possible. I assume that the person that suggested this never actually tried it. The reason that this cannot happen is that you cannot compile more than two cBots in the same dll. As a result, each cBot exists in a different dll and they cannot share variables between them. If you need to share information between cBots maybe you can consider reading and writing to a file accessible by both. Let me know if this suggestion helps.

Best Regards,

Panagiotis

Hi,

   One clarification - could multiple instances of same cBot, share a static variable?

 

Regards

Vivek

Yes.

See this updated thread:

https://ctrader.com/forum/calgo-support/22028?page=1#3

 


@firemyst