indicator with extern data
indicator with extern data
16 Sep 2020, 09:24
Dear community, dear Panagiotis,
I have a .csv file, containing date and a value, separated and for a long time period, let's say 2 years, one datapoint per day. Is it possible to construct an own indicator within cTrader? If yes - what would be the correct steps / commands to get an idea how this will work?
Kindest regards to all,
Replies
xabbu
16 Sep 2020, 09:43
Hey Panagiotis,
thanks for the always fast reply! I would like to have a clue how to read the .csv file into the cTrader indicator code and how to draw a simple line, which should connect the imported datapoints. The indicator should draw a line. Is this specific enough? And thank you in advance, Panagiotis...
@xabbu
PanagiotisCharalampous
16 Sep 2020, 09:50
Hi xabbu,
Check here on how to read a csv file using C#. To draw lines you can use DrawTrendLine() method.
Best Regards,
Panagiotis
@PanagiotisCharalampous
xabbu
06 Oct 2020, 10:34
Dear Panagiotis,
thank you, my "The indicator should draw a line" and your "use DrawTrendLine() method" might be a not exactly what I ment, sorry for the confusion. I try to start again:
I have an csv with data pairs:
Date,Value
11/1/2007,8.09
11/2/2007,8.12
11/5/2007,7.98
After importing that into cTrader (I did not manage that because of missing programming skills...) I would like that these data draw a line like an ordinary indicator, lets's say like the ATR. Each day has a value (closing price) and the values for each day should be connected like the ATR line.
Kindest regards
@xabbu
PanagiotisCharalampous
06 Oct 2020, 10:38
Hi xabbu,
I am still not sure what information are you looking for. Can you make your question more specific? If you just want to draw imported values, then just add them to an IndicatorDataSeries and the indicator will do the job for you. Check any of the sample indicators available in cTrader on how to do this.
Best Regards,
Panagiotis
@PanagiotisCharalampous
Shares4us
06 Oct 2020, 10:39
RE:
Each day has a value (closing price) and the values for each day should be connected like the ATR line.
Maybe look at ADR indicator and adapt to closingprice;
@Shares4us
xabbu
06 Oct 2020, 10:46
Okay - thanks again. I have to import the csv data into cTrader and than bring them to an IndicatorDataSeries.
For the importing part of the question, Panagiotis: Is there an easy to implemente example how to do this? I read all the resources here and the hints you gave to external sites, but it's still confusing to me. Can I do it in cTrader or do I have to use Visual Studio for that.
Is there maybe an free indicator or cBot out there, which does a similar job I can look at and get some clues?
@xabbu
PanagiotisCharalampous
06 Oct 2020, 11:05
Hi xabbu,
It cannot get simpler than the link I posted above. Here is again the code sample
using(var reader = new StreamReader(@"C:\test.csv"))
{
List<string> listA = new List<string>();
List<string> listB = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(';');
listA.Add(values[0]);
listB.Add(values[1]);
}
}
You can do it anywhere you want. If you cannot implement it, then maybe you should ask for professional assistance.
Best Regards,
Panagiotis
@PanagiotisCharalampous
xabbu
07 Oct 2020, 13:21
Hello Panagiotis,
good news, thanks to your help, I managed to read a sample .csv file into an indicator. I read the site you gave me and get the best result with this adapted solution (and maybe it could help others when searching "cTrader import / importing csv file / data":
using System;
using System.IO;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
using Microsoft.VisualBasic.FileIO;
using System.Globalization;
namespace cAlgo
{
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FileSystem)]
public class NewIndicator : Indicator
{
[Output("Main")]
public IndicatorDataSeries Result { get; set; }
protected override void Initialize()
{
var path = "C:\\Users\\xabbu\\Desktop\\evzTestklein.csv";
//var path = "C:\\Users\\xabbu\\Desktop\\evzTest Kopie.csv";
using (TextFieldParser csvParser = new TextFieldParser(path))
{
csvParser.CommentTokens = new string[]
{
"#"
};
csvParser.SetDelimiters(new string[]
{
";"
});
csvParser.HasFieldsEnclosedInQuotes = true;
// Skip the row with the column names
csvParser.ReadLine();
while (!csvParser.EndOfData)
{
// Read current line fields, pointer moves to the next line.
string[] fields = csvParser.ReadFields();
string _datefield = fields[0];
string _evzValue = fields[1];
Print("Datum. " + Convert.ToDateTime(_datefield, CultureInfo.InvariantCulture) + " $EVZ: " + Convert.ToDouble(_evzValue, CultureInfo.InvariantCulture));
}
}
}
public override void Calculate(int index)
{
}
}
}
I could also convert the fields in the .csv-file to an date and double value and printed it to the log:
There are so many sources of C# knowledge and tutorials out there (I bought some c# courses on Udemy), but in combination with cTrader the internet wisdom is very limited. I found only 2 tutorials about cTrader / cAlgo programming to buy. One is extremly bad and outdatet and hardly to understand. The other one I bought for around $50 but it touches only the "standard" questions an procedures.
I think that is very frustrating, because cTrader is THE modern platform and years in advance compaired to the MarkeT-Leaders (-;... BUT: the interaction between the platform and the users in meaning of the choice of cBots and indicators is very small compared to the other platforms, if one compares the resources and indicators / bots available...
I would like to ask for your knowledge and kind help again:
How can I now, with this imported data from the .csv file, create the indicator data series correct, so that the imported values (date, value) can form the output of an cTrader indicator?
Kindest regards,
@xabbu
xabbu
07 Oct 2020, 15:11
( Updated at: 21 Dec 2023, 09:22 )
Dear Panagiotis,
I walked a few steps further, but the final piece seems missing: the code produces only a line with one value (the last one)...
using System;
using System.IO;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
using Microsoft.VisualBasic.FileIO;
using System.Globalization;
namespace cAlgo
{
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FileSystem)]
public class CSVIMPORTNNFX : Indicator
{
[Output("Main")]
public IndicatorDataSeries Result { get; set; }
public string _datefield;
public string _evzValue;
protected override void Initialize()
{
var path = "C:\\Users\\xabbu\\Desktop\\evzTest Kopie.csv";
//\\evzTest Kopie.csv";
using (TextFieldParser csvParser = new TextFieldParser(path))
{
csvParser.CommentTokens = new string[]
{
"#"
};
csvParser.SetDelimiters(new string[]
{
";"
});
csvParser.HasFieldsEnclosedInQuotes = true;
// Skip the row with the column names
csvParser.ReadLine();
while (!csvParser.EndOfData)
{
// Read current line fields, pointer moves to the next line.
string[] fields = csvParser.ReadFields();
_datefield = fields[0];
_evzValue = fields[1];
}
}
}
public override void Calculate(int index)
{
Print("Datum. " + Convert.ToDateTime(_datefield, CultureInfo.InvariantCulture) + " $EVZ: " + Convert.ToDouble(_evzValue, CultureInfo.InvariantCulture));
Result[index] = Convert.ToDouble(_evzValue, CultureInfo.InvariantCulture);
}
}
}
@xabbu
PanagiotisCharalampous
08 Oct 2020, 07:56
Hi xabbu,
This happens because you are reading only the last value of the indicator here
while (!csvParser.EndOfData)
{
// Read current line fields, pointer moves to the next line.
string[] fields = csvParser.ReadFields();
_datefield = fields[0];
_evzValue = fields[1];
}
You should be using collections e.g. a list and store all the values, not only the last one.
Best Regards,
Panagiotis
@PanagiotisCharalampous
xabbu
08 Oct 2020, 13:48
RE:
Dear Panagiotis,
I'm now back to the first solution you have proposed, and it seems that this short code reads the csv file - but how I can get now the imported values into the IndicatorDataSeries to get the demanded result...?
I i appreciate your kind help very much!
Thats my code in this moment of time:
using System;
using System.IO;
using System.Collections.Generic;
using System.Globalization;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
namespace cAlgo
{
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FileSystem)]
public class NewIndicator : Indicator
{
[Parameter(DefaultValue = 0.0)]
public double Parameter { get; set; }
[Output("Main")]
public IndicatorDataSeries Result { get; set; }
string[] listA;
string[] listB;
protected override void Initialize()
{
using (var reader = new StreamReader("C:\\Users\\xabbu\\Desktop\\evzTestklein.csv"))
{
List<string> listA = new List<string>();
List<string> listB = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(';');
listA.Add(values[0]);
listB.Add(values[1]);
}
foreach (var element in listA)
Print(element);
foreach (var element in listB)
Print(element);
}
}
public override void Calculate(int index)
{
}
}
}
PanagiotisCharalampous said:
Hi xabbu,
It cannot get simpler than the link I posted above. Here is again the code sample
using(var reader = new StreamReader(@"C:\test.csv")) { List<string> listA = new List<string>(); List<string> listB = new List<string>(); while (!reader.EndOfStream) { var line = reader.ReadLine(); var values = line.Split(';'); listA.Add(values[0]); listB.Add(values[1]); } }
You can do it anywhere you want. If you cannot implement it, then maybe you should ask for professional assistance.
Best Regards,
Panagiotis
@xabbu
fxtradersystems
09 Oct 2020, 13:09
Custom Indicator Loading from Daily CSV
Hi all,
Seems like a more efficient way to store information would be to initalise and load a key-value pair dictionary Dictionary<DateTime, double> such that you could search for the appropriate datetime amongst the keys, and return the double value for that index.
As we're using daily data, you could possibly get away with finding the date using:
DateTime currentDate = Bars.OpenTimes[index] - in the Calculate() method.
I am unsure as to whether this yet introduces a look-ahead bias (ie. it returns data from later that day, whereas it should return data from the day before); and it almost certainly won't be able to handle data not on a daily TF.
I whipped up some code for the idea here. Let me know if it works / any errors (particularly on the look-ahead bias), and I can update.
Warning: currently has to be stored exactly in the csv format: date;double (newline). @xabbu, if you are happy to send the CSV, I can tailor this for you.
using System;
using System.IO;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
using System.Globalization;
namespace cAlgo
{
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
public class DailyCustomIndi : Indicator
{
[Parameter("Path to CSV:")]
public string Path { get; set; }
[Output("Main")]
public IndicatorDataSeries Result { get; set; }
// Set up a dictionary to hold the dates and values
Dictionary<DateTime, double> keyValuePairs = new Dictionary<DateTime, double>();
int count;
protected override void Initialize()
{
keyValuePairs = new Dictionary<DateTime, double>();
count = 0;
Print("keyValuePairs initialised");
using (var reader = new StreamReader(Path))
{
Print("Streamer initialised");
while (!reader.EndOfStream)
{
// Use the reader to read in the lines
var line = reader.ReadLine();
var values = line.Split(';');
// Split out dates and values, and then convert them to datetime and double
string stringDate = values[0];
string stringIndi = values[1];
if (count != 0)
{
DateTime date = Convert.ToDateTime(stringDate, CultureInfo.InvariantCulture);
DateTime shortDate = CompactDate(date);
double doubleIndi = Double.Parse(stringIndi);
Print(shortDate.ToString() + ":" + doubleIndi.ToString());
// Add to dictionary
keyValuePairs.Add(shortDate, doubleIndi);
}
else
{
count = 1;
}
}
Print("Streamer finished");
}
}
public override void Calculate(int index)
{
// Get the datetime of the current bar (at Index)
DateTime indexDateTime = Bars.OpenTimes[index];
DateTime shortIndexDate = CompactDate(indexDateTime);
double indexResult;
// Find the appropriate dateTime in the dictionary and then add to result:
bool findSuccessful = keyValuePairs.TryGetValue(shortIndexDate, out indexResult);
Print(shortIndexDate.ToString() + ": " + findSuccessful);
if (findSuccessful)
{
Result[index] = indexResult;
}
else
{
Result[index] = double.NaN;
}
}
public DateTime CompactDate(DateTime longDate)
{
DateTime shortDate = new DateTime(longDate.Year, longDate.Month, longDate.Day);
return shortDate;
}
}
}
@fxtradersystems
xabbu
09 Oct 2020, 14:17
Dear Panagiotis,
I'm now back to the first solution you have proposed, and it seems that this short code reads the csv file - but how I can get now the imported values into the IndicatorDataSeries to get the demanded result...?
I i appreciate your kind help very much!
Thats my code in this moment of time:
using System;
using System.IO;
using System.Collections.Generic;
using System.Globalization;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
namespace cAlgo
{
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FileSystem)]
public class NewIndicator : Indicator
{
[Parameter(DefaultValue = 0.0)]
public double Parameter { get; set; }
[Output("Main")]
public IndicatorDataSeries Result { get; set; }
string[] listA;
string[] listB;
protected override void Initialize()
{
using (var reader = new StreamReader("C:\\Users\\xabbu\\Desktop\\evzTestklein.csv"))
{
List<string> listA = new List<string>();
List<string> listB = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(';');
listA.Add(values[0]);
listB.Add(values[1]);
}
foreach (var element in listA)
Print(element);
foreach (var element in listB)
Print(element);
}
}
public override void Calculate(int index)
{
}
}
}
@xabbu
fxtradersystems
09 Oct 2020, 15:06
RE: Custom Indicator Loading from Daily CSV
fxtradersystems said:
Hi all,
Seems like a more efficient way to store information would be to initalise and load a key-value pair dictionary Dictionary<DateTime, double> such that you could search for the appropriate datetime amongst the keys, and return the double value for that index.
As we're using daily data, you could possibly get away with finding the date using:
DateTime currentDate = Bars.OpenTimes[index] - in the Calculate() method.
I am unsure as to whether this yet introduces a look-ahead bias (ie. it returns data from later that day, whereas it should return data from the day before); and it almost certainly won't be able to handle data not on a daily TF.
I whipped up some code for the idea here. Let me know if it works / any errors (particularly on the look-ahead bias), and I can update.
Warning: currently has to be stored exactly in the csv format: date;double (newline). @xabbu, if you are happy to send the CSV, I can tailor this for you.
using System; using System.IO; using System.Collections.Generic; using cAlgo.API; using cAlgo.API.Internals; using cAlgo.API.Indicators; using cAlgo.Indicators; using System.Globalization; namespace cAlgo { [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)] public class DailyCustomIndi : Indicator { [Parameter("Path to CSV:")] public string Path { get; set; } [Output("Main")] public IndicatorDataSeries Result { get; set; } // Set up a dictionary to hold the dates and values Dictionary<DateTime, double> keyValuePairs = new Dictionary<DateTime, double>(); int count; protected override void Initialize() { keyValuePairs = new Dictionary<DateTime, double>(); count = 0; Print("keyValuePairs initialised"); using (var reader = new StreamReader(Path)) { Print("Streamer initialised"); while (!reader.EndOfStream) { // Use the reader to read in the lines var line = reader.ReadLine(); var values = line.Split(';'); // Split out dates and values, and then convert them to datetime and double string stringDate = values[0]; string stringIndi = values[1]; if (count != 0) { DateTime date = Convert.ToDateTime(stringDate, CultureInfo.InvariantCulture); DateTime shortDate = CompactDate(date); double doubleIndi = Double.Parse(stringIndi); Print(shortDate.ToString() + ":" + doubleIndi.ToString()); // Add to dictionary keyValuePairs.Add(shortDate, doubleIndi); } else { count = 1; } } Print("Streamer finished"); } } public override void Calculate(int index) { // Get the datetime of the current bar (at Index) DateTime indexDateTime = Bars.OpenTimes[index]; DateTime shortIndexDate = CompactDate(indexDateTime); double indexResult; // Find the appropriate dateTime in the dictionary and then add to result: bool findSuccessful = keyValuePairs.TryGetValue(shortIndexDate, out indexResult); Print(shortIndexDate.ToString() + ": " + findSuccessful); if (findSuccessful) { Result[index] = indexResult; } else { Result[index] = double.NaN; } } public DateTime CompactDate(DateTime longDate) { DateTime shortDate = new DateTime(longDate.Year, longDate.Month, longDate.Day); return shortDate; } } }
Hi all,
I updated this^ comment, so that this code now works.
> Changed access permissions to full so that it can access the csv (you can also use FileSystem).
> Added a function to cut down the DateTimes so that the Bars.OpenTimes and dictionary keys were in the same format.
> Added a count = 0 to avoid reading the csv titles as input data (hacky I know, but works).
To be clear: ^that comment now gives output from the csv snippet xabbu sent me.
Hope this is useful!
Cheers,
Sam (fxtradersystems.com)
@fxtradersystems
bonedrak
15 May 2022, 05:28
( Updated at: 21 Dec 2023, 09:22 )
RE: indicator data series from external data
xabbu said:
Hello Panagiotis,
good news, thanks to your help, I managed to read a sample .csv file into an indicator. I read the site you gave me and get the best result with this adapted solution (and maybe it could help others when searching "cTrader import / importing csv file / data":
using System; using System.IO; using System.Collections.Generic; using cAlgo.API; using cAlgo.API.Internals; using cAlgo.API.Indicators; using cAlgo.Indicators; using Microsoft.VisualBasic.FileIO; using System.Globalization; namespace cAlgo { [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FileSystem)] public class NewIndicator : Indicator { [Output("Main")] public IndicatorDataSeries Result { get; set; } protected override void Initialize() { var path = "C:\\Users\\xabbu\\Desktop\\evzTestklein.csv"; //var path = "C:\\Users\\xabbu\\Desktop\\evzTest Kopie.csv"; using (TextFieldParser csvParser = new TextFieldParser(path)) { csvParser.CommentTokens = new string[] { "#" }; csvParser.SetDelimiters(new string[] { ";" }); csvParser.HasFieldsEnclosedInQuotes = true; // Skip the row with the column names csvParser.ReadLine(); while (!csvParser.EndOfData) { // Read current line fields, pointer moves to the next line. string[] fields = csvParser.ReadFields(); string _datefield = fields[0]; string _evzValue = fields[1]; Print("Datum. " + Convert.ToDateTime(_datefield, CultureInfo.InvariantCulture) + " $EVZ: " + Convert.ToDouble(_evzValue, CultureInfo.InvariantCulture)); } } } public override void Calculate(int index) { } } }
I could also convert the fields in the .csv-file to an date and double value and printed it to the log:
There are so many sources of C# knowledge and tutorials out there (I bought some c# courses on Udemy), but in combination with cTrader the internet wisdom is very limited. I found only 2 tutorials about cTrader / cAlgo programming to buy. One is extremly bad and outdatet and hardly to understand. The other one I bought for around $50 but it touches only the "standard" questions an procedures.
I think that is very frustrating, because cTrader is THE modern platform and years in advance compaired to the MarkeT-Leaders (-;... BUT: the interaction between the platform and the users in meaning of the choice of cBots and indicators is very small compared to the other platforms, if one compares the resources and indicators / bots available...
I would like to ask for your knowledge and kind help again:
How can I now, with this imported data from the .csv file, create the indicator data series correct, so that the imported values (date, value) can form the output of an cTrader indicator?
Kindest regards,
@bonedrak
... Deleted by UFO ...
... Deleted by UFO ...
bonedrak
16 May 2022, 11:12
RE: RE: Indicator data series from external data
amusleh said:
bonedrak said:
Hi xabbu
did you ever find a solution to this
thanks
anthony
Hi,
Solution for which issue? Reading CSV file?
For creating an indicator data series from external source, either csv or json.
Thanks
anthony
@bonedrak
... Deleted by UFO ...
amusleh
16 May 2022, 11:18
RE: RE: RE: Indicator data series from external data
bonedrak said:
amusleh said:
bonedrak said:
Hi xabbu
did you ever find a solution to this
thanks
anthony
Hi,
Solution for which issue? Reading CSV file?
For creating an indicator data series from external source, either csv or json.
Thanks
anthony
Hi,
You can easily do that by reading the file, de-serializing it to an object, and then using them to populate an indicator data series.
For reading files: How to read from a text file - C# Programming Guide | Microsoft Docs
For CSV files use CsvHelper: A .NET library for reading and writing CSV files. Extremely fast, flexible, and easy to use. | CsvHelper (joshclose.github.io)
For JSON use System.Text.Json (cTrader 4.2 >): How to serialize and deserialize JSON using C# - .NET | Microsoft Docs
@amusleh
bonedrak
16 May 2022, 11:21
RE: RE: RE: RE: Indicator data series from external data
amusleh said:
bonedrak said:
amusleh said:
bonedrak said:
Hi xabbu
did you ever find a solution to this
thanks
anthony
Hi,
Solution for which issue? Reading CSV file?
For creating an indicator data series from external source, either csv or json.
Thanks
anthony
Hi,
You can easily do that by reading the file, de-serializing it to an object, and then using them to populate an indicator data series.
For reading files: How to read from a text file - C# Programming Guide | Microsoft Docs
For CSV files use CsvHelper: A .NET library for reading and writing CSV files. Extremely fast, flexible, and easy to use. | CsvHelper (joshclose.github.io)
For JSON use System.Text.Json (cTrader 4.2 >): How to serialize and deserialize JSON using C# - .NET | Microsoft Docs
The last part is what I’m wondering about. Using the data to populate an indicator data series. How do you do that.
@bonedrak
amusleh
16 May 2022, 11:47
RE: RE: RE: RE: RE: Indicator data series from external data
bonedrak said:
The last part is what I’m wondering about. Using the data to populate an indicator data series. How do you do that.
Hi,
Once you read the data from a file or any other source, deserialize it to appropriate types, then insert it on an indicator data series.
Use the bars open times GetIndexByTime method to find the appropriate index for each value of the data, the data must be time stamped.
@amusleh
PanagiotisCharalampous
16 Sep 2020, 09:34
Hi xabbu,
Yes this is possible but there is no recipe for this. It all depends on what is your indicator doing. What exactly do you need to find out e.g. how to read a csv file? If you can make more specific questions, we can help you by answering them.
Best Regards,
Panagiotis
Join us on Telegram
@PanagiotisCharalampous