static void CalculatePythonData(PythonBridge pb, string assetName, int timeframe, int barCount) { //do nothing if this timeframe is not listed as required if (!pythonCalcTimeframes.Contains(timeframe)) { return; } //get the relevant bars (whole lookback period) but not the zero index bar as this is incomplete Bar[] bars = priceData[assetName][timeframe].Skip(1).ToArray(); //save a temporary binary file to disk for python to read (faster than sending all the data via the stdout string tempData = @"C:\ForexData\ShareData\" + assetName + "_m" + timeframe + "_Share_live.bin"; DataBuilder.DatasetToBinary(tempData, bars, DataFeedType.Ask); //Create the python bridge and run the calculation commands string[] commands = new string[] { "whole", tempData, barCount.ToString(), pythonCalcCommands }; string[] results = pb.RunScript("build_features.py", commands); PreCalculatedFeatures pcFeatures = new PreCalculatedFeatures(); try { pcFeatures.FillFromCsv(results, pythonCalcLabels); } catch (Exception e) { DisplayError(e.Message); } //add this data to the asset if it doesnt exist if (!assetDetails[assetName].Data.ContainsKey(timeframe)) { assetDetails[assetName].Data.Add(timeframe, pcFeatures); } else { //remove the oldest one to save on memory creep assetDetails[assetName].Data[timeframe].RemoveOldest(); //we just add the data to the current set of data assetDetails[assetName].Data[timeframe].Merge(pcFeatures); } }
public PythonBridgeTests() { pb = new PythonBridge(@"C:\Users\matth\Anaconda3\python"); }
public static void Start() { ProgramRunning = true; controller = new MainController(); controller.MessageHandler = new MessageHandler(DisplayMessage); controller.ErrorHandler = new ErrorHandler(DisplayError); controller.ConnectionLostHandler = new ConnectionLostHandler(LostConnection); controller.SymbolWriteMessageHandler = new SymbolWriteMessageHandler(DisplaySymbolWrite); controller.SymbolTickRequestHandler = new SymbolTickRequestHandler(DisplayTickRequest); controller.HeartBeatHandler = new HeartBeatHandler(HeartBeat); controller.SymbolTickHandler = new SymbolTickHandler(TickReceived); controller.OnAccountAuthorised = new AccountAuthorisationComplete(AccountAuthorised); WriteConsole("Starting cTrader Trading Application"); //local directory will store all user relevant data if (!System.IO.Directory.Exists("local")) { System.IO.Directory.CreateDirectory("local"); } if (!System.IO.Directory.Exists("local//users")) { System.IO.Directory.CreateDirectory("local//users"); } try { controller.Config = new Config(@"local/"); if (controller.Config.PythonPath != null) { PythonBridge = new PythonBridge(controller.Config.PythonPath); } } catch (Exception ex) { //if the config file can't be loaded terminate the program DisplayError("Unable to load required config file - " + ex.Message); Console.ReadLine(); return; } //Load all the user config files (need at least 1 user) string[] userFiles = System.IO.Directory.GetFiles(@"local/users/"); foreach (string filename in userFiles) { UserConfig config = new UserConfig(filename); //store as a dictionary with access token as the key for easier referencing if (config != null) { controller.Users.Add(config.Token, config); } } //Hold all the price data here on the trading program - push this price data to each strategy priceData = new Dictionary <string, Dictionary <int, Bar[]> >(); barIndices = new Dictionary <string, Dictionary <int, int> >(); //Load in the strategies Strategy strategyMain = Strategy.Load("YenSquared", @"TestStrategy.dll"); //Load in the asset details and set this strategy asset, a new strategy object is created for each asset assetDetails = Asset.LoadAssetFile("Assets.csv"); // NOTE normally this is got from the strategy but quick fix here for Linux compatible //setup each strategy foreach (string assetName in new string[] { "EURUSD", "EURJPY", "GBPJPY" }) { Strategy strategy = Strategy.Load("YenSquared", @"TestStrategy.dll"); strategy.IsTesting = false; strategy.Assets.Add(assetName, assetDetails[assetName]); strategy.Asset = assetDetails[assetName]; //check the required data for each strategy and update the price data to the maximum lookback required for all strategies if (!priceData.ContainsKey(assetName)) { priceData.Add(assetName, new Dictionary <int, Bar[]>()); priceData[assetName].Add(1, new Bar[5]); //add at a minimum a 1 minute bar with 5 bar lookback barIndices.Add(assetName, new Dictionary <int, int>()); barIndices[assetName].Add(1, 0); } foreach (KeyValuePair <int, int> lookbacks in strategy.RequiredData) { //if price data isn't setup for this timeframe, add it. if (!priceData[assetName].ContainsKey(lookbacks.Key)) { priceData[assetName].Add(lookbacks.Key, new Bar[lookbacks.Value + 1]); barIndices[assetName].Add(lookbacks.Key, 0); } //overwrite any existing setup with the higher lookback else if (lookbacks.Value > priceData[assetName][lookbacks.Key].Length) { priceData[assetName][lookbacks.Key] = new Bar[lookbacks.Value + 1]; } } //Pass a reference of the datasets to the strategy strategy.Datasets = priceData[assetName]; strategy.BarIndices = barIndices[assetName]; liveStrategies.Add(strategy); } if (controller.Users.Count == 0) { DisplayError("Must have atleast 1 user config.txt file in the local/users/ directory"); } else { //remove any symbols that are not required by the strategies SymbolCollection symbolDetails = controller.Users.FirstOrDefault().Value.Symbols; Symbol[] notRequired = symbolDetails.Where(p => !priceData.Keys.Any(p2 => p2 == p.Name)).ToArray(); foreach (Symbol symbol in notRequired) { symbolDetails.Remove(symbol); } //build an required python calculation commands and labels based on the requirements of the loaded strategies pythonCalcTimeframes = new int[] { 60 }; pythonCalcCommands = "ATR(3,close,high,low);ATR(4,close,high,low);ATR(5,close,high,low);ATR(100,close,high,low);VOLATILITY_LOG_MA(12,high,low);VOLUME_LOG_MA(12,volume);BBANDS(20,1.8,1,close);BBANDS(20,1.8,2,close)"; pythonCalcLabels = new string[] { "ATR_3", "ATR_4", "ATR_5", "ATR_100", "VOLATILITY_LOG_MA_12", "VOLUME_LOG_MA_12", "BBANDS_UP", "BBANDS_LOW" }; //Start the Connection WriteConsole(controller.Config.ToString()); controller.OpenConnection(); //Use a seperate thread to write from a message queue //This should be the only thread to Dequeue from the message queus Thread t = new Thread(() => { //make sure this thread exits when the program exits Thread.CurrentThread.IsBackground = true; try { WriteMessages(); } catch (Exception ex) { WriteConsole("No more messages or errors will be recorded. Message thread has failed: " + ex.Message); } }); t.Start(); } }