Dark Theme
Light Theme
Trading Articles
Article Categories
Article Tools
Welcome to NexusFi: the best trading community on the planet, with over 150,000 members Sign Up Now for Free
Genuine reviews from real traders, not fake reviews from stealth vendors
Quality education from leading professional traders
We are a friendly, helpful, and positive community
We do not tolerate rude behavior, trolling, or vendors advertising in posts
We are here to help, just let us know what you need
You'll need to
register in order to view the content of the threads and start contributing to our community.
It's free for basic access, or support us by becoming an Elite Member -- see if you qualify for a discount below.
-- Big Mike, Site Administrator
(If you already have an account, login at the top of the page)
Help exporting NT8 data to csv via indicator
Updated June 20, 2023
trending_up
569 views
thumb_up
1 thanks given
group
3 followers
forum
3 posts
attach_file
1 attachments
Help exporting NT8 data to csv via indicator
May 9th, 2023, 06:03 AM
Seattle, WA
Experience: Intermediate
Platform: NinjaTrader 8
Broker: AMP/CQG
Trading: Indices
Frequency: Every few days
Duration: Minutes
Posts: 96 since Feb 2012
Thanks Given: 1,047
Thanks Received: 96
Has anyone created a Ninjatrader 8 indicator that exports live tick data to a .csv? I want to export time, Price, OHLC, Volume and a few custom indicator values. I just need a starting point in terms of C#. I haven't worked in C# in many years and am hoping somoene else has started or created a version of this that I can use as a template. Be grateful for any help.
Our life is our own today. Tomorrow you will be dust, a shade, a tale that is told. Live mindful of death, the hour flies.
Can you help answer these questions from other members on NexusFi?
Best Threads (Most Thanked) in the last 7 days on NexusFi
May 10th, 2023, 03:31 AM
Huntsville, AL
Posts: 13 since Feb 2022
Thanks Given: 9
Thanks Received: 5
It's been over a year since I've played with this code, but I believe it still works with the latest NT8 update. That is, I haven't seen any write errors. Please don't be shy with suggestions, as well, since this was my first go in C# to write to CSV.
Here is a routine for recording prices of a day's open, market open, high, and low prices. I'll throw in something for reading these values from CSV just for completeness, such as for painting historical data. I'm leaving some of the regular items out (e.g. some SetDefaults items) and the algorithm for actually finding these values since this isn't what I've ever used it for:
Code
#region Fields
private double _open = 0, _marketOpen = 0, _low = 0, _high = 0;
private DateTime _currentDate, _previousDate;
private Data.SessionIterator _sessionIterator;
private static ReaderWriterLockSlim _readWriteLock;
private const int _retries 3;
private const int _delay = 1000;
private string _filepath = Path.Combine(new string[] { NinjaTrader.Core.Globals.UserDataDir, "bin", "Custom", "Indicators" });
private bool _fileExists;
#endregion
#region Properties
[NinjaScriptProperty]
[Display(Order = 1800, ResourceType = typeof(Custom.Resource), Name = "Filename", GroupName = "NinjaScriptParameters")]
public string Filename
{ get; set; }
#endregion
#region Methods
protected override void OnStateChange()
{
base.OnStateChange();
switch (State)
{
case State.SetDefaults:
...
Filename = @"OMoHL.csv";
break;
case State.Configure:
_currentDate = _previousDate = Core.Globals.MinDate;
break;
case State.DataLoaded:
_sessionIterator = new SessionIterator(Bars);
_fileExists = File.Exists(Path.Combine(_filepath, Filename);
_readWriteLock = new ReaderWriterLockSlim();
break;
}
}
protected override void OnBarUpdate()
{
base.OnBarUpdate();
_previousDate = _currentDate;
_currentDate = _sessionIterator.GetTradingDay(Time[0]);
if (_currentDate != _previousDate)
{
// Routine for getting old values:
if (State == State.Historical)
{
var entry = GetEntry();
if (entry.Item5)
{
_open = entry.Item1;
_marketOpen = entry.Item2;
...
}
}
else
{
// Algo for getting new values:
...
AddEntry(_currentDate, _open, _marketOpen, _high, _low, _filepath, _Filename); // Given that all these arguments are fields in the class, I would imagine you could just change this to AddEntry().
}
}
private void AddEntry(DateTime date, double open, double marketOpen, double high, double low, string path, string filename)
{
StringBuilder newEntry = new StringBuilder();
string[] instrumentName = Instrument.FullName.Split(' ');
newEntry.Append(Environment.NewLine);
newEntry.Append(date.ToString("yyyyMMdd") + ",");
newEntry.Append(instrumentName[0].ToLowerInvariant() + ",");
newEntry.Append(open.ToString(), ",");
newEntry.Append(marketOpen.ToString(), ",");
...
_readWriteLock.EnterWriteLock();
try
{
for (var ii = 1; i <= _retries; ii++)
{
try
{
using (StreamWriter sw = new StreamWriter(Path.Combine(path, filename), true))
{
var t = Task.Run(() => sw.Write(newEntry.ToString()));
t.Wait();
t.Close();
break;
}
}
catch (IOException e)
{
Thread.Sleep(_delay);
}
}
}
finally
{
_readWriteLock.ExitWriteLock();
}
}
private Tuple<double, double, double, double, bool> GetEntry()
{
double open = 0, marketOpen = 0, high = 0, low = 0;
bool entryFound = false;
if (!_fileExists)
return Tuple.Create(open, marketOpen, high, low, entryFound);
using (TextFieldParser parser = new TextFieldParser(Path.Combine(_filepath, Filename)))
{
parser.Delimiters = new string[] { "," };
string[] parts;
DateTime entryDate;
do
{
parts = parser.ReadFields();
if (parts != null)
{
if (DateTime.TryParseExact(parts[0], "yyyyMMdd", null, System.Globalization.DateTimeStyles.AllowWhiteSpaces |
System.Globalization.DateTimeStyles.AdjustToUniversal, out entryDate))
{
if (_currentDate == entryDate)
{
string[] chartInstrument = Instrument.FullName.Split(' ');
if (parts[1].Equals(chartInstrument[0], StringComparison.OrdinalIgnoreCase))
{
open = Convert.ToDouble(parts[2]);
marketOpen = Convert.ToDouble(parts[3]);
...
entryFound = true;
break;
}
}
}
}
} while (!entryFound && !parser.EndOfData);
}
return Tuple.Create(open, marketOpen, high, low, entryFound);
}
#endregion
May 11th, 2023, 05:48 PM
Seattle, WA
Experience: Intermediate
Platform: NinjaTrader 8
Broker: AMP/CQG
Trading: Indices
Frequency: Every few days
Duration: Minutes
Posts: 96 since Feb 2012
Thanks Given: 1,047
Thanks Received: 96
benJephunneh
It's been over a year since I've played with this code, but I believe it still works with the latest NT8 update. That is, I haven't seen any write errors. Please don't be shy with suggestions, as well, since this was my first go in C# to write to CSV.
Here is a routine for recording prices of a day's open, market open, high, and low prices. I'll throw in something for reading these values from CSV just for completeness, such as for painting historical data. I'm leaving some of the regular items out (e.g. some SetDefaults items) and the algorithm for actually finding these values since this isn't what I've ever used it for:
Code
#region Fields
private double _open = 0, _marketOpen = 0, _low = 0, _high = 0;
private DateTime _currentDate, _previousDate;
private Data.SessionIterator _sessionIterator;
private static ReaderWriterLockSlim _readWriteLock;
private const int _retries 3;
private const int _delay = 1000;
private string _filepath = Path.Combine(new string[] { NinjaTrader.Core.Globals.UserDataDir, "bin", "Custom", "Indicators" });
private bool _fileExists;
#endregion
#region Properties
[NinjaScriptProperty]
[Display(Order = 1800, ResourceType = typeof(Custom.Resource), Name = "Filename", GroupName = "NinjaScriptParameters")]
public string Filename
{ get; set; }
#endregion
#region Methods
protected override void OnStateChange()
{
base.OnStateChange();
switch (State)
{
case State.SetDefaults:
...
Filename = @"OMoHL.csv";
break;
case State.Configure:
_currentDate = _previousDate = Core.Globals.MinDate;
break;
case State.DataLoaded:
_sessionIterator = new SessionIterator(Bars);
_fileExists = File.Exists(Path.Combine(_filepath, Filename);
_readWriteLock = new ReaderWriterLockSlim();
break;
}
}
protected override void OnBarUpdate()
{
base.OnBarUpdate();
_previousDate = _currentDate;
_currentDate = _sessionIterator.GetTradingDay(Time[0]);
if (_currentDate != _previousDate)
{
// Routine for getting old values:
if (State == State.Historical)
{
var entry = GetEntry();
if (entry.Item5)
{
_open = entry.Item1;
_marketOpen = entry.Item2;
...
}
}
else
{
// Algo for getting new values:
...
AddEntry(_currentDate, _open, _marketOpen, _high, _low, _filepath, _Filename); // Given that all these arguments are fields in the class, I would imagine you could just change this to AddEntry().
}
}
private void AddEntry(DateTime date, double open, double marketOpen, double high, double low, string path, string filename)
{
StringBuilder newEntry = new StringBuilder();
string[] instrumentName = Instrument.FullName.Split(' ');
newEntry.Append(Environment.NewLine);
newEntry.Append(date.ToString("yyyyMMdd") + ",");
newEntry.Append(instrumentName[0].ToLowerInvariant() + ",");
newEntry.Append(open.ToString(), ",");
newEntry.Append(marketOpen.ToString(), ",");
...
_readWriteLock.EnterWriteLock();
try
{
for (var ii = 1; i <= _retries; ii++)
{
try
{
using (StreamWriter sw = new StreamWriter(Path.Combine(path, filename), true))
{
var t = Task.Run(() => sw.Write(newEntry.ToString()));
t.Wait();
t.Close();
break;
}
}
catch (IOException e)
{
Thread.Sleep(_delay);
}
}
}
finally
{
_readWriteLock.ExitWriteLock();
}
}
private Tuple<double, double, double, double, bool> GetEntry()
{
double open = 0, marketOpen = 0, high = 0, low = 0;
bool entryFound = false;
if (!_fileExists)
return Tuple.Create(open, marketOpen, high, low, entryFound);
using (TextFieldParser parser = new TextFieldParser(Path.Combine(_filepath, Filename)))
{
parser.Delimiters = new string[] { "," };
string[] parts;
DateTime entryDate;
do
{
parts = parser.ReadFields();
if (parts != null)
{
if (DateTime.TryParseExact(parts[0], "yyyyMMdd", null, System.Globalization.DateTimeStyles.AllowWhiteSpaces |
System.Globalization.DateTimeStyles.AdjustToUniversal, out entryDate))
{
if (_currentDate == entryDate)
{
string[] chartInstrument = Instrument.FullName.Split(' ');
if (parts[1].Equals(chartInstrument[0], StringComparison.OrdinalIgnoreCase))
{
open = Convert.ToDouble(parts[2]);
marketOpen = Convert.ToDouble(parts[3]);
...
entryFound = true;
break;
}
}
}
}
} while (!entryFound && !parser.EndOfData);
}
return Tuple.Create(open, marketOpen, high, low, entryFound);
}
#endregion
Thanks, I'll give it a try!
Our life is our own today. Tomorrow you will be dust, a shade, a tale that is told. Live mindful of death, the hour flies.
June 20th, 2023, 04:29 AM
Seattle, WA
Experience: Intermediate
Platform: NinjaTrader 8
Broker: AMP/CQG
Trading: Indices
Frequency: Every few days
Duration: Minutes
Posts: 96 since Feb 2012
Thanks Given: 1,047
Thanks Received: 96
I used the streamwriter to create a indicator that gets me the information I need. I included a 'Datetime.Now' to correlate market time with PC local time. It also helps me to know when past data was added. I'm uploading it in case it helps someone else. I'll be updating and making edits to suit my needs.
Our life is our own today. Tomorrow you will be dust, a shade, a tale that is told. Live mindful of death, the hour flies.
Attached Files
Elite Membership required to download: Samplecsvwriter.zip
Last Updated on June 20, 2023