Your interactive trading laboratory!
 • 
7 users online

Quantacula Help

How-To
C# API Reference
Extensions
Development Blog
API-Extensions
Indicator Spotlights

QCommunity Extensions
The open-source GitHub repository of source code for the QCommunity Extensions library. Contains indicators and other extensions submitted by the Quantacula Community. Look for QCommunity indicators when you create a Building Block model, mark the "QCommunity" library check box to expose them.

TASC-Extensions
The open-source GitHub repository of source code for the TASCExtensions Quantacula extension. Contains indicators and other extensions adapted from the Traders' Tips articles in Technical Analysis of Stocks & Commodities magazine.
Historical Data Source
Published by Q Glitch on 11/26/2018

A Historical Data Source is responsible for providing historical market data to Quantacula. It's job is to deliver historical open, high, low, close, volume data (in the form of a BarHistory instance) from a specific data provider. Like all Quantacula extensions, it is implemented as a .NET class, compiled into a .NET class library. You can create a Historical Data Source by using an external development tool such as Microsoft Visual Studio or SharpDevelop.

Creating the Class Library

  1. Be sure your project targets .NET version 4.7.1.
  2. Add references to the QuantaculaCore and QuantaculaData class libraries, located in your Quantacula Studio installation folder.

TargetDotNet471

DataLoaderBase Class Reference

Historical Data Loaders descend from the DataLoaderBase base class. The development of this extension involves these tasks:

  1. Create a new class derived from DataLoaderBase.
  2. Override descriptive properties: Name, Glyph, HelpDescription, etc. described below.
  3. Optionally support initialization, configuration and persistence.
  4. Handle the request for historical data for a specific symbol.

Descriptive Properties

Name

public abstract string Name

Override this property to return the name of your Historical Data Source.

Glyph

public abstract Bitmap Glyph

Override this property to return a 24x24 bitmap to represent your Historical Data Source.

HelpDescription

public abstract string HelpDescription

Override this property to return a brief description of your Historical Data Source.

HelpURL

public virtual string HelpURL

Optionally override this property to return a URL that leads to a web page providing more information about your Historical Data Provider.

Configuration Related Properties and Methods

NeedsConfiguration

public virtual bool NeedsConfiguration

Override this property to return true if your Historical Data Source requires configuration by the user. A data provider might require a user login, API key, or may expose settings that you'd like to interface with. If you enable configuration, also implement the Configure method below.

Configure

public virtual void Configure(string configuration)

Implement this method to handle configuration of your Historical Data Provider. The provider's configuration is boiled down to one string variable, which is passed to you in this method via the configuration parameter. In your implementation, you'd typically bring up a Windows Forms modal dialog which allows the user to provide configuration information. Your method should distill the configuration from this UI into one string and assign this to the Configuration property.

Configuration

public string Configuration

This string contains the configuration that was established by the user during the call to Configure, above.

IsConfigured

public bool IsConfigured

This read-only property returns true if the Configuration string has a value assigned to it.

Persisting Historical Data

DataLoaderBase contains these properties and methods to offer built-in support for persisting historical market data to the user's file system. You can opt-in to this support, ignore it and implement your own persistence scheme as needed, or just ignore persistence completely if does not make sense for your Historical Data Provider. The built-in mechanism works by maintaining files for each symbol's historical data, and then requesting new data from the provider only for dates that are not covered by this local storage.

UsePersistentStorage

public virtual bool UsesPersistentStorage

To opt-in to the built-in persistent storage scheme, simply override this property and return true.

Initialization

public virtual void Initialize(IHost host)

Optionally override this method to perform any required initialization for your Historical Data Provider. Be sure to call base.Initialize if you implement this method. The method provides you an instance of the IHost interface that you can use to access information about the Quantacula installation.

Host Property

public IHost Host

Returns the instance of the IHost interface that you can use to access information about the Quantacula installation.

Requesting Historical Data

protected abstract BarHistory GetHistoryInternal(string symbol, HistoryScale scale, DateTime startDate, DateTime endDate, int maxBars);

Override this method to handle the request for historical data for a specific symbol. You should typically follow these steps:

  1. Validate that your provider can obtain data for the specified symbol and scale (instance of HistoryScale class), and return null if it cannot.
  2. Instantiate a new instance of the BarHistory class to receive the historical data.
  3. Obtain the historical data from the provider for the specified date range (startDate to endDate). Add the data to the BarHistory instance by calling its Add method.
  4. Return the BarHistory instance.

Note: startDate might contain DateTime.MinValue, and endDate might contain DateTime.MaxValue. In this case, return as much historical data as your provider supports.

Because Quantacula makes calls to GetHistoryInternal in parallel you should not use class-level variables in the implementation of this method. Declare any variables you need within the body of this method itself.

if your data provider provides partial bars of data, that is, incomplete bars during market hours, do not return the partial bar. Instead, return the partial bar in the GetPartialBar method.

GetPartialBar

public virtual BarHistory GetPartialBar(string symbol, HistoryScale scale)

Override this method to return a partial bar of data for the specified symbol and scale during market hours. The return value should be an instance of the BarHistory class with one bar added to it (use its Add method). If your provider cannot access partial bars, return null.

GetSymbolMarket

public virtual MarketDetails GetSymbolMarket(string symbol)

You can optionally override this method to return an instance of the MarketDetails class that contains information about the market that the specified symbol trades in.

Bulk Data Update

For certain historical data providers, it makes sense to implement a bulk data update option in addition to the default on-demand data updates that Quantacula defaults to. Implement the following properties and methods to support bulk data update in your Historical Data Source. In Quantacula Studio, when the user select a Data Source that supports bulk update, they will see a button allowing them to execute the bulk update operation.

SupportsBulkUpdate

public virtual bool SupportsBulkUpdate

Override this property to return true to indicate that your Data Source supports bulk update.

PerformBulkUpdate

public virtual void PerformBulkUpdate()

Override this method to execute your bulk update. As your update proceeds, you can call the DataUpdateMessage method of the IHost interface (available in the Host property) to communicate to Quantacula Studio. Your message appears in the bulk data update log. When the update is completed, call the DataUpdateCompleted method of the Host property.

CancelBulkUpdate

public virtual void CancelBulkUpdate()

Override this method to cancel a bulk data update operation in progress.

LoadFromStorage

public BarHistory LoadFromStorage(string symbol, HistoryScale scale)

If you've opted into the built-in persistent storage mechanism, a bulk update workflow will probably be, load a symbol's data from persistent storage, look at its last DateTime to determine if it needs to be updated, update it, then save it back to storage. Use LoadFromStorage to load a symbol from persistent storage. The return value is a fully populated BarHistory object.

SaveToStorage

public void SaveToStorage(BarHistory bh)

After your bulk update process updates a BarHistory instance, use this method to save it back to persistent storage.

Accessing Symbols

Symbols

public virtual List<string> Symbols

When you think about historical data providers, consider two distinct types:

  1. Providers that can return historical data for a wide range of symbols across a whole market, typically via internet service calls (examples are the QPremium, and the Yahoo Data Sources).
  2. Providers that access a fixed set of symbols, typically stored on a local computer file system (examples are the ASCII and Metastock Data Sources).

For the second case, it makes sense to allow the Historical Data Source to communicate the list of symbols that it contains. This is the purpose of the Symbols property. You can optionally override the Symbols property to return a list of symbols that the Historical Data Source has available.

In Quantacula Studio, the ASCII and Metastock Historical Data Source implementations expose their Symbols in this way. When creating a new Data Source based on any Historical Data Source that supports the Symbols property, the user can optionally create a Universe that automatically contains all of the symbols that the Data Source contains.

Example

Although Google Finance no longer provides their historical data service, its implementation is a concise example of how a Historical Data Source can be implemented. Here is the complete code for the legacy Google Finance Data Provider.

using System;
using System.Drawing;
using QuantaculaCore;
using System.Globalization;
using System.Net;

namespace QuantaculaData
{
    //get historical data from Google
    public class GoogleDataLoader : DataLoaderBase
    {
        //Name
        public override string Name
        {
            get
            {
                return "Google Finance";
            }
        }

        //Glyph
        public override Bitmap Glyph
        {
            get
            {
                return Properties.Resources.Google;
            }
        }

        //help description
        public override string HelpDescription
        {
            get
            {
                return "Obtains free historical market data from the Google Finance web site.";
            }
        }

        //use persistent storage
        public override bool UsesPersistentStorage
        {
            get
            {
                return true;
            }
        }

        //get history
        protected override BarHistory GetHistoryInternal(string symbol, HistoryScale scale, DateTime startDate, DateTime endDate, int maxBars)
        {
            //supports daily
            if (scale.Scale != HistoryScales.Daily)
                return null;

            //construct URL
            if (startDate == DateTime.MinValue)
                startDate = new DateTime(2000, 1, 1);
            if (endDate == DateTime.MaxValue)
                endDate = DateTime.Now.Date;
            string url = "http://finance.google.com/finance/historical?q=" + symbol + "&output=csv&startdate=" + FormatDate(startDate) + "&enddate=" + FormatDate(endDate);

            //try and call
            WebClient wc = new WebClient();
            string data = wc.DownloadString(url);
            string[] lines = data.Split('\n');

            //parse
            BarHistory bh = new BarHistory(symbol, scale);
            for(var n = lines.Length - 1; n > 0; n--)
            {
                string line = lines[n].Trim();
                if (line == "")
                    continue;
                string[] tokens = line.Split(',');
                if (tokens[1].Trim() == "-")
                    continue;
                DateTime dt = DateTime.ParseExact(tokens[0], "d-MMM-yy", CultureInfo.InvariantCulture);
                double o = Double.Parse(tokens[1], CultureInfo.InvariantCulture);
                double h = Double.Parse(tokens[2], CultureInfo.InvariantCulture);
                double l = Double.Parse(tokens[3], CultureInfo.InvariantCulture);
                double c = Double.Parse(tokens[4], CultureInfo.InvariantCulture);
                double v = Double.Parse(tokens[5], CultureInfo.InvariantCulture);
                bh.Add(dt, o, h, l, c, v);
            }
            return bh;
        }

        //private members

        //format a date for Google
        private string FormatDate(DateTime dt)
        {
            return dt.ToString("MMM+d+yyyy", CultureInfo.InvariantCulture);
        }
    }
}