/// <summary> /// Delete an instrument and all locally stored data. /// </summary> public static void RemoveInstrument(Instrument instrument) { using (var entityContext = new MyDBContext()) { //hacking around the circular reference issue if (instrument.IsContinuousFuture) { entityContext.Instruments.Attach(instrument); var tmpCF = instrument.ContinuousFuture; instrument.ContinuousFuture = null; instrument.ContinuousFutureID = null; entityContext.SaveChanges(); entityContext.ContinuousFutures.Attach(tmpCF); entityContext.ContinuousFutures.Remove(tmpCF); entityContext.SaveChanges(); } entityContext.Instruments.Attach(instrument); entityContext.Instruments.Remove(instrument); entityContext.SaveChanges(); } using (var localStorage = DataStorageFactory.Get()) { localStorage.Connect(); localStorage.DeleteAllInstrumentData(instrument); } }
public DataUpdateJob(IHistoricalDataBroker broker, IEmailService emailService, UpdateJobSettings settings = null, IDataStorage localStorage = null, IInstrumentSource instrumentManager = null) { _broker = broker; _emailService = emailService; _errors = new List <string>(); _pendingRequests = new List <HistoricalDataRequest>(); _settings = settings ?? GetSettings(); _localStorage = localStorage ?? DataStorageFactory.Get(); _instrumentManager = instrumentManager ?? new InstrumentManager(); }
//delete data from selected instruments private void ClearDataBtn_ItemClick(object sender, RoutedEventArgs routedEventArgs) { IList selectedInstruments = InstrumentsGrid.SelectedItems; if (selectedInstruments.Count == 0) { return; } if (selectedInstruments.Count == 1) { var inst = (Instrument)selectedInstruments[0]; MessageBoxResult res = MessageBox.Show( string.Format("Are you sure you want to delete all data from {0} @ {1}?", inst.Symbol, inst.Datasource.Name), "Delete", MessageBoxButton.YesNo); if (res == MessageBoxResult.No) { return; } } else { MessageBoxResult res = MessageBox.Show( string.Format("Are you sure you want to delete all data from {0} instruments?", selectedInstruments.Count), "Delete", MessageBoxButton.YesNo); if (res == MessageBoxResult.No) { return; } } using (IDataStorage storage = DataStorageFactory.Get()) { //todo remove dependency on local storage here, use client instead foreach (Instrument i in selectedInstruments) { try { storage.DeleteAllInstrumentData(i); } catch (Exception ex) { MessageBox.Show(ex.Message); } } } StatusBarLabel.Content = "Instrument data deleted"; }
private void SaveChangesBtn_Click(object sender, RoutedEventArgs e) { using (var localStorage = DataStorageFactory.Get()) { try { localStorage.UpdateData(Data.ToList(), TheInstrument, _loadedFrequency, true); MessageBox.Show("Successfully updated data."); } catch (Exception ex) { MessageBox.Show("Error while updating data: " + ex.Message); } } }
public HistoricalDataBroker(IDataStorage localStorage = null, IEnumerable <IHistoricalDataSource> additionalSources = null, IContinuousFuturesBroker cfBroker = null) { _dataStorage = localStorage ?? DataStorageFactory.Get(); DataSources = new ObservableDictionary <string, IHistoricalDataSource> { { "Interactive Brokers", new IB(Properties.Settings.Default.histClientIBID) }, { "Yahoo", new Yahoo() }, { "Quandl", new Quandl() }, { "FRED", new FRED() }, { "Google", new Google() } }; //add the continuous futures broker to the data sources DataSources.Add("ContinuousFuturesBroker", cfBroker ?? new ContinuousFuturesBroker(clientName: "HDBCFClient")); //add additional sources if (additionalSources != null) { foreach (IHistoricalDataSource ds in additionalSources) { if (!DataSources.ContainsKey(ds.Name)) { DataSources.Add(ds.Name, ds); } } } foreach (IHistoricalDataSource ds in DataSources.Values) { ds.Error += DatasourceError; ds.HistoricalDataArrived += ExternalHistoricalDataArrived; ds.Disconnected += SourceDisconnects; } _dataStorage.Error += DatasourceError; _dataStorage.HistoricalDataArrived += LocalStorageHistoricalDataArrived; _connectionTimer = new Timer(10000); _connectionTimer.Elapsed += ConnectionTimerElapsed; _connectionTimer.Start(); _originalRequests = new ConcurrentDictionary <int, HistoricalDataRequest>(); _subRequests = new ConcurrentDictionary <int, List <HistoricalDataRequest> >(); _usedIDs = new List <int>(); TryConnect(); }
public DataEditWindow(Instrument instrument) { InitializeComponent(); DataContext = this; Data = new ObservableCollection <OHLCBar>(); //grab and update the instrument //TODO rewrite to use client using (var context = new MyDBContext()) { context.Instruments.Attach(instrument); context.Entry(instrument).Reload(); TheInstrument = instrument; } string timezone = TheInstrument.Exchange == null ? "UTC" : TheInstrument.Exchange.Timezone; _tzInfo = TimeZoneInfo.FindSystemTimeZoneById(timezone); StartTime = new DateTime(1950, 1, 1, 0, 0, 0, 0); EndTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0, 0); if (!TheInstrument.ID.HasValue) { return; } //grab the data info //todo remove dependency on DataStorageFactory using (var localStorage = DataStorageFactory.Get()) { var storageInfo = localStorage.GetStorageInfo(TheInstrument.ID.Value); if (storageInfo.Count == 0) //if it doesn't have any data, we just exit { MessageBox.Show("This instrument has no data."); Hide(); } else { foreach (StoredDataInfo s in storageInfo) //fill the resolution box { ResolutionComboBox.Items.Add(s.Frequency); } } } }
/// <summary> /// Constructor /// </summary> /// <param name="additionalDataSources">Optional. Pass any additional data sources (for testing purposes).</param> /// <param name="cfBroker">Optional. IContinuousFuturesBroker (for testing purposes).</param> public RealTimeDataBroker(IEnumerable <IRealTimeDataSource> additionalDataSources = null, IContinuousFuturesBroker cfBroker = null, IDataStorage localStorage = null) { _connectionTimer = new Timer(10000); _connectionTimer.Elapsed += ConnectionTimerElapsed; _connectionTimer.Start(); DataSources = new ObservableDictionary <string, IRealTimeDataSource> { { "SIM", new RealTimeSim() }, { "Interactive Brokers", new IB(Properties.Settings.Default.rtdClientIBID) } }; if (additionalDataSources != null) { foreach (IRealTimeDataSource ds in additionalDataSources) { DataSources.Add(ds.Name, ds); } } //we need to set the appropriate event methods for every data source foreach (IRealTimeDataSource s in DataSources.Values) { s.DataReceived += RealTimeData; s.Disconnected += SourceDisconnects; s.Error += s_Error; } ActiveStreams = new ConcurrentNotifierBlockingList <RealTimeStreamInfo>(); _arrivedBars = new BlockingCollection <RealTimeDataEventArgs>(); StreamSubscribersCount = new Dictionary <RealTimeStreamInfo, int>(); _aliases = new Dictionary <int, List <int> >(); _pendingCFRealTimeRequests = new Dictionary <int, RealTimeDataRequest>(); _continuousFuturesIDMap = new Dictionary <int, int>(); _requests = new Dictionary <int, RealTimeDataRequest>(); _usedIDs = new List <int>(); //connect to our data sources TryConnect(); //local storage _localStorage = localStorage ?? DataStorageFactory.Get(); //start up the continuous futures broker _cfBroker = cfBroker ?? new ContinuousFuturesBroker(clientName: "RTDBCFClient"); _cfBroker.FoundFrontContract += _cfBroker_FoundFrontContract; }
private void DeleteBtn_Click(object sender, RoutedEventArgs e) { //get the selected bars var rows = DataGrid.SelectedItems; if (rows.Count < 0) { return; } var result = MessageBox.Show(string.Format("Are you sure you want to delete {0} rows?", rows.Count), "Delete Rows", MessageBoxButton.YesNo); if (result == MessageBoxResult.No) { return; } var toDelete = rows.Cast <OHLCBar>().ToList(); //data is stored in the db at exchange time. But we may have loaded it at UTC or local. //If so, we must convert it back. foreach (OHLCBar b in toDelete) { if (_loadedTimeZone == "UTC") { b.DT = TimeZoneInfo.ConvertTimeFromUtc(b.DT, _tzInfo); } else if (_loadedTimeZone == "Local") { b.DT = TimeZoneInfo.ConvertTime(b.DT, TimeZoneInfo.Local, _tzInfo); } } //todo remove dependency on DataStorageFactory using (var localStorage = DataStorageFactory.Get()) { localStorage.DeleteData(TheInstrument, _loadedFrequency, toDelete); } foreach (OHLCBar bar in toDelete) { Data.Remove(bar); } }
//delete one or more instruments private void DeleteInstrumentBtn_ItemClick(object sender, RoutedEventArgs routedEventArgs) { var selectedInstruments = InstrumentsGrid.SelectedItems; if (selectedInstruments.Count == 0) { return; } if (selectedInstruments.Count == 1) { var inst = (Instrument)selectedInstruments[0]; MessageBoxResult res = MessageBox.Show(string.Format("Are you sure you want to delete {0} @ {1}?", inst.Symbol, inst.Datasource.Name), "Delete", MessageBoxButton.YesNo); if (res == MessageBoxResult.No) { return; } } else { MessageBoxResult res = MessageBox.Show(string.Format("Are you sure you want to delete {0} instruments?", selectedInstruments.Count), "Delete", MessageBoxButton.YesNo); if (res == MessageBoxResult.No) { return; } } List <Instrument> toRemove = new List <Instrument>(); foreach (Instrument i in InstrumentsGrid.SelectedItems) { InstrumentManager.RemoveInstrument(i, DataStorageFactory.Get()); toRemove.Add(i); } while (toRemove.Count > 0) { Instruments.Remove(toRemove[toRemove.Count - 1]); toRemove.RemoveAt(toRemove.Count - 1); } }
//check the latest date we have available in local storage, then request historical data from that date to the current time private void UpdateHistoricalDataBtn_ItemClick(object sender, RoutedEventArgs routedEventArgs) { var frequency = (BarSize)((MenuItem)sender).Tag; List <Instrument> selectedInstruments = InstrumentsGrid.SelectedItems.Cast <Instrument>().ToList(); int requestCount = 0; using (var localStorage = DataStorageFactory.Get()) { foreach (Instrument i in selectedInstruments) { if (!i.ID.HasValue) { continue; } var storageInfo = localStorage.GetStorageInfo(i.ID.Value); if (storageInfo.Any(x => x.Frequency == frequency)) { var relevantStorageInfo = storageInfo.First(x => x.Frequency == frequency); _client.RequestHistoricalData(new HistoricalDataRequest( i, frequency, relevantStorageInfo.LatestDate + frequency.ToTimeSpan(), DateTime.Now, dataLocation: DataLocation.ExternalOnly, saveToLocalStorage: true)); requestCount++; } } } if (_progressBar.Value >= _progressBar.Maximum) { _progressBar.Maximum = requestCount; _progressBar.Value = 0; } else { _progressBar.Maximum += requestCount; } }
private void LoadDataBtn_Click(object sender, RoutedEventArgs e) { Data.Clear(); //grab the data //todo remove dependency on DataStorageFactory using (var localStorage = DataStorageFactory.Get()) { var bars = localStorage.GetData(TheInstrument, StartTime, EndTime, (BarSize)ResolutionComboBox.SelectedItem); //find largest significant decimal by sampling the prices at the start and end of the series var decPlaces = new List <int>(); for (int i = 0; i < Math.Min(bars.Count, 20); i++) { decPlaces.Add(bars[i].Open.CountDecimalPlaces()); decPlaces.Add(bars[bars.Count - 1 - i].Close.CountDecimalPlaces()); } //set the column format to use that number so we don't get any useless trailing 0s SetPriceColumnFormat(decPlaces.Max()); foreach (OHLCBar b in bars) { //do any required time zone coversions if (TimezoneComboBox.Text == "UTC") { b.DT = TimeZoneInfo.ConvertTimeToUtc(b.DT, _tzInfo); } else if (TimezoneComboBox.Text == "Local") { b.DT = TimeZoneInfo.ConvertTime(b.DT, _tzInfo, TimeZoneInfo.Local); } Data.Add(b); } _loadedFrequency = (BarSize)ResolutionComboBox.SelectedItem; _loadedTimeZone = TimezoneComboBox.Text; } StatusLabel.Content = string.Format("Loaded {0} Bars", Data.Count); }
public MainWindow() { Common.Logging.LogManager.Adapter = new NLogLoggerFactoryAdapter(new Common.Logging.Configuration.NameValueCollection()); //make sure we can connect to the database CheckDBConnection(); //set the log directory SetLogDirectory(); //set the connection string DBUtils.SetConnectionString(); //set EF configuration, necessary for MySql to work DBUtils.SetDbConfiguration(); InitializeComponent(); DataContext = this; //load datagrid layout string layoutFile = AppDomain.CurrentDomain.BaseDirectory + "GridLayout.xml"; if (File.Exists(layoutFile)) { try { InstrumentsGrid.DeserializeLayout(File.ReadAllText(layoutFile)); } catch { } } LogMessages = new ConcurrentNotifierBlockingList <LogEventInfo>(); //target is where the log managers send their logs, here we grab the memory target which has a Subject to observe var target = LogManager.Configuration.AllTargets.Single(x => x.Name == "myTarget") as MemoryTarget; //Log unhandled exceptions AppDomain.CurrentDomain.UnhandledException += AppDomain_CurrentDomain_UnhandledException; //we subscribe to the messages and send them all to the LogMessages collection if (target != null) { target.Messages.Subscribe(msg => LogMessages.TryAdd(msg)); } //build the instruments grid context menu //we want a button for each BarSize enum value in the UpdateFreqSubMenu menu foreach (int value in Enum.GetValues(typeof(BarSize))) { var button = new MenuItem { Header = Regex.Replace(((BarSize)value).ToString(), "([A-Z])", " $1").Trim(), Tag = (BarSize)value }; button.Click += UpdateHistoricalDataBtn_ItemClick; ((MenuItem)Resources["UpdateFreqSubMenu"]).Items.Add(button); } //create metadata db if it doesn't exist var entityContext = new MyDBContext(); entityContext.Database.Initialize(false); //seed the datasources no matter what, because these are added frequently Seed.SeedDatasources(entityContext); //check for any exchanges, seed the db with initial values if nothing is found if (!entityContext.Exchanges.Any()) { Seed.DoSeed(); } //create data db if it doesn't exist var dataContext = new DataDBContext(); dataContext.Database.Initialize(false); dataContext.Dispose(); //create quartz db if it doesn't exist QuartzUtils.InitializeDatabase(Settings.Default.databaseType); //build the tags menu var allTags = entityContext.Tags.ToList(); BuildTagContextMenu(allTags); //build session templates menu BuildSetSessionTemplateMenu(); Instruments = new ObservableCollection <Instrument>(); var instrumentRepo = new InstrumentRepository(entityContext); var instrumentList = instrumentRepo.FindInstruments().Result; foreach (Instrument i in instrumentList) { Instruments.Add(i); } //create brokers var cfRealtimeBroker = new ContinuousFuturesBroker(new QDMSClient.QDMSClient( "RTDBCFClient", "127.0.0.1", Properties.Settings.Default.rtDBReqPort, Properties.Settings.Default.rtDBPubPort, Properties.Settings.Default.hDBPort, Properties.Settings.Default.httpPort, Properties.Settings.Default.apiKey, useSsl: Properties.Settings.Default.useSsl), connectImmediately: false); var cfHistoricalBroker = new ContinuousFuturesBroker(new QDMSClient.QDMSClient( "HDBCFClient", "127.0.0.1", Properties.Settings.Default.rtDBReqPort, Properties.Settings.Default.rtDBPubPort, Properties.Settings.Default.hDBPort, Properties.Settings.Default.httpPort, Properties.Settings.Default.apiKey, useSsl: Properties.Settings.Default.useSsl), connectImmediately: false); var localStorage = DataStorageFactory.Get(); RealTimeBroker = new RealTimeDataBroker(cfRealtimeBroker, localStorage, new IRealTimeDataSource[] { //new Xignite(Properties.Settings.Default.xigniteApiToken), //new Oanda(Properties.Settings.Default.oandaAccountId, Properties.Settings.Default.oandaAccessToken), new IB(Properties.Settings.Default.ibClientHost, Properties.Settings.Default.ibClientPort, Properties.Settings.Default.rtdClientIBID), //new ForexFeed(Properties.Settings.Default.forexFeedAccessKey, ForexFeed.PriceType.Mid) }); HistoricalBroker = new HistoricalDataBroker(cfHistoricalBroker, localStorage, new IHistoricalDataSource[] { new Yahoo(), new FRED(), //new Forexite(), new IB(Properties.Settings.Default.ibClientHost, Properties.Settings.Default.ibClientPort, Properties.Settings.Default.histClientIBID), new Quandl(Properties.Settings.Default.quandlAuthCode), new BarChart(Properties.Settings.Default.barChartApiKey) }); var countryCodeHelper = new CountryCodeHelper(entityContext.Countries.ToList()); EconomicReleaseBroker = new EconomicReleaseBroker("FXStreet", new[] { new fx.FXStreet(countryCodeHelper) }); //create the various servers _realTimeServer = new RealTimeDataServer(Properties.Settings.Default.rtDBPubPort, Properties.Settings.Default.rtDBReqPort, RealTimeBroker); _historicalDataServer = new HistoricalDataServer(Properties.Settings.Default.hDBPort, HistoricalBroker); //and start them _realTimeServer.StartServer(); _historicalDataServer.StartServer(); //we also need a client to make historical data requests with _client = new QDMSClient.QDMSClient( "SERVERCLIENT", "localhost", Properties.Settings.Default.rtDBReqPort, Properties.Settings.Default.rtDBPubPort, Properties.Settings.Default.hDBPort, Properties.Settings.Default.httpPort, Properties.Settings.Default.apiKey, useSsl: Properties.Settings.Default.useSsl); _client.Connect(); _client.HistoricalDataReceived += _client_HistoricalDataReceived; ActiveStreamGrid.ItemsSource = RealTimeBroker.ActiveStreams; //create the scheduler var quartzSettings = QuartzUtils.GetQuartzSettings(Settings.Default.databaseType); ISchedulerFactory schedulerFactory = new StdSchedulerFactory(quartzSettings); _scheduler = schedulerFactory.GetScheduler(); _scheduler.JobFactory = new JobFactory(HistoricalBroker, Properties.Settings.Default.updateJobEmailHost, Properties.Settings.Default.updateJobEmailPort, Properties.Settings.Default.updateJobEmailUsername, Properties.Settings.Default.updateJobEmailPassword, Properties.Settings.Default.updateJobEmailSender, Properties.Settings.Default.updateJobEmail, new UpdateJobSettings( noDataReceived: Properties.Settings.Default.updateJobReportNoData, errors: Properties.Settings.Default.updateJobReportErrors, outliers: Properties.Settings.Default.updateJobReportOutliers, requestTimeouts: Properties.Settings.Default.updateJobTimeouts, timeout: Properties.Settings.Default.updateJobTimeout, toEmail: Properties.Settings.Default.updateJobEmail, fromEmail: Properties.Settings.Default.updateJobEmailSender), localStorage, EconomicReleaseBroker); _scheduler.Start(); //Take jobs stored in the qmds db and move them to the quartz db - this can be removed in the next version MigrateJobs(entityContext, _scheduler); var bootstrapper = new CustomBootstrapper( DataStorageFactory.Get(), EconomicReleaseBroker, HistoricalBroker, RealTimeBroker, Properties.Settings.Default.apiKey); var uri = new Uri((Settings.Default.useSsl ? "https" : "http") + "://localhost:" + Properties.Settings.Default.httpPort); var host = new NancyHost(bootstrapper, uri); host.Start(); entityContext.Dispose(); ShowChangelog(); }
private void ImportBtn_Click(object sender, RoutedEventArgs e) { Stopwatch sw = new Stopwatch(); sw.Start(); //check that we've got the relevant data needed if (!Data.Columns.Contains("Date") && !Data.Columns.Contains("DateTime")) { MessageBox.Show("Must have a date column."); return; } if ((BarSize)FrequencyComboBox.SelectedItem < BarSize.OneDay && !Data.Columns.Contains("DateTime") && !Data.Columns.Contains("Time")) { MessageBox.Show("Must have time column at this frequency"); return; } if (!Data.Columns.Contains("Open") || !Data.Columns.Contains("High") || !Data.Columns.Contains("Low") || !Data.Columns.Contains("Close")) { MessageBox.Show("Must have all OHLC columns."); return; } //make sure the timezone is set, and get it if (string.IsNullOrEmpty(_instrument.Exchange.Timezone)) { MessageBox.Show("Instrument's exchange has no set timezone, can't import."); return; } var tzInfo = TimeZoneInfo.FindSystemTimeZoneById(_instrument.Exchange.Timezone); //get the multipliers decimal priceMultiplier; int volumeMultiplier; bool parseWorked = decimal.TryParse(PriceMultiplier.Text, out priceMultiplier); if (!parseWorked) { priceMultiplier = 1; } parseWorked = int.TryParse(VolumeMultiplier.Text, out volumeMultiplier); if (!parseWorked) { volumeMultiplier = 1; } //lines to skip int toSkip; parseWorked = int.TryParse(StartingLine.Text, out toSkip); if (!parseWorked) { toSkip = 1; } //get the frequency var frequency = (BarSize)FrequencyComboBox.SelectedItem; //separator char[] separator = DelimiterBox.Text.ToCharArray(); List <OHLCBar> bars = new List <OHLCBar>(); string[] columns = new string[Data.Columns.Count]; for (int i = 0; i < Data.Columns.Count; i++) { columns[i] = Data.Columns[i].ColumnName; } //determining time: if the freq is >= one day, then the time is simply the session end for this day Dictionary <int, TimeSpan> sessionEndTimes = new Dictionary <int, TimeSpan>(); //1 day and up: we can load it all in one go with no trouble, also may require adjustment bool periodicSaving = frequency < BarSize.OneDay; OHLCBar bar; var barsCount = 0; using (StreamReader sr = new StreamReader(FilePathTextBox.Text)) { string line; while ((line = sr.ReadLine()) != null) { barsCount++; if (barsCount < toSkip) { continue; } try { bar = ParseLine(line.Split(separator), columns, priceMultiplier, volumeMultiplier); } catch (Exception ex) { MessageBox.Show("Importing error: " + ex.Message); return; } //only add the bar if it falls within the specified date range if (bar.DT >= MinDT.Value && bar.DT <= MaxDT.Value) { bars.Add(bar); } //with 30 bars, we make a check to ensure that the user has entered the correct frequency if (bars.Count == 30) { //the reason we have to use a bunch of bars and look for the most frequent timespan between them //is that session breaks, daily breaks, weekends, etc. can have different timespans despite the //correct frequency being chosen List <int> secDiffs = new List <int>(); for (int i = 1; i < bars.Count; i++) { secDiffs.Add((int)Math.Round((bars[i].DT - bars[i - 1].DT).TotalSeconds)); } int mostFrequent = secDiffs.MostFrequent(); if ((int)Math.Round(frequency.ToTimeSpan().TotalSeconds) != mostFrequent) { MessageBox.Show("You appear to have selected the wrong frequency."); return; } } if (periodicSaving && bars.Count > 1000) { //convert to exchange timezone ConvertTimeZone(bars, tzInfo); //low frequencies, < 1 day. No adjustment required and inserting data at intervals instead of all at once using (var storage = DataStorageFactory.Get()) { try { storage.AddData(bars, _instrument, frequency, OverwriteCheckbox.IsChecked.HasValue && OverwriteCheckbox.IsChecked.Value, false); } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); } } bars.Clear(); } } } if (bars.Count == 0) { return; } //convert to exchange timezone ConvertTimeZone(bars, tzInfo); //if only the date column is set, we need to get the session info and generate the closing time ourselves if (frequency >= BarSize.OneDay && !Data.Columns.Contains("Time") && !Data.Columns.Contains("DateTime")) { //get the closing time for every day of the week var dotwValues = MyUtils.GetEnumValues <DayOfTheWeek>(); foreach (DayOfTheWeek d in dotwValues) { if (_instrument.Sessions.Any(x => x.ClosingDay == d && x.IsSessionEnd)) { var endTime = _instrument.Sessions.First(x => x.ClosingDay == d && x.IsSessionEnd).ClosingTime; sessionEndTimes.Add((int)d, endTime); } else { sessionEndTimes.Add((int)d, TimeSpan.FromSeconds(0)); } } for (int i = 0; i < bars.Count; i++) { int dayOfWeek = bars[i].DT.DayOfWeek.ToInt(); bars[i].DT = bars[i].DT.Date + sessionEndTimes[dayOfWeek]; } } //if there are no dividends/splits, but there IS an adjclose column, use that to adjust data right here //if there are divs/splits, adjustment will be done by the local storage if (frequency >= BarSize.OneDay && !Data.Columns.Contains("Dividends") && !Data.Columns.Contains("Splits") && Data.Columns.Contains("AdjClose")) { //if we have an adjusted close to work off of, we just use the ratio to get the OHL for (int i = 0; i < bars.Count; i++) { if (bars[i].AdjClose == null) { continue; } decimal ratio = bars[i].AdjClose.Value / bars[i].Close; bars[i].AdjOpen = bars[i].Open * ratio; bars[i].AdjHigh = bars[i].High * ratio; bars[i].AdjLow = bars[i].Low * ratio; } } //sort by date if (frequency >= BarSize.OneDay) { bars.Sort((x, y) => x.DT.CompareTo(y.DT)); } //try to import using (var storage = DataStorageFactory.Get()) { try { storage.AddData(bars, _instrument, frequency, OverwriteCheckbox.IsChecked.HasValue && OverwriteCheckbox.IsChecked.Value, frequency >= BarSize.OneDay); } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); } } sw.Stop(); MessageBox.Show(string.Format("Imported {0} bars in {1} ms.", barsCount, sw.ElapsedMilliseconds)); }