-
Notifications
You must be signed in to change notification settings - Fork 69
/
RNNProject_NT7_Indi.cs
667 lines (573 loc) · 20.2 KB
/
RNNProject_NT7_Indi.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
#region Using declarations
using System;
using System.ComponentModel;
using System.Drawing;
using NinjaTrader.Data;
using NinjaTrader.Gui.Chart;
using System.Net.Sockets;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Text;
#endregion
// This namespace holds all indicators and is required. Do not change it.
namespace NinjaTrader.Indicator
{
/// <summary>
/// Indicator for RNN Project
/// </summary>
[Description("Indicator for RNN Project ")]
public class RNNProject_NT7_Indi : Indicator
{
#region Variables
// Wizard generated variables
// User defined variables (add any user defined variables below)
private E_Architecture architecture = E_Architecture.LSTM; // RNN Architecture
private E_Optimizer optimizer = E_Optimizer.RMSProp; // Optimizer
private E_Loss loss = E_Loss.MSE; // Loss Function
private bool gpu = true; // Allow GPU Computations ?
private bool train = true; // Train ?
private bool isTrained = false;
private bool isReceived = false;
//Train size must be greater than window_size = 60
private int trainingSize = 500 ; // Train Size
private int epochs = 5; // Epochs
private int scale = 100; // Scale
private string fileName = "model1"; // File Name to export model
private double momentum = 0.9; // Momentum (for SGD)
private double learningRate = 0.001; // Learning Rate
private double testingPart = 10; // Percentage of Train/Test Split
private double testingWeight = 50; // Percentage of Train/Test Score Weights
private int bars = 5; // Number of Bars To Predict
private int prevTrain = 0; // The Bar NUmber on which the model was previously trained
private int retrainInterval = 10; // The default Interval after which the model should be retrained
// For Connection with socket
public TcpClient socket;
public NetworkStream stream; // for reading and writing data
#endregion
#region Class Definition
// Parameters to be sent to the model for training
public class trainParameters
{
public List<string> Data{ get; set;}
public List<string> Time{get; set;}
public string FileName {get; set;}
public bool GPU {get; set;}
public bool Train {get; set;}
public int Architecture {get; set;}
public int Optimizer {get; set;}
public int Loss{get; set;}
public int Epochs {get; set;}
public int Bars {get; set ;}
public int Scale {get; set;}
public double LearningRate {get; set;}
public double Momentum {get; set;}
public double TestingPart{get; set;}
public double TestingWeight{get; set;}
}
// Parameters to be received from Trained model
public class PredictionParameters
{
public List<double> Eval {get; set;}
public List<double> Pred {get; set;}
}
// Parameters to be sent when fetching previously trained results
public class SendParameters
{
public string FileName {get; set;}
public bool Train {get; set;}
public int Bars {get; set ;}
}
// Parameters to be received when fetching previously trained model language.
public class ReceivePrediction
{
public List<double> Pred {get; set;}
}
#endregion
/// <summary>
/// This method is used to configure the indicator and is called once before any bar data is loaded.
/// </summary>
protected override void Initialize()
{
Overlay = false;
CalculateOnBarClose = true;
// User defined Variables
retrain = true; // Allow Retraining ?
}
/// <summary>
/// Called on each bar update event (incoming tick)
/// </summary>
protected override void OnBarUpdate()
{
//For Training on Real-Time Data
if(Historical)
return;
// If the model needs to be trained
if (train)
{
// Collect Enough Data
if (CurrentBar < trainingSize)
return;
int interval = CurrentBar - prevTrain; // Interval elapsed since last training of the model
if (!isTrained ||(retrain && interval == retrainInterval)) // For sending data to the model
{
// Establishing connection
try
{
socket = new TcpClient();
socket.Connect("localhost", 9090); // Connecting to python server on localhost
stream = socket.GetStream(); // Creating stream to read and write data
}
catch (ArgumentNullException e)
{
Print(Time[0].ToString()+ " Exception Occured! The hostname parameter is null. "+ e.ToString());
}
catch (ArgumentOutOfRangeException e)
{
Print(Time[0].ToString()+ " Exception Occured! The port parameter is not between MinPort and MaxPort."+ e.ToString());
}
catch (SocketException e)
{
Print(Time[0].ToString()+ " Exception Occured! "+ e.ToString());
}
catch (ObjectDisposedException e)
{
Print(Time[0].ToString()+ " Exception Occured! TcpClient is closed. "+ e.ToString());
}
if (socket.Connected)
{
Print("Connected to localhost : 9090");
var message = DrawTextFixed("Chart Message", "Connected!" , TextPosition.TopRight);
message.TextColor = Color.DarkBlue;
// Collecting close Price and Dates data
List<string> closePrice = new List<string>();
List<string> time = new List<string>();
for (int index = 0; index < trainingSize; index++)
{
closePrice.Add(Close[index].ToString() );
time.Add(Time[index].ToString());
}
closePrice.Reverse();
time.Reverse();
// Storing the parameters for training in a class object
var jsonObject = new trainParameters();
jsonObject.Data = closePrice;
jsonObject.Time = time;
jsonObject.FileName = fileName;
jsonObject.Train = train;
jsonObject.GPU = gpu;
jsonObject.Architecture = (int)architecture;
jsonObject.Optimizer = (int)optimizer;
jsonObject.Loss = (int)loss;
jsonObject.LearningRate = learningRate;
jsonObject.Epochs = epochs;
jsonObject.Scale = scale;
jsonObject.Momentum = momentum;
jsonObject.TestingPart = testingPart;
jsonObject.TestingWeight = testingWeight;
jsonObject.Bars = bars;
// Serializing to JSON
string jsonString = JsonConvert.SerializeObject(jsonObject);
Byte[] data = Encoding.UTF8.GetBytes(jsonString);
if (stream.CanWrite)
{
stream.Write(data, 0, data.Length); // sending data to the socket
//Print("Sent : " + jsonString);
Print("Data Sent Successfully!");
var msg = DrawTextFixed( "Chart Message", "Data Sent..." , TextPosition.TopRight);
msg.TextColor = Color.DarkBlue;
isTrained = true;
prevTrain = CurrentBar;
}
else
{
Print("Data cannot be sent to the stream!");
stream.Close();
socket.Close();
return;
}
}
else
{
Print("connection failed!");
}
}
// Receiving data after training from the server
if(socket.Connected)
{
if(stream.DataAvailable)
{
byte[] data = new Byte[2*256];
string response = "";
Int32 bytes = stream.Read(data, 0, data.Length);
response = Encoding.UTF8.GetString(data,0,bytes);
if(response != "")
{
//Print("Received : " + response);
Print("Data Received Successfully!");
var message = DrawTextFixed( "Chart Message", "Predictions Received!\nPlotting on Chart..." , TextPosition.TopRight);
message.TextColor = Color.DarkBlue;
var jsonObject = new PredictionParameters();
// Deserializing JSON data
jsonObject = JsonConvert.DeserializeObject<PredictionParameters>(response);
// Plotting the predictions on the chart
for (int i=-1;i>=-1*bars;i--)
{
double ypred = double.Parse(jsonObject.Pred[(-1*i)-1].ToString());
DrawDot("Prediction " + i.ToString(), true, i, ypred, Color.Cyan);
DrawTextFixed("Chart Message", "" , TextPosition.TopRight);
}
// closing the socket
stream.Close();
socket.Close();
}
else
Print("Not Received!");
}
else
{
Print("Please Wait... Loading Predictions...");
var message = DrawTextFixed("Chart Message", "Loading Predictions\nPlease Wait..." , TextPosition.TopRight);
message.TextColor = Color.DarkBlue;
}
}
else
Print("Socket Disconnected! ");
} // end of train
// receive predictions from previously trained model
else if(!isReceived)
{
// Establishing connection
try
{
socket = new TcpClient();
socket.Connect("localhost", 9090); // Connecting to python server on localhost
stream = socket.GetStream(); // Creating stream to read and write data
}
catch (ArgumentNullException e)
{
Print(Time[0].ToString()+ " Exception Occured! The hostname parameter is null. "+ e.ToString());
}
catch (ArgumentOutOfRangeException e)
{
Print(Time[0].ToString()+ " Exception Occured! The port parameter is not between MinPort and MaxPort."+ e.ToString());
}
catch (SocketException e)
{
Print(Time[0].ToString()+ " Exception Occured! "+ e.ToString());
}
catch (ObjectDisposedException e)
{
Print(Time[0].ToString()+ " Exception Occured! TcpClient is closed. "+ e.ToString());
}
if (socket.Connected)
{
Print("Connected to localhost : 9090");
DrawTextFixed("Chart Message", "Connected!" , TextPosition.TopRight);
// Storing parameters to be sent to model in a class object
var jsonObject = new SendParameters();
jsonObject.FileName = fileName;
jsonObject.Train = train;
jsonObject.Bars = bars;
// Serializing to JSON
string jsonString = JsonConvert.SerializeObject(jsonObject);
Byte[] data = Encoding.UTF8.GetBytes(jsonString);
if (stream.CanWrite)
{
stream.Write(data, 0, data.Length);
Print("Data Sent Successfully!");
//Print("Sent : " + jsonString);
var message = DrawTextFixed("Chart Message", "Data Sent..." , TextPosition.TopRight);
message.TextColor = Color.DarkBlue;
}
else
{
Print("Data cannot be sent to the stream!");
stream.Close();
socket.Close();
return;
}
if(stream.CanRead)
{
byte[] recData = new Byte[256];
string response = string.Empty;
Int32 bytes = stream.Read(recData, 0, recData.Length);
response = Encoding.UTF8.GetString(recData,0,bytes);
if(response != string.Empty)
{
//Print("Received : " + response);
Print("Successfully Received Data!");
DrawTextFixed("Chart Message", "Predictions Received!\nPlotting on Chart..." , TextPosition.TopRight);
var jsonObj = new ReceivePrediction();
// Deserializing JSON data
jsonObj = JsonConvert.DeserializeObject<ReceivePrediction>(response);
// Plotting the predictions on the chart
for (int i=-1;i>=-1*bars;i--)
{
double ypred = double.Parse(jsonObj.Pred[(-1*i)-1].ToString());
DrawDot("Prediction " + i.ToString(), true, i, ypred, Color.Cyan);
DrawTextFixed( "Chart Message", "" , TextPosition.TopRight);
}
// closing the socket
stream.Close();
socket.Close();
}
else
{
Print("Prediction cannot be Received!");
var message = DrawTextFixed("Chart Message", "Predictions Not Available!\nPlease Train the Model..." , TextPosition.TopRight);
message.TextColor = Color.DarkBlue;
}
}
else
{
Print("Prediction Data Not Available!\nPlease Train the Model...");
var message = DrawTextFixed("Chart Message", "Predictions Not Available!\nPlease Train the Model..." , TextPosition.TopRight);
message.TextColor = Color.DarkBlue;
}
isReceived = true;
}
else
{
Print("Connection could not be established!");
var message = DrawTextFixed("Chart Message", "Connection Failed!" , TextPosition.TopRight);
message.TextColor = Color.DarkBlue;
}
} // end of receive predictions from previously trained model
} // end of OnBarUpdate
#region Properties
[Description("Architecture of the Training Model")]
[Category("Model Input Parameters")]
public E_Architecture Architecture
{
get { return architecture; }
set { architecture = value; }
}
[Description("Optimizer to be Used")]
[Category("Model Input Parameters")]
public E_Optimizer Optimizer
{
get { return optimizer; }
set { optimizer = value; }
}
[Description("Loss Function")]
[Category("Model Input Parameters")]
public E_Loss Loss
{
get { return loss; }
set { loss = value; }
}
[Description("If GPU is enabled")]
[Category("Model Input Parameters")]
public bool GPU
{
get {return gpu;}
set{gpu = value;}
}
[Description("If training is enabled")]
[Category("Model Input Parameters")]
public bool Train
{
get {return train;}
set{train = value;}
}
[Description("Size of data to be sent for training")]
[Category("Model Input Parameters")]
public int Training_Size
{
get {return trainingSize;}
set{ trainingSize = value;}
}
[Description("Epochs")]
[Category("Model Input Parameters")]
public int Epochs
{
get {return epochs;}
set{epochs = value;}
}
[Description("Scaling Parameter")]
[Category("Model Input Parameters")]
public int Scale
{
get {return scale;}
set{scale = value;}
}
[Description("Number of future bars to predict")]
[Category("Model Input Parameters")]
public int Bars_To_Predict
{
get {return bars;}
set{bars = value;}
}
[Description("Momentum")]
[Category("Model Input Parameters")]
public double Momentum
{
get {return momentum;}
set{momentum = value;}
}
[Description("Learning Rate for the model")]
[Category("Model Input Parameters")]
public double Learning_Rate
{
get {return learningRate;}
set{learningRate = value;}
}
[Description("Train/Test data split (in percentage)")]
[Category("Model Input Parameters")]
public double Testing_Part
{
get {return testingPart ;}
set{ testingPart = value;}
}
[Description("Train/Test score(in percentage)")]
[Category("Model Input Parameters")]
public double Testing_Weight
{
get {return testingWeight;}
set{testingWeight = value;}
}
[Description("Name of file to store Model")]
[Category("Model Input Parameters")]
public string FileName
{
get {return fileName;}
set {fileName = value;}
}
[Description("If the model should be Retrained or not!")]
[Category("Model Input Parameters")]
public bool retrain
{
get; set;
}
[Description("The Number Of Bars after which to retrain")]
[Category("Model Input Parameters")]
public int Retrain_Interval
{
get {return retrainInterval;}
set{retrainInterval = value;}
}
#endregion
}
}
#region Enum Declaration
public enum E_Optimizer {
RMSProp,
SGD,
Adam,
Adagrad
};
public enum E_Architecture {
LSTM,
GRU,
BidirectionalLSTM,
BidirectionalGRU
};
public enum E_Loss {
MSE,
R2
};
#endregion
#region NinjaScript generated code. Neither change nor remove.
// This namespace holds all indicators and is required. Do not change it.
namespace NinjaTrader.Indicator
{
public partial class Indicator : IndicatorBase
{
private RNNProject_NT7_Indi[] cacheRNNProject_NT7_Indi = null;
private static RNNProject_NT7_Indi checkRNNProject_NT7_Indi = new RNNProject_NT7_Indi();
/// <summary>
/// Indicator for RNN Project
/// </summary>
/// <returns></returns>
public RNNProject_NT7_Indi RNNProject_NT7_Indi()
{
return RNNProject_NT7_Indi(Input);
}
/// <summary>
/// Indicator for RNN Project
/// </summary>
/// <returns></returns>
public RNNProject_NT7_Indi RNNProject_NT7_Indi(Data.IDataSeries input)
{
if (cacheRNNProject_NT7_Indi != null)
for (int idx = 0; idx < cacheRNNProject_NT7_Indi.Length; idx++)
if (cacheRNNProject_NT7_Indi[idx].EqualsInput(input))
return cacheRNNProject_NT7_Indi[idx];
lock (checkRNNProject_NT7_Indi)
{
if (cacheRNNProject_NT7_Indi != null)
for (int idx = 0; idx < cacheRNNProject_NT7_Indi.Length; idx++)
if (cacheRNNProject_NT7_Indi[idx].EqualsInput(input))
return cacheRNNProject_NT7_Indi[idx];
RNNProject_NT7_Indi indicator = new RNNProject_NT7_Indi();
indicator.BarsRequired = BarsRequired;
indicator.CalculateOnBarClose = CalculateOnBarClose;
#if NT7
indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256;
indicator.MaximumBarsLookBack = MaximumBarsLookBack;
#endif
indicator.Input = input;
Indicators.Add(indicator);
indicator.SetUp();
RNNProject_NT7_Indi[] tmp = new RNNProject_NT7_Indi[cacheRNNProject_NT7_Indi == null ? 1 : cacheRNNProject_NT7_Indi.Length + 1];
if (cacheRNNProject_NT7_Indi != null)
cacheRNNProject_NT7_Indi.CopyTo(tmp, 0);
tmp[tmp.Length - 1] = indicator;
cacheRNNProject_NT7_Indi = tmp;
return indicator;
}
}
}
}
// This namespace holds all market analyzer column definitions and is required. Do not change it.
namespace NinjaTrader.MarketAnalyzer
{
public partial class Column : ColumnBase
{
/// <summary>
/// Indicator for RNN Project
/// </summary>
/// <returns></returns>
[Gui.Design.WizardCondition("Indicator")]
public Indicator.RNNProject_NT7_Indi RNNProject_NT7_Indi()
{
return _indicator.RNNProject_NT7_Indi(Input);
}
/// <summary>
/// Indicator for RNN Project
/// </summary>
/// <returns></returns>
public Indicator.RNNProject_NT7_Indi RNNProject_NT7_Indi(Data.IDataSeries input)
{
return _indicator.RNNProject_NT7_Indi(input);
}
}
}
// This namespace holds all strategies and is required. Do not change it.
namespace NinjaTrader.Strategy
{
public partial class Strategy : StrategyBase
{
/// <summary>
/// Indicator for RNN Project
/// </summary>
/// <returns></returns>
[Gui.Design.WizardCondition("Indicator")]
public Indicator.RNNProject_NT7_Indi RNNProject_NT7_Indi()
{
return _indicator.RNNProject_NT7_Indi(Input);
}
/// <summary>
/// Indicator for RNN Project
/// </summary>
/// <returns></returns>
public Indicator.RNNProject_NT7_Indi RNNProject_NT7_Indi(Data.IDataSeries input)
{
if (InInitialize && input == null)
throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method");
return _indicator.RNNProject_NT7_Indi(input);
}
}
}
#endregion