Replies

JohnK
03 Jun 2020, 15:20

RE:

Hi Panagiotis,

I appreciate the feedback, thank you


@JohnK

JohnK
24 Apr 2020, 12:50

RE:

Hi Panagiotis,

Thanks for the info! Based on that, I've installed the library version that supports 4.0 & haven't needed to re-target the project.

All seems to work as expected at first glance. Seems perhaps I was running into compatibility issues between what cTrader & TPL Dataflow support.

 

If anyone else is looking for the library version supporting .NET 4, you can get it from NuGet with:

PM> Install-Package HomeLab.Tpl.DataFlow -Version 4.0.0


@JohnK

JohnK
24 Apr 2020, 11:52

RE:

So even with re-targeting, there are still issues...

When adding the reference through the cTrader platform & re-targeting to 4.5

-> Error: ...is inaccessible due to its protection level

When adding it in VS with NuGet package installer after re-targeting to 4.5:

-> Error: ...is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=...


@JohnK

JohnK
24 Apr 2020, 11:10

RE:

PanagiotisCharalampous said:

Hi JohnK,

Can we also have the cBot source code to reproduce this issue?

Best Regards,

Panagiotis 

Join us on Telegram

Hi Panagiotis,

Thanks for the reply. There is "no code" as yet - I've just created a new cBot & tried to add the reference.

To see if the reference works, I've tried to type e.g. var actionBlock = new ActionBlock<int>(n => Print(n));


@JohnK

JohnK
02 May 2019, 12:28

RE:

Hi Panagiotis,

Thank you very much for your solution, it's very much appreciate. It appears to work just fine and solves my issue.

Just a couple of related questions:

1) Should the index in the indicator be indexed in the following way?

X_Series[index] = X_Source.Close[X_Source.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index])];
Y_Series[index] = Y_Source.Close[Y_Source.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index])];

2) Is there a way to link the bot to the indicator without having to manually enter the chart symbol for the indicator? I've put an example below to illustrate what I mean. I know the example I'm giving doesn't work, and in this context of the indicator alone it's also useless, but just to understand the ways in which the API may be called.

[Parameter("X Series")]
public DataSeries X_Source { get; set; }

[Parameter("Y Series")]
public DataSeries Y_Source { get; set; }

private MarketSeries X_Series;
private MarketSeries Y_Series;

protected override void Initialize()
{
	X_Series = MarketData.GetSeries(X_Source.Symbol.Code, TimeFrame);
	Y_Series = MarketData.GetSeries(Y_Source.Symbol.Code, TimeFrame);
}

3) As I understand it there's no dropdown menu option for selecting a symbol (only manual input as a string). I see there is a "vote for feature" concerning "custom parameters" which is planned (since August 2018) to be implemented in a following update. I just wonder if a dropdown for symbols will also be implemented seeing as it's a somewhat standard parameter?

[Ref.: http://vote.spotware.com/forums/229166-ideas-and-suggestions-for-ctrader-and-calgo/suggestions/5502949-custom-parameters]

 

Again, many thanks for your support.

John


@JohnK

JohnK
30 Apr 2019, 15:02

RE:

Panagiotis Charalampous said:

Hi John,

You need to make sure you are using corresponing indices. See below the correct way to implement it

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

namespace cAlgo.Indicators
{
    [Indicator("P_C_Source", IsOverlay = false, ScalePrecision = 5)]
    public class P_C_Source : Indicator
    {
        [Output("P_C_Source", LineColor = "Red", LineStyle = LineStyle.Solid)]
        public IndicatorDataSeries Result { get; set; }

        [Parameter()]
        public string SymbolCode { get; set; }

        private MarketSeries PC_Symbol_series;
        private Symbol PC_Symbol;

        protected override void Initialize()
        {
            PC_Symbol = MarketData.GetSymbol(SymbolCode);
            PC_Symbol_series = MarketData.GetSeries(PC_Symbol, TimeFrame);
        }

        public override void Calculate(int index)
        {
            Result[index] = PC_Symbol_series.Close[PC_Symbol_series.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index])];
        }
    }
}

Best Regards,

Panagiotis

Hi Panagiotis,

The indicator now appears to be functioning as intended. Very much appreciate the support!

Thank you,

John


@JohnK

JohnK
30 Apr 2019, 14:54

RE:

Panagiotis Charalampous said:

Hi JohnK,

Please share with us the indicator code as well.

Best Regards,

Panagiotis

Hi Panagiotis,

Thank you for the reply & support with my issue. Below you'll find the cBot & indicator codes. You'll notice they don't really "do" anything - simply just a trial to make sure that I can call & use the multi-symbol functionality correctly.

Indicator code:

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

namespace cAlgo
{
    [Indicator(IsOverlay = false, AccessRights = AccessRights.None)]
    public class Bot_Indicator_v1 : Indicator
    {
        [Parameter("X Series")]
        public DataSeries X_Source { get; set; }

        [Parameter("Y Series")]
        public DataSeries Y_Source { get; set; }

        [Output("X Series", PlotType = PlotType.Line, LineColor = "#FFFF0000", LineStyle = LineStyle.Solid)]
        public IndicatorDataSeries X_Series { get; set; }

        [Output("Y Series", PlotType = PlotType.Line, LineColor = "#FF000000", LineStyle = LineStyle.Solid)]
        public IndicatorDataSeries Y_Series { get; set; }

        protected override void Initialize()
        {
        }

        public override void Calculate(int index)
        {
            X_Series[index] = X_Source[index];
            Y_Series[index] = Y_Source[index];
        }
    }
}

cBot code:

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

namespace cAlgo
{
    [Robot(AccessRights = AccessRights.None)]
    public class BotTrialv1 : Robot
    {
        [Parameter("X-Series")]
        public string SymbolCode { get; set; }

        private const string Long_label = "BotTrialv1_Long";
        private const string Short_label = "BotTrialv1_Short";

        private Symbol X_Symbol;
        private MarketSeries X_Series;
        private MarketSeries Y_Series;
        private Bot_Indicator_v1 BI;

        protected override void OnStart()
        {
            X_Symbol = MarketData.GetSymbol(SymbolCode);
            X_Series = MarketData.GetSeries(X_Symbol, TimeFrame);
            Y_Series = MarketData.GetSeries(Symbol, TimeFrame);
            BI = Indicators.GetIndicator<Bot_Indicator_v1>(X_Series.Close, Y_Series.Close);
        }

        protected override void OnBar()
        {
        }
    }
}

Again, I appreciate your support on this issue.

John


@JohnK

JohnK
02 Feb 2017, 16:17

RE:

OK, I see. That explanation made it clearer for me, thanks. I think I'm starting to get my head around it a bit now.

I should say thanks! Not only for providing the different solutions but also for helping me understand these things a bit better. Definitely much appreciated!


@JohnK

JohnK
01 Feb 2017, 20:40

RE:

 

Thanks for taking the time and effort to respond and offer solutions. It's much appreciated!

I've had the chance now to look at the two solutions you gave. As I said I'm new to coding my own indicators and coding in general so I’m a bit slow at this. I've just been trying to get my head around what you've shown.

Looking at your first solution...

What I see it does:

Creates an indicator value for each Chart-TF index point / bar.

Indicator value @Custom-TF index point = Custom-TF value.

Indicator value between last Custom-TF index and current Chart-TF index = Current Close value (= same for both Custom-TF & Actual-TF) = Current price.

How the data affects downstream calculations/referenced indicators:

Any referenced indicator which is calculated using e.g. “Source[index]” calculates only values at the Custom-TF index – no in between values are considered from the Chart-TF. Plotted calculated values remain.

Looking at your second solution...

What I see it does:

(Without else clause)

Creates an indicator value only for each Chart-TF index point / bar which coincides with the Custom-TF index.

 (With else clause)

Additionally creates an indicator value for the current Chart-TF index point = Current Close value (= same for both Custom-TF & Actual-TF) = Current price.

How the data affects downstream calculations/referenced indicators:

Any referenced indicator which is calculated using e.g. “Source[index]” calculates only values at the Custom-TF index – no in between values are considered from the Chart-TF. Plotted calculated values disappear.

I’ve tried to follow and understand your code. I assume the reason why the downstream calculations suffer is because in cases where the Custom-TF & Chart-TF don’t coincide, the result is not Result[index] but Result[i] - and and indicator calculating using Source[index] doesn't pick-up the Result[i]...?

Also, I have no idea how the “lastIdx” works. Completely lost here. No idea what it is or how it’s used. Seems to come out of nowhere, fits everywhere, and is very useful.


@JohnK

JohnK
01 Feb 2017, 13:17

RE:

tmc. said:

Hi John, you are reading close value of 3-minute chart every minute. Therefore it returns you close value of a bar that is still in the progress. You would need to repaint previous values of all indexes that are within one 3-minute chart bar in order to achieve flat lines as in the history where you can read only OHLC values of closed bars. I hope it makes any sense.

Hi tmc

I appreciate you getting back to me. As I mentioned, my "temporary solution" for repainting has been to refresh the chart periodically. Do you know of a way in which the indicator can be made to repaint itself upon closing the 3m bar? And I guess subsequently any indicators referencing this if need be?


@JohnK