/// <summary> /// Executes a run of processing the stock data /// </summary> /// <param name="session">The session configuration</param> public static void Run(StockSession session) { // Set up the derived data sink var sourceData = session.SourceFile.GetSegments <StockDataSource>(); var sinkData = StockDataSetDerived <StockDataSink, StockDataSource> .Derive(sourceData, session.SinkFile, (data, idx) => { var point = new StockDataSink(); point.Update(data, idx); return(point); }); session.SinkFile.SetSegments(sinkData); // Find when a stock increases by a certain amount PriceMonitor priceMonitor = new PriceMonitor(0.025); priceMonitor.MonitorDecrease = false; sinkData["AA"][0].Load(); priceMonitor.Monitor("AA", sinkData["AA"][0][0].Price, (string stock, float startPrice, float endPrice, DateTime time) => { System.Windows.Forms.MessageBox.Show(string.Format("{0} {1:C}->{2:C} @ {3}", stock, startPrice, endPrice, time)); return(true); }); // Load the first set of data foreach (var pair in sinkData) { foreach (var set in pair.Value) { set.Load(); priceMonitor.Process(set, 0); } } }
/// <summary> /// The main update function for the class /// </summary> /// <param name="data">The available source data</param> /// <param name="updateIndex">The index into the data that should be used as the source for this</param> partial void MovingAverage_Update(StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState> data, int updateIndex) { this.Average10Min = 0.0f; int startIdx = Math.Max(0, updateIndex - 9); for (int idx = startIdx; idx <= updateIndex; idx++) { this.Average10Min += data[idx].Price; } this.Average10Min /= ((updateIndex + 1) - startIdx); }
public StockProcessor(StockSession session) { this.Session = session; // Load the source file static information Session.SourceFile.LoadStaticData(session); // Create the derived data set HistoricalData = StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState> .Derive(Session.SourceFile.GetSegments <StockDataSource>(), Session.SinkFile, CreateSink, GetProcessingState); DerivedData = StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState> .CastToBase(HistoricalData); Session.SinkFile.SetSegments <StockDataSink>(DerivedData); }
/// <summary> /// The main update function which sets all of the member variables based on other source data /// </summary> /// <param name="data">The available source data</param> /// <param name="updateIndex">The index into the data that should be used as the source for this</param> partial void DataSetReference_Update(StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState> data, int updateIndex) { this.DataSet = data; this.DataSetIndex = data.ProcessingState.DataSetIndex; this.DataPointIndex = updateIndex; if (DataPointIndex == 0) { DataSetData = new DataPerSet(); } else { DataSetData = data[0].DataSetData; } }
/// <summary> /// Creates a derived set of data from the given source /// </summary> /// <param name="source">The source data</param> /// <returns>The derived data</returns> public static Dictionary <string, List <StockDataSetDerived <T, U, V> > > Derive(Dictionary <string, List <StockDataSet <U> > > source, StockDataFile file, StockDataCreator create, StockProcessingStateAccessor stateGetter) { var derived = new Dictionary <string, List <StockDataSetDerived <T, U, V> > >(); foreach (KeyValuePair <string, List <StockDataSet <U> > > pair in source) { StockDataSetDerived <T, U, V> prevSet = null; derived[pair.Key] = new List <StockDataSetDerived <T, U, V> >(pair.Value.Count); foreach (StockDataSet <U> srcSet in pair.Value) { var newSet = new StockDataSetDerived <T, U, V>(srcSet, file, create, stateGetter); newSet.Previous = prevSet; prevSet = newSet; derived[pair.Key].Add(newSet); } } return(derived); }
/// <summary> /// Adds a new processing target /// </summary> /// <param name="target">The target point to add</param> public void Add(ProcessingTarget target) { Targets.Add(target); // If live, set up a subscription if (Live && !LiveData.ContainsKey(target.Symbol)) { var sourceList = new StockDataSet <StockDataSource>(target.Symbol, DateTime.Now, Session.SourceFile); var data = new StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState>(sourceList, Session.SinkFile, CreateSink, GetProcessingState); var sub = DataAccessor.Subscribe(target.Symbol, LiveInterval); sub.Notify += (DataAccessor.Subscription s) => { LiveData[s.Symbol].Item1.Add(StockDataSource.CreateFromPrice((float)s.Price)); LiveProcessingQueue.Add(target); }; LiveData[target.Symbol] = new Tuple <StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState>, DataAccessor.Subscription>(data, sub); } }
public StockProcessor(StockSession session) { this.Session = session; // Load the source file static information Session.SourceFile.LoadStaticData(session); // Create the derived data set HistoricalData = StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState> .Derive(Session.SourceFile.GetSegments <StockDataSource>(), Session.SinkFile, CreateSink, GetProcessingState); DerivedData = StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState> .CastToInterface(HistoricalData); Session.Data = DerivedData; Session.SinkFile.SetSegments <StockDataSink>(StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState> .CastToBase(HistoricalData)); foreach (var pair in HistoricalData) { var state = new StockProcessingState(); state.DataSet = pair.Value; ProcessingStates[pair.Key] = new Dictionary <TimeSpan, StockProcessingState>() { }; } }
/// <summary> /// Creates a new instance of a StockDataSink based on a StockDataSource /// </summary> /// <param name="data">Source data</param> /// <param name="idx">Index in the source data to base the new point off of</param> public static void CreateSink(StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState> data, int idx) { data.DataSet.InternalArray[idx].Update(data, idx); }
/// <summary> /// Task for processing live data /// </summary> private void ProcessLive() { foreach (var target in LiveProcessingQueue.GetConsumingEnumerable()) { StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState> set = LiveData[target.Symbol].Item1; if (target.Reference.Price == 0) { target.Reference = set[0]; } for (; (target.ProcessedLiveIdx < set.Count); target.ProcessedLiveIdx++) { if (Evaluator.Evaluate(set, target.ProcessedLiveIdx, target)) { Action.Do(this, target, set.Time(target.ProcessedLiveIdx)); } } } }
/// <summary> /// Processes the specified data using the evaluator and resulting action /// <param name="multithreaded">Indicates if the processing should be done multithreaded</param> /// <param name="keep">Indicates if the processed data should remain in memory, /// or should be cleared once processing is complete.</param> /// </summary> public virtual void Process(bool multithreaded = false, MemoryScheme keep = MemoryScheme.MEM_KEEP_NONE) { System.Action <ProcessingTarget> processFunc = (ProcessingTarget target) => { List <StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState> > sets = HistoricalData[target.Symbol]; var processingState = new StockProcessingState(); for (; target.ProcessedSetIdx < sets.Count; target.ProcessedSetIdx++) { // Process all of the data sets for the target StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState> set = sets[target.ProcessedSetIdx]; set.Load(Session); for (; (target.ProcessedDataIdx < set.Count); target.ProcessedDataIdx++) { if (Evaluator.Evaluate(set, target.ProcessedDataIdx, target)) { Action.Do(this, target, set.Time(target.ProcessedDataIdx)); } } // Clean up the memory after processing has completed if (keep == MemoryScheme.MEM_KEEP_NONE) { set.Clear(); } else if (keep == MemoryScheme.MEM_KEEP_SOURCE) { set.ClearDerived(); } } }; // Process each of the targets if (multithreaded) { System.Threading.Tasks.Parallel.ForEach(Targets, processFunc); } else { foreach (ProcessingTarget target in Targets) { processFunc(target); } } // Indicate processing has completed if (Complete != null) { Complete(); } }
/// <summary> /// The main update function which sets all of the member variables based on other source data /// </summary> /// <param name="data">The available source data</param> /// <param name="updateIndex">The index into the data that should be used as the source for this</param> partial void DataSetReference_Update(StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState> data, int updateIndex) { this.DataSet = data; this.DataSetIndex = data.ProcessingState.DataSetIndex; this.DataPointIndex = updateIndex; }
///= Members /// #endregion #region Prototypes ///= PartialPrototypes /// #endregion /// <summary> /// The main update function which sets all of the member variables based on other source data /// </summary> /// <param name="data">The available source data</param> /// <param name="updateIndex">The index into the data that should be used as the source for this</param> public void Update(StockDataSetDerived <StockDataSink, StockDataSource, StockProcessingState> data, int updateIndex) { this.Price = data.SourceData.DataSet.InternalArray[data.GetSourceIndex(updateIndex)].Price; ///= PartialUpdates /// }
public void Run() { System.Windows.Forms.OpenFileDialog diag = new System.Windows.Forms.OpenFileDialog(); diag.Multiselect = true; diag.Title = "Open Stock Data File..."; if (diag.ShowDialog() == System.Windows.Forms.DialogResult.OK) { List <string> script = new List <string>(); Directory.CreateDirectory("tmp"); // Get the source file if (diag.FileName.EndsWith(".csv")) { System.Windows.Forms.SaveFileDialog saveDiag = new System.Windows.Forms.SaveFileDialog(); if (saveDiag.ShowDialog() != System.Windows.Forms.DialogResult.OK) { return; } SourceFile = StockDataFile.Convert(diag.FileNames.ToList(), new FileStream(saveDiag.FileName, FileMode.Create)); } else { SourceFile = StockDataFile.Open(new FileStream(diag.FileName, FileMode.Open)); } script.Add("tmp/" + SOURCE_CLASS + ".cs"); using (var file = new StreamWriter(new FileStream(script.Last(), FileMode.Create))) file.Write(SourceFile.GetSourceCode(SOURCE_CLASS)); // Create the sink file //SinkFile = new StockDataFile(new List<string>() { }, new List<string>() { }); SinkFile = new StockDataFile(new List <string>() { "MovingAverage" }, new List <string>() { File.ReadAllText(@"Script/Data/MovingAverage.cs") }); script.Add("tmp/" + SINK_CLASS + ".cs"); using (var file = new StreamWriter(new FileStream(script.Last(), FileMode.Create))) file.Write(SinkFile.GetSourceCode(SINK_CLASS)); // Create the analyzer file (needs to be compiled in the script since it references StockDataSource) var analyzerFilename = "RobinhoodDesktop.Script.StockAnalyzer.cs"; script.Add("tmp/StockAnalyzer.cs"); StringBuilder analyzerCode = new StringBuilder(); analyzerCode.Append(new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(analyzerFilename)).ReadToEnd()); using (var file = new StreamWriter(new FileStream(script.Last(), FileMode.Create))) file.Write(StockDataFile.FormatSource(analyzerCode.ToString())); // Add the user defined analyzers string[] analyzerPaths = Directory.GetFiles(@"Script/Decision", "*.cs", SearchOption.AllDirectories); foreach (string path in analyzerPaths) { script.Add(path); } // Get the code that will actually run the session script.Add("tmp/StockSessionScript.cs"); var sessionFilename = "RobinhoodDesktop.Script.StockSessionScript.cs"; using (var file = new StreamWriter(new FileStream(script.Last(), FileMode.Create))) file.Write(new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(sessionFilename)).ReadToEnd()); // Build and run the session #if DEBUG var isDebug = true; #else var isDebug = false; #endif #if true try { var scriptInstance = CSScript.LoadFiles(script.ToArray(), null, isDebug); var run = scriptInstance.GetStaticMethod("RobinhoodDesktop.Script.StockSessionScript.Run", this); run(this); } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.ToString()); } #else // Set up the derived data sink var sourceData = SourceFile.GetSegments <StockDataBase>(); var sinkData = StockDataSetDerived <StockDataBase, StockDataBase> .Derive(sourceData, SinkFile, (data, idx) => { var point = new StockDataBase(); point.Update(data, idx); return(point); }); SinkFile.SetSegments(sinkData); // Load the first set of data foreach (var pair in sinkData) { foreach (var set in pair.Value) { set.Load(); } } #endif // Cleanup SourceFile.Close(); } }