Documentation

See also tutorials, videos and chat.

Key Concepts

Getting Started

Welcome

Welcome to QuantConnect. We are an open source, community driven algorithmic trading platform. Our trading engine is powered by LEAN, a cross platform, multi-asset technology which brings cutting edge finance to the open source community. We support C#, Python and F# programming languages making us a truly open platform.

Our Mission

We believe the future of finance is automated and we plan to be the quantitative trading infrastructure of the future. We believe algorithmic trading is a powerful tool and we want to open it up to all investors.

Select Language (C#PythonF#): C# | Python | F#
//Over here you'll see code snippets and examples demonstrating the API!
//Over here you'll see code snippets and examples demonstrating the API!
#Over here you'll see code snippets and examples demonstrating the API!

Security Privacy

You own all your intellectual property and your code. Your code is private by default unless you explicitly share it with the community in the forums or with another team member via collaboration. You are creating valuable intellectual property and we respect this, and wish to make it easier.Only two QuantConnect staff members have access to the database. If we ever need access to your algorithm for the purpose of debugging, we only explicitly request permission first. Please see our terms and conditions.

Data Library

We provide an enormous library of data for your backtesting roughly 40TB in size. This library includes:

Type Source Start Date Symbols Resolutions
US Equity QuantQuote Jan 1998 16,400 Tick, Sec, Min, Hour, Daily
Forex FXCM Apr 2007 13 Tick, Sec, Min, Hour, Daily
Forex OANDA Apr 2004 71 Tick, Sec, Min, Hour, Daily
CFD OANDA Apr 2004 50 Tick, Sec, Min, Hour, Daily
Options AlgoSeek Jan 2010 4000 Minute Bars Only
Futures AlgoSeek Jan 2009 1000 Tick, Second, Minute (Trades, Quotes)

More information on the data library and its symbols can be found at the Data Library.

Business Model

QuantConnect makes backtesting available for free and charges a small monthly fee to cover live algorithm trading. This offsets our costs and aligns our interests with yours - our client. We also work with brokerages to make your live trading free.

Developing in the IDE

Coding Your Algorithm

Write code in project files and then press the Build button to compile your algorithm. Build errors will be displayed in the console and highlighted with red-lines.

You can add, rename and delete files in your project in the Projects tab. You can create a virtual folder for your project by placing a slash ("/") into the name of your file.

Algorithms require only initialization and data event handlers.

public class BasicTemplateAlgorithm : QCAlgorithm
{
	public override void Initialize() {
		// Setup algorithm requirements: cash, dates and securities.
                // Initialize is called once at the start of the algorithm.
	}

	public override void OnData(Slice data) {
               // Data requested is then piped into event handlers like this one.
	}
}
class BasicTemplateAlgorithm(QCAlgorithm):

	def Initialize(self):
		'''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''
		pass
		
	def OnData(self, data):
        '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
            data: Slice object keyed by symbol containing the stock data
        '''
		pass

QuantConnect Backtesting and Coding Environment.

Backtesting Your Algorithm

Once you've got an algorithm compiling you can click the Play button to launch a backtest. You can launch as many backtests as want in parallel and results are shown in the result drop-down.

University Algorithms

The QuantConnect Learn Tab is a collection of videos, tutorials and algorithms to demonstrate the API. There are 50+ algorithms covering all aspects of the API and common questions users have raised over time.

Data Manager

The Data Manager Tab is a searchable database of the QuantConnect Data Library. Each asset details are accessible including the start date, delist date, source of the data, resolutions available and the exchange the asset is traded.

API Help Documentation

The Help Tab details the classes and API of the underlying LEAN engine so you can see the methods and class infrastructure. It includes an indicator reference table to see all the indicators available.

Shortcut Keys

Here are some keyboard short-cuts built into the IDE to make coding easier.

Short Cut Description
Ctrl + Space Initiate full auto-complete
Ctrl + / Toggle comments on selected code
Ctrl + Up/Down Increase/decrease font size
Ctrl + S Save document and compile project
Ctrl + D Remove line
Alt + Up/Down Move line up/down
Alt + Shift + Up/Down Copy lines up/down
Alt + 0 (zero) Collapse all code blocks
Alt + Shift + 0 (zero) Expand all code blocks

The full list of short cuts can be found on at the ACE Editor open source project.

Algorithm Reference

Overview

QuantConnect's LEAN engine manages your portfolio and data feeds letting you focus on your algorithm strategy and execution. Data is piped into your strategy via event handlers, upon which you can place trades. We provide basic portfolio management and fill modelling underneath the hood automatically. This is provided by the QCAlgorithm base class.

All algorithms extend QCAlgorithm, which provides some key helper properties for you to use: Security Manager, Portfolio Manager, Transactions Manager, Notification Manager and Scheduling Manager. Along with hundreds of helper methods to make the API easy to use. We'll go into more detail on those below, but its important for you to know the basic infrastructure around your algorithm.

The Securities propertyget_Securities() method is a dictionary of Security objects. Each asset (equity, forex pair etc) in your algorithm has a security object. All the models for a security live on these objects: e.g. Securities["IBM"].FeeModel or Securities["IBM"].Price.get_Securities().get_Item("SPY").get_Price()

Portfolio is a dictionary of SecurityHolding classes. These classes track the individual portfolio items profit and losses, fees and quantity held. e.g. Portfolio["IBM"].LastTradeProfitDecimal profit = get_Portfolio().get_Item("IBM").get_LastTradeProfit();.

Other helpers like Transactions, Schedule, Notify, and Universe have their own helper methods which we'll explain below.

All algorithms must have an Initialize() method to setup your strategy. Once setup most algorithms have OnData event handlers to process market data and make trading decisions.

public class QCAlgorithm
{
        SecurityManager Securities;   //Array of Security objects.
        SecurityPortfolioManager Portfolio;  // Array of SecurityHolding objects
        SecurityTransactionManager Transactions;  // Transactions helper
        ScheduleManager Schedule;  // Scheduling helper
        NotificationManager Notify; //Email, SMS helper
        UniverseManager Universe; // Universe helper
 
        //Set up Requested Data, Cash, Time Period.
        public virtual void Initialize() { ... };
 
        //Event Handlers:
        public virtual OnData(Slice data) { ... };
        public virtual OnDividend() { ... };
        public virtual OnEndOfDay() { ... };
        public virtual OnEndOfAlgorithm() { ... };
        
        //Helpers... 
        public SimpleMovingAverage SMA();
}

Initializing Algorithms

The Initialize method is called to setup your strategy. Here you can request data, set starting cash or warm up periods.

Setting Cash

In backtests you can set your starting capital using the SetCash(decimal cash)self.SetCash(decimal cash)this.SetCash(decimal cash) method. In live trading this is ignored and your brokerage cash is used instead. In paper trading we set the cash to a fictional $100,000 USD.

SetCash(25000);
this.SetCash(100000)
self.SetCash(100000)

Setting Dates

Backtesting uses the SetStartDate(int year, int month, int day) self.SetStartDate(int year, int month, int day) this.SetStartDate(int year, int month, int day) and SetEndDate(int year, int month, int day) self.SetEndDate(int year, int month, int day) this.SetEndDate(int year, int month, int day) methods to configure the backtest time range. If unspecified the end date defaults to yesterday. In .NET languages you can also use a DateTime object to set the dates.

SetStartDate(2013, 1, 1);         // Set start date to specific date.
SetEndDate(2015, 1, 1);         // Set end date to specific date.
SetEndDate(DateTime.Now.Date.AddDays(-1)); // Or use a relative date.
self.SetStartDate(2013,1,1)
self.SetEndDate(2015,1,1)
self.SetEndDate(datetime.now() - timedelta(1)) # Or use a relative date.
this.SetStartDate(2013, 10, 7)
this.SetEndDate(2013, 10, 11)

Selecting Asset Data

Algorithms can manually subscribe to data for specific assets they need, or use universes to choose groups of assets based on filtering criteria (e.g. all stocks with volumes greater than $10M/day). See more about Universes here.

To manually subscribe to a specific asset you can call the AddEquity(), AddForex(), AddCrypto(), AddCfd() and AddOption() methods in your Initialize() method. You can subscribe to 500 minute resolution datafeeds, 100 second resolutions feeds and 10 tick resolution datafeeds.

QuantConnect supports international trading across multiple timezones and markets. Markets are used to distinguish between the same tickers on different exchanges (e.g. FXCM and OANDA both offer EURUSD, but have different rates).

QuantConnect provides 40TB of US Equities, US Options, FXCM FX and OANDA FX data. Check out more information about our data in our data library.

We provide data in tick, second, minute, hour or daily resolutions. These are specified by the Resolution enum.

If there is a gap in the data (e.g. because there are no trades), by default the data is still pumped into your strategy on each time step. This behavior is called "fillForward" and defaults to true. You can disable this by setting fillForward to false.

By default equity data in QuantConnect is Split and Dividend adjusted backwards in time to give smooth continuous prices. This allows easy use for indicators. Some algorithms need raw or partially adjusted price data. You can control this with the SetDataNormalizationMode() method. The DataNormalizationMode enum has the values Adjusted (default), Raw, SplitAdjusted, and TotalReturn. When data is set to Raw mode the dividends are paid as cash into your algorithm and the splits are directly applied to your holding quantity.

If you have your own custom data you'd like to backtest against, check out the custom data section.

// Complete Add Equity API - Including Default Parameters:
AddEquity(string ticker, Resolution resolution = Resolution.Minute, string market = Market.USA, bool fillDataForward = true, decimal leverage = 0m, bool extendedMarketHours = false)

//Complete Add Forex API - Including Default Parameters:
AddForex(string ticker, Resolution resolution = Resolution.Minute, string market = Market.FXCM, bool fillDataForward = true, decimal leverage = 0m)
AddEquity("AAPL"); //Add Apple 1 minute bars (minute by default).
AddForex("EURUSD", Resolution.Second); //Add EURUSD 1 second bars.
this.AddEquity("SPY", Resolution.Minute) |> ignore
this.AddForex("EURUSD", Resolution.Second) |> ignore
self.AddEquity("SPY")  # Default to minute bars
self.AddForex("EURUSD", Resolution.Second) # Set second bars.
//Setting the data normalization mode for the MSFT security to raw (pay dividends as cash)
Securities["MSFT"].SetDataNormalizationMode(DataNormalizationMode.Raw);
# Setting the data normalization mode for the MSFT security to raw (pay dividends as cash)
self.Securities["SPY"].SetDataNormalizationMode(DataNormalizationMode.Raw);
(* Setting MSFT security to use raw prices *)
this.Securities.Item("MSFT").SetDataNormalizationMode(DataNormalizationMode.Raw);

Setting Warm Up Period

Often algorithms need some historical data to prime technical indicators, or populate historical data arrays. Using the SetWarmUp(TimeSpan period) or SetWarmUp(int barCount) methods you can specify a warm up period for your algorithm which pumps data in from before the start date. During the warm up period you cannot place a trade.

Algorithms can use the bool IsWarmingUp property to determine if the warm up period has completed.

See more about using historical data in the History section.

SetWarmUp(200); //Warm up 200 bars for all subscribed data.
SetWarmUp(TimeSpan.FromDays(7)); //Warm up 7 days of data.
self.SetWarmUp(200) //Warm up 200 bars for all subscribed data.
self.SetWarmUp(timedelta(7)) //Warm up 7 days of data.
this.SetWarmUp(200)

Cash and Brokerage Models

US Equity brokerage accounts are either Cash or Margin based accounts. Cash accounts do not allow leveraged trading, whereas Margin accounts support 2-4x leverage on your account value. You can set your brokerage account type in your initialization with SetBrokerageModel(BrokerageName broker, AccountType account);.

The BrokerageName enum supports values of Default, TradierBrokerage, InteractiveBrokersBrokerage, FxcmBrokerage and OandaBrokerage. When setting the brokerage name we also set the trading fee structures for that brokerage.

The AccountType enum supports values of Cash and Margin. When using cash leverage is disabled by default, and the cash settlement period is set to 3 days. Margin accounts are settled immediately and have a leverage of 2.

Margin accounts with more than $25,000 in equity are eligible for pattern day trading margin limits. This increases your available leverage to 4x while the market is open and 2x overnight. To model this behavior in your algorithm you must set your security MarginModel a PatternDayTradingMarginModel class.

See more about brokerage models in the Reality Modelling section.

//Brokerage model and account type:
SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin);

//Add securities and if required set custom margin models 
var spy = AddEquity("SPY"); //Defaults to minute bars.
spy.MarginModel = new PatternDayTradingMarginModel();
#Brokerage model and account type:
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Cash)

//Add securities and if required set custom margin models 
spy = self.AddEquity("SPY") # Default to minute bars
spy.MarginModel = PatternDayTradingMarginModel()
(* In Initialize method, set the brokerage models *)
this.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Cash);
this.AddEquity("SPY", Resolution.Second) |> ignore
(* Then if required, you can set specific margin models for your secutities *)
this.Securities.Item("SPY").MarginModel <- new PatternDayTradingMarginModel()
// You can also create your own brokerage model: IBrokerageModel
class MyBrokerage: DefaultBrokerage {
   // Custom implementation of brokerage here.
} 

SetBrokerageModel(new MyBrokerage());

Setting Benchmark

You can set a custom benchmark for your algorithm using the SetBenchmark(Symbol ticker)self.SetBenchmark(Symbol ticker)this.SetBenchmark(Symbol ticker) method. This should be called in your Initialize() function.

// Defaults to Equity market
SetBenchmark("IBM"); 
this.SetBenchmark("IBM")
self.SetBenchmark("SPY")

Handling Data

Requested data is passed into event handlers for you to use to make trading decisions. The primary event handler, Slice, groups all data types together at a single moment in time in the OnData(Slice data) handler. Slice is short for "time slice" - representing a slice of time and values of the data at that time. C# and F# also allow you to receive data with dedicated event handlers for each data type e.g OnData(TradeBars data).Python only supports the Slice event handlers.

All data uses DataDictionary objects to group data by symbol and provide easy access to information. The plural of the type denotes the collection of objects e.g. the TradeBars DataDictionary is made up of TradeBar objects. You can access individual data points in the dictionary through its string or symbol dictionary index. For example var ibmTradeBar = tradebars["IBM"].

Time Slices

The Slice event handler combine all of the data together into a single method. It represents the data at a point in time. The Slice object contains many helpers for accessing your data. The Slice objects arrive to the OnData(Slice data) event handler.

The Slice object gives you three ways to access your data:

  1. Dynamic string/symbol indexer which returns a dynamic object of your type slice["IBM"].
  2. Statically typed properties (slice.Bars[], slice.QuoteBars[]).
  3. Statically typed Get<T>() helper

Strongly typed access gives you compile time safety but dynamic types can sometimes simplify coding. We recommend static types as they are easier to debug.

Python is dynamically typed so does not have the Get method. Primary Slice data access is through the string/symbol indexer.

Slice is the recommended method for data access in your algorithm.

Slice has the following internal structure:

class Slice : IEnumerable<KeyValuePair<Symbol, BaseData>>
{
    TradeBars Bars;
    QuoteBars QuoteBars;
    Ticks Ticks;
    OptionChains OptionChains;
    FuturesChains FuturesChains;
    Splits Splits;
    Dividends Dividends;
    Delistings Delistings;
    SymbolChangedEvents SymbolChangedEvents;
}

It contains all the data for a given moment of time. TradeBars and QuoteBars are symbol/string indexed dictionaries so you can easily access the data. Ticks is a symbol-list dictionary with a list of ticks for that moment of time.

To make accessing the data easier the Slice object itself can also be indexed. e.g. slice["IBM"] will return a TradeBar for IBM. slice["EURUSD"] will return a QuoteBar for EURUSD.

// Event handler for Slice method
public void OnData(Slice data) {
}
// Event handler for Slice method
member this.OnData(slice:Slice) =  
      ()
# Event handler for the slice method
def OnData(self, slice):
    pass
//Access data in a Slice object: 
// 1. Strong Typed Properties: Ticks, TradeBars, Delistings, SymbolChangedEvents, Splits and Dividends
var bars = slice.Bars; // e.g. bars["IBM"].Open

// 2. Strong Typed Get Accessor:
var bars = slice.Get<TradeBars>(); //e.g. bars["IBM"].Open
var bar   = slice.Get<TradeBar>("IBM"); //e.g. bar.Open

// 3. Dynamic String / Symbol Indexer:
var bar = slice["IBM"]; // e.g. bar.Open
#Access data in a Slice object: 
# 1. Grouped Properties: Ticks, Bars, Delistings, SymbolChangedEvents, Splits and Dividends
bars = slice.Bars; # e.g. bars["IBM"].Open

# 2. Dynamic String / Symbol Indexer:
bar = slice["IBM"] # e.g. bar.Open - TradeBar properties OHLCV
spyTickList = data["SPY"] # Tick assets return a list of Tick objects.

Event Handlers

In C#/F# data is also piped into dedicated event handlers for each data type. To use data this way you need to put an event handler in your algorithm which follows the pattern: public void OnData(TradeBars data) {}. LEAN automatically detects the method exists and sends data to it. Python does not support dedicated event data handlers. Slice is the preferred way to access data for your strategy.

When working with Ticks they can occur at the same moment of time across different exchanges. Because of this we provide the ticks as a list. In backtesting this moment is stepped each second and you will get many ticks per second; in live trading it is stepped as fast as possible and you will probably get 1 tick per event. The public void OnData(Ticks data) {} event handler captures these events. To understand the event handlers you should click on each class object link below to see its structure.

public void OnData(TradeBars data) {
    // TradeBars objects are piped into this method.
}
public void OnData(Ticks data) {
    // Ticks objects are piped into this method.
}

Data Formats

There are six financial data types: TradeBars, Ticks, Delistings, SymbolChangedEvents, Splits and Dividends.

All data extends from BaseData - the core data class which provides Symbol, Time and Value properties.

TradeBar events contains Open, High, Low, Close and Volume properties for a given period of time.

Dividend events are triggered on payment of a dividend. It provides the Distribution per share.

Split events are triggered on a share split or reverse split event. It provides a SplitFactor and ReferencePrice.

SymbolChangedEvent provide notice of new ticker names for stocks, or mergers of two tickers into one. It provides the OldSymbol and NewSymbol tickers.

Delisting events provide notice an asset is no longer trading on the exchange.

Ticks is a string indexed dictionary of lists of ticks.

These data types all have dedicated event handlers which follow the pattern above (public void OnData(Type data) {}); and are also passed into the OnData(Slice data) event handler.

All these data types are accessible through their properties on the slice object. i.e.

  • slice.Bars
  • slice.Ticks
  • slice.Splits
  • slice.Dividends
  • slice.Delistings
  • slice.SymbolChangedEvents

//TradeBars collection of TradeBar objects
TradeBars data; TradeBar ibm = data["IBM"];

//Dividends collection of Dividend objects
Dividends data; Dividend ibm = data["IBM"];

Importing Custom Data

Introduction to Custom Data

LEAN supports backtesting almost any external custom data source. To use this feature you need to add the data during initialize using AddData<T>() self.AddData() and instruct your algorithm how to read your data. We provide helpers for popular data sources like Quandl, but if you are using your own format or server you'll need to create a custom type.

Initializing Custom Data

During initialize your algorithm must use AddData<T>(string ticker, Resolution resolution = Resolution.Daily). This gives LEAN the T-type factory to create the objects, the name of the data and the resolution at which to poll the data to check for updates. self.AddData(Type class, string ticker, Resolution resolution = Resolution.Daily). This gives LEAN the type factory to create the data objects and the resolution to poll the remote datasource for updates.

The framework checks for new data every as instructed by the Resolution period, i.e. Resolution.Tick polls constantly, Resolution.Second polls every second, and Resolution.Minute every minute. Hourly and Daily Resolutions are polled every 30 minutes to prevent skipping a day if the data was emitted late.

// In Initialize method:
AddData<Weather>("KNYC", Resolution.Daily);
# In Initialize method:
self.AddData(Weather, "KNYC", Resolution.Minute)

Creating and Reading Custom Data

You must create a custom type to instruct LEAN where to get your data, and how to read it. We support many different data types and formats. You can even change source locations for backtesting and live modes. All data must extend from BaseData and override the Reader and GetSource methods.

GetSource instructs LEAN where to find your data. It must return a SubscriptionDataSource object containing the string Url to find your data, and the format of the data (SubscriptionTransportMedium RemoteFile or Rest). When the source returned changes URL the data is downloaded again. This allows LEAN to cache large files and only download new data when requested. This also allows you to break up large intraday data into smaller daily files, speeding up the backtest.

When using SubscriptionTransportMedium.Rest the url provided is polled at each Resolution time step and is assumed to be sufficient for 1-data point. This is generally intended for live data sources.

Reader takes one line of data provided by the source, and parses it into one of your custom objects (e.g. Yahoo in the code snippet). In addition to setting your custom type properties, you should also take care to set three required properties:

  1. Symbol - Should always be set to config.Symbol
  2. Time - Required synchronization of custom data
  3. Value - Required for purchasing and portfolio calculations

When there is no usable data in a line, your type should return null.

public class Weather : BaseData
{
    public decimal MaxC = 0;
    public decimal MinC = 0;
    public string errString = "";

    public override SubscriptionDataSource GetSource(
        SubscriptionDataConfig config, 
        DateTime date, 
        bool isLive)
    {
        var source = string.Format(
                "https://www.wunderground.com/history/airport/{0}/{1}/1/1/CustomHistory.html?dayend=31&monthend=12&yearend={1}&format=1",
                config.Symbol, date.Year);

          return new SubscriptionDataSource(source,
              SubscriptionTransportMedium.RemoteFile);
    }

    public override BaseData Reader(
        SubscriptionDataConfig config,
        string line,
        DateTime date,
        bool isLive)
    {
        if (string.IsNullOrWhiteSpace(line) ||
            char.IsLetter(line[0])) 
            return null;
            
        var data = line.Split(',');

        return new Weather()
        {
            // Make sure we only get this data AFTER trading day - don't want forward bias.
            Time = DateTime.Parse(data[0]).AddHours(20), 
            Symbol = config.Symbol,
            MaxC = Convert.ToDecimal(data[1]),
            Value = Convert.ToDecimal(data[2]),
            MinC = Convert.ToDecimal(data[3]),
        };
    }
}
class Weather(PythonData):
    ''' Weather based rebalancing'''
    
    def GetSource(self, config, date, isLive):
        source = "https://www.wunderground.com/history/airport/{0}/{1}/1/1/CustomHistory.html?dayend=31&monthend=12&yearend={1}&format=1".format(config.Symbol, date.year);
        return SubscriptionDataSource(source, SubscriptionTransportMedium.RemoteFile);       


    def Reader(self, config, line, date, isLive):
        # If first character is not digit, pass
        if not (line.strip() and line[0].isdigit()): return None
        
        data = line.split(',')
        weather = Weather()
        weather.Symbol = config.Symbol
        weather.Time = datetime.strptime(data[0], '%Y-%m-%d') + timedelta(hours=20) # Make sure we only get this data AFTER trading day - don't want forward bias.
        weather.Value = decimal.Decimal(data[2])
        weather["MaxC"] = float(data[1])
        weather["MinC"] = float(data[3])

        return weather

Consolidating Data

Consolidators are used to combine smaller data points into larger bars. Commonly this is used to create 5, 10 or 15 minute bars from minute data. We provide tick, second, minute, hour and daily resolution bars which can be consolidated into any form you wish.

To use consolidators you create the consolidator class and then register it to receive data. Once you've registered the class it automatically gets data updates. Once it has aggregated the desired data it emits an event on the DataConsolidated event handler. You setup the consolidator and bind to this event handler once from inside your Initialize() method to prevent your algorithm from running out of memory.

// Create and initialize a consolidator
public override void Initialize()
{
	//...other initialization...
	AddEquity("SPY", Resolution.Minute);
	var consolidator = new TradeBarConsolidator(15);
	consolidator.DataConsolidated += {
		Debug(Time.ToString() + " > New Bar!");
	};
	SubscriptionManager.AddConsolidator("SPY", consolidator);
}
# Create and initialize a consolidator
def Initialize(self):
    # ...other initialization...
    self.AddEquity("SPY", Resolution.Minute)
    consolidator = TradeBarConsolidator(15)
    consolidator.DataConsolidated += self.OnDataConsolidated
    self.SubscriptionManager.AddConsolidator("SPY", consolidator)

def OnDataConsolidated(self, sender, bar):
    self.Debug(str(self.Time) + " > New Bar!")

TradeBars vs QuoteBars

The specific consolidator you should use depends on the data and assets you're requesting. TradeBars should be consolidated with a TradeBarConsolidator ; QuoteBars with a QuoteBarConsolidator and Ticks with a TickConsolidator . Quote tick data must be consolidated by the TickQuoteBarConsolidator .

For each asset class and the data we provide please see the data library. It is a little confusing but here is the summary of QuantConnect provided data:

  • Equities - trade data only. For Resolution.Tick use the TickConsolidator, for all other resolutions use the TradeBarConsolidator.
  • Forex and CFD - quote data only. For Resolution.Tick use the TickQuoteBarConsolidator, for all other resolutions use the QuoteBarConsolidators.
  • Options- trade and quote data, at Resolution.Minute only. For consolidating options data use the TradeBarConsolidator or the QuoteBarConsolidator (depending on if you're consolidating trades or quotes).
  • Futures - trade and quote data, at all resolutions!

Consolidators Indicators

If you'd like to have an indicator updated using a specific resolution of data; e.g. 30-period, 15-minute EMA; then you should ideally use the helper methods which come with the indicators. Most indicators handle setting up these resolution periods for you. See Indicators for more information.

You may have a custom indicator which doesn't have this helper. In this case you should register your indicator with the RegisterIndicator function which will automatically create a consolidator and pipe the data into your Indicator class.

In very rare cases you may want to update your indicator manually. You can do this by passing each data point into your indicator.Update() method from your consolidator DataConsolidated event handler.

// Consolidating minute SPY into Daily SMA/EMA.
var ema = EMA("SPY", 14, Resolution.Daily);
var sma = SMA("SPY", 14, Resolution.Daily);
// Register for daily bars from minutely data.
AddEquity("SPY", Resolution.Minute);
var myTradeBarIndicator = new MyTradeBarIndicator(120);
RegisterIndicator("SPY", myTradeBarIndicator, Resolution.Daily);
# Consolidating minute SPY into Daily SMA/EMA.
ema = self.EMA("SPY", 14, Resolution.Daily)
sma = self.SMA("SPY", 14, Resolution.Daily)
# Register for daily bars from minutely data.
self.AddEquity("SPY", Resolution.Minute)
myTradeBarIndicator = MyTradeBarIndicator(120)
self.RegisterIndicator("SPY", myTradeBarIndicator, Resolution.Daily)
// Create, initialize a consolidator and add an indicator
private SimpleMovingAverage _sma;

public override void Initialize()
{
	//...other initialization...
	AddEquity("SPY", Resolution.Minute);
	var consolidator = new TradeBarConsolidator(30);
	_sma = new SimpleMovingAverage(10);
	RegisterIndicator("SPY", _sma, consolidator);
	SubscriptionManager.AddConsolidator("SPY", consolidator);
}
# Create, initialize a consolidator and add an indicator
def Initialize(self):
    # ...other initialization...
    self.AddEquity("SPY", Resolution.Minute)
    consolidator = TradeBarConsolidator(30)
    self._sma = SimpleMovingAverage(10)
    self.RegisterIndicator("SPY", self._sma, consolidator)
    self.SubscriptionManager.AddConsolidator("SPY", consolidator)

Securities and Portfolio

Securities and Portfolio Classes

Algorithms have a Securities property which stores a Security object for each asset in your algorithm. Security objects hold the models (backtesting behaviors) and properties of an asset. Each security can be completely customized to behave as you'd like. Securities is a Dictionary<Symbol, Security> so you can access your Security objects with their ticker Securities["IBM"].Price.

// Popular Securities Property Values:
Securities["IBM"].HasData           // Security has data 
                 .Invested          // Have holdings
                 .LocalTime         // Time on the asset exchange
                 .Holdings          // Portfolio object
                 .Exchange          // Exchange information
                 .FeeModel;         // Fee model setter

Security objects also carry all the models for creating realistic backtests. These models are set via the public security properties and then used in LEAN to improve your backtest realism.

The Portfolio property is a collection of SecurityHolding objects to provide easy access to the holding properties. The Portfolio class is a Dictionary<Symbol, SecurityHolding> so can be accessed via ticker index: Portfolio["IBM"].IsLong

// Popular Portfolio Property Values:
Portfolio["IBM"].Invested 
                .IsLong            // IsLong, IsShort Holdings.
                .Quantity          // Shares held.
                .UnrealizedProfit; // Holdings profit/loss
                .TotalFees         // Fees incurred since backtest start
                .Price;            // Asset price

Detailed information on these classes can be found in LEAN documentation. Check out the Security class (Securities objects), and SecurityHolding (Portfolio objects) classes.

//Securities array access to Security Objects:
Securities["IBM"].Price
//Security object properties:
class Security {
    Resolution Resolution;
    bool HasData;
    bool Invested;
    DateTime LocalTime;
    SecurityHolding Holdings;
    SecurityExchange Exchange;
    IFeeModel FeeModel;
    IFillModel FillModel;
    ISlippageModel SlippageModel;
    ISecurityPortfolioModel PortfolioModel;
    ISecurityMarginModel MarginModel;
    ISettlementModel SettlementModel;
    IVolatilityModel VolatilityModel;
    ISecurityDataFilter DataFilter;
}
#Securities array access to Security Objects:
self.Securities["IBM"].Price
//Security object properties:
class Security {
    Resolution Resolution;
    bool HasData;
    bool Invested;
    DateTime LocalTime;
    SecurityHolding Holdings;
    SecurityExchange Exchange;
    IFeeModel FeeModel;
    IFillModel FillModel;
    ISlippageModel SlippageModel;
    ISecurityPortfolioModel PortfolioModel;
    ISecurityMarginModel MarginModel;
    ISettlementModel SettlementModel;
    IVolatilityModel VolatilityModel;
    ISecurityDataFilter DataFilter;
}

Trading and Orders

Key Concepts

Algorithms can place an order through calling the appropriate method in the API. Going long is denoted with a ordering positive number, and short a negative one. LEAN does not support hedging (long and short at the same time).

Placing an order generates an OrderTicket which you can use to update, cancel or check the status of your order.

To update an order can call the Update method on the OrderTicket. The Update method takes an UpdateOrderFields object which defines what properties of the order should be updated. In the same way you can cancel your order with the OrderTicket Cancel method.

The OrderTicket Status property can be used to determine if the order is filled. The OrderStatus has the values Submitted, PartiallyFilled, Filled, Cancelled or Invalid.

The Transactions property is a helper that provides easy access to current and past orders and order tickets.

// Popular Transactions methods:
Transactions
            .CancelOpenOrders(Symbol symbol)
            .CancelOrder(int orderId, string orderTag = null)
            .GetOpenOrders()
            .GetOpenOrders(Symbol symbol)
            .GetOrderById(int orderId)
            .GetOrders(Func
	 filter)            .GetOrderTicket(int orderId)            .GetOrderTickets(Func
	
		 filter = null)

// Creating an Order:
OrderTicket limitOrderTicket = LimitOrder("SPY", 100, 205);

// Updating an Order:
limitOrderTicket.Update(new UpdateOrderFields{LimitPrice = 207.50};

// Cancel an Order:
limitOrderTicket.Cancel();
# Creating an Order:
limitOrderTicket = self.LimitOrder("SPY", 100, 205)

# Updating an Order:
updateOrderFields = UpdateOrderFields()
updateOrderFields.LimitPrice = decimal.Decimal(207.50)
limitOrderTicket.Update(updateOrderFields)

# Cancel an Order:
limitOrderTicket.Cancel()
// Cancel all open orders from SPY
List<OrderTicket> cancelledOrders = Transactions.CancelOpenOrders("SPY")

// Cancel order #10
OrderTicket cancelledOrder = Transactions.CancelOrder(10);

// Get open orders
List<Order> openOrders = Transactions.GetOpenOrders();
List<Order> openOrders = Transactions
    .GetOrders(x => x.Status.IsOpen()).ToList();

// Get open orders from SPY
List<Order> openOrders = Transactions.GetOpenOrders("SPY");
List<Order> openOrders = Transactions
    .GetOrders(x => x.Status.IsOpen() && x.Symbol == "SPY").ToList();

// Get open order #10
Order openOrder = Transactions.GetOrderById(10);

// Get order ticket #10
OrderTicket orderTicket = Transactions.GetOrderTicket(10);

// Get open orders tickets from SPY
IEnumerable<OrderTicket> openOrderTickets = Transactions
    .GetOrderTickets(x => x.Status.IsOpen() && x.Symbol == "SPY");
# Cancel all open orders from SPY
cancelledOrders = self.Transactions.CancelOpenOrders("SPY")

# Cancel order #10
cancelledOrder = self.Transactions.CancelOrder(10)

# Get open orders
openOrders = self.Transactions.GetOpenOrders()

# Get open orders from SPY
openOrders = self.Transactions.GetOpenOrders("SPY")

# Get open order #10
openOrder = self.Transactions.GetOrderById(10)

# Get all orders
orders = self.Transactions.GetOrders()

# Get order ticket #10
orderTicket = self.Transactions.GetOrderTicket(10)

# Get all orders tickets
openOrderTickets = self.Transactions.GetOrderTickets()

Set Holdings Helper

Often portfolio based algorithms want to set the portfolio based on percentage weighting. We provide a helper method to perform this weighting for you called SetHoldings .

SetHoldings(Symbol symbol, double percentage, bool liquidateExistingHoldings = false)

When liquidate existing holdings is set to true any existing holdings will first be sold. This may be useful when you're rebalancing to a new set of stocks. The Liquidate method can achieve the same affect.

Liquidate(Symbol symbolToLiquidate = null)
Liquidate sells all holdings in your portfolio, or just the ticker symbol if the parameter is specified.

SetHoldings sets a fraction of unlevered equity. e.g. If you have 2x available leverage, and SetHoldings to 1.0 the algorithm will use 1.0 of your available buying power. To maximize buying power in this case you would make the SetHoldings fractions total 2.0.

// Set fixed percentages of known tickers:
SetHoldings("IBM", 0.25);
SetHoldings("GOOG", 0.25);
SetHoldings("AAPL", 0.25);
SetHoldings("MSFT", 0.25);

// Or set portfolio to equal weighting of all securities:
var weighting = 1m / Securities.Count;
foreach(var security in Securities.Values) {
    SetHoldings(security.Symbol, weighting);
}
# Set fixed percentages of known tickers:
self.SetHoldings("IBM", 0.25)
self.SetHoldings("GOOG", 0.25)
self.SetHoldings("AAPL", 0.25)
self.SetHoldings("MSFT", 0.25)

# Or set portfolio to equal weighting of all securities:
weighting = 1.0 / self.Securities.Count
for security in self.Securities.Values:
    self.SetHoldings(security.Symbol, weighting)

Order Types

We support many different order types. In live trading some of these order types may be simulated depending on your brokerage (for more information on this see Live Trading).

Order Type Method Signature
Market Order
MarketOrder(Symbol symbol, int quantity, bool asynchronous = false, string tag = "")
Asynchronous flag can be used to send the many orders and not wait for the fill response.
Market On Open
MarketOnOpenOrder(Symbol symbol, int quantity, string tag = "")
Fill an order at the market opening. Equity markets only.
Market On Close
MarketOnCloseOrder(Symbol symbol, int quantity, string tag = "")
Fill an order on market closing. Equity markets only. Orders must be submitted 15min before closing.
Stop Market
StopMarketOrder(Symbol symbol, int quantity, decimal stopPrice, string tag = "")
Submit a market order when the stop price is reached.
Limit Order
LimitOrder(Symbol symbol, int quantity, decimal limitPrice, string tag = "")
Fill order for the limit price or better.
Stop Limit Order
StopLimitOrder(Symbol symbol, int quantity, decimal stopPrice, decimal limitPrice, string tag = "")
Submit limit order when stop price is reached.
All order methods return an OrderTicket. The tag parameter can be used to send additional debugging information along with each order object.

// Various order types:
// Fill a market order immediately (before moving to next line of code)
var newTicket = MarketOrder("IBM", 100);

// Place a long limit order with limit price less than current price
var newTicket = LimitOrder("IBM", 100, lastClose * .999m);

// Closing out a short position; long stop above the last close price
var stopPrice = close * 1.0025m;
var newTicket = StopMarketOrder("IBM", 100, stopPrice);

// Closing out a long position on market drop
var stopPrice = close * .9975m;
var newTicket = StopMarketOrder("IBM", -100, stopPrice);

// Limit order trigger on reaching the stop price
var newTicket = StopLimitOrder("IBM", 100, stopPrice, limitPrice);

// Market on Open/Close:
var newTicket = MarketOnCloseOrder("IBM", 100);
var newTicket = MarketOnOpenOrder("IBM", 100);
# Various order types:
# Fill a market order immediately (before moving to next line of code)
newTicket = self.MarketOrder("IBM", 100)

# Place a long limit order with limit price less than current price
newTicket = self.LimitOrder("IBM", 100, lastClose * decimal.Decimal(.999))

# Closing out a short position; long stop above the last close price
stopPrice = close * decimal.Decimal(1.0025)
newTicket = self.StopMarketOrder("IBM", 100, stopPrice)

# Closing out a long position on market drop
stopPrice = close * decimal.Decimal(.9975)
newTicket = self.StopMarketOrder("IBM", -100, stopPrice)

# Limit order trigger on reaching the stop price
newTicket = self.StopLimitOrder("IBM", 100, stopPrice, limitPrice)

# Market on Open/Close:
newTicket = self.MarketOnCloseOrder("IBM", 100)
newTicket = self.MarketOnOpenOrder("IBM", 100)

Order Events

Orders create lots of events you can use to track their status. These events are passed into the OnOrderEvent event handler with the relevant order.

// Override the base class event handler for order events
public override void OnOrderEvent(OrderEvent orderEvent)
{
    var order = Transactions.GetOrderById(orderEvent.OrderId);
    Console.WriteLine("{0}: {1}: {2}", Time, order.Type, orderEvent);
}
# Override the base class event handler for order events
def OnOrderEvent(self, orderEvent):
    order = self.Transactions.GetOrderById(orderEvent.OrderId)
    self.Debug("{0}: {1}: {2}".format(self.Time, order.Type, orderEvent))

Order Error Codes

When an order fails to process it is returned with a negative order code. These error codes mean different things as described below:

Error Code Interpretation
-1 ProcessingError - Unknown error.
-2 OrderAlreadyExists - Cannot submit because order already exists.
-3 InsufficientBuyingPower - Not enough money to to submit order.
-4 BrokerageModelRefusedToSubmitOrder - Internal logic invalidated submit order.
-5 BrokerageFailedToSubmitOrder - Brokerage rejected order.
-6 BrokerageFailedToUpdateOrder - Failed to update order.
-7 BrokerageHandlerRefusedToUpdateOrder - Brokerage rejected update request.
-8 BrokerageFailedToCancelOrder - Brokerage refused to cancel order.
-9 InvalidOrderStatus - Only pending orders can be cancelled
-10 UnableToFindOrder - Cannot find order with that id.
-11 OrderQuantityZero - Cannot submit or update orders with zero quantity.
-12 UnsupportedRequestType - This type of request is unsupported.
-13 PreOrderChecksError - Pre-placement order checks failed.
-14 MissingSecurity - Security is missing. Probably did not subscribe.
-15 ExchangeNotOpen - Some order types require open exchange.
-16 SecurityPriceZero - There isn't any market data yet for the security.
-17 ForexBaseAndQuoteCurrenciesRequired - Need both currencies in cashbook to trade a pair.
-18 ForexConversionRateZero - Need conversion rate to account currency.
-19 SecurityHasNoData - Should not attempt trading without at least one data point.
-20 ExceededMaximumOrders - Transaction manager's cache is full.
-21 MarketOnCloseOrderTooLate - Need to submit market on close orders at least 11 minutes before exchange close.
-22 InvalidRequest - Request is invalid or null.
-23 RequestCanceled - Request was canceled by user.
-24 AlgorithmWarmingUp - All orders are invalidated while algorithm is warming up.
-25 BrokerageModelRefusedToUpdateOrder - Internal logic invalidated update order.
-26 QuoteCurrencyRequired - Need quote currency in cashbook to trade.
-27 ConversionRateZero - Need conversion rate to account currency.
-28 NonTradableSecurity - The order's symbol references a non-tradable security.
-29 NonExercisableSecurity - The order's symbol references a non-exercisable security.

Scheduled Events

Introduction to Scheduled Events

Scheduled events allow you to trigger code to run at specific times of day. This happens regardless of your data events. The schedule API requires a date and time rule to specify when the event is fired.

Scheduled events need a DateRules and TimeRules pair to set a specific time. When the event is triggered the action block is executed.

DateTime Rules

DateRules Class Example Usage
On(year,month,day)
DateRules.On(2013, 10, 7)
Trigger an event on a specific date.
EveryDay(symbol)
DateRules.EveryDay("SPY")
Trigger an event every day a specific symbol is trading.
EveryDay()
DateRules.EveryDay()
Trigger an event every day.
Every(days)
DateRules.Every(DayOfWeek.Monday, DayOfWeek.Friday)
Trigger an event on specific days during week.

TimeRules Class Example Usage
At(hour, min)
TimeRules.At(13, 10)
Trigger an event at a specific time of day (e.g. 13:10).
AfterMarketOpen(symbol, min)
TimeRules.AfterMarketOpen("SPY", 10)
Trigger an event a few minutes after market open for a specific symbol.
BeforeMarketClose(symbol, min)
TimeRules.BeforeMarketClose("SPY", 10)
Trigger an event a few minutes before close for a specific symbol.
Every(period)
TimeRules.Every(TimeSpan.FromMinutes(10))
Trigger an event every period interval.

// Schedule an event to fire at a specific date/time
Schedule.On(DateRules.On(2013, 10, 7), TimeRules.At(13, 0), () =>
{
	Log("SpecificTime: Fired at : " + Time);
});

// Schedule an event to fire every trading day for a security
// The time rule here tells it to fire 10 minutes after SPY's market open
Schedule.On(DateRules.EveryDay("SPY"), TimeRules.AfterMarketOpen("SPY", 10), () =>
{
	Log("EveryDay.SPY 10 min after open: Fired at: " + Time);
});

// Schedule an event to fire every trading day for a security
// The time rule here tells it to fire 10 minutes before SPY's market close
Schedule.On(DateRules.EveryDay("SPY"), TimeRules.BeforeMarketClose("SPY", 10), () =>
{
	Log("EveryDay.SPY 10 min before close: Fired at: " + Time);
});

// Schedule an event to fire on certain days of the week
Schedule.On(DateRules.Every(DayOfWeek.Monday, DayOfWeek.Friday), TimeRules.At(12, 0), () =>
{
	Log("Mon/Fri at 12pm: Fired at: " + Time);
});
# Schedule.On third argument type is System.Action or System.Action[System.String,System.DateTime]
# we need to cast the callback function using Action(...) to make it work

# schedule an event to fire at a specific date/time
self.Schedule.On(self.DateRules.On(2013, 10, 7), \ 
                 self.TimeRules.At(13, 0), \ 
                 Action(self.SpecificTime))

# schedule an event to fire every trading day for a security the
# time rule here tells it to fire 10 minutes after SPY's market open
self.Schedule.On(self.DateRules.EveryDay("SPY"), \ 
                 self.TimeRules.AfterMarketOpen(self.spy, 10), \        
                 Action(self.EveryDayAfterMarketOpen))

# schedule an event to fire every trading day for a security the
# time rule here tells it to fire 10 minutes before SPY's market close
self.Schedule.On(self.DateRules.EveryDay("SPY"), \
                 self.TimeRules.BeforeMarketClose("SPY", 10), \
                 Action(self.EveryDayAfterMarketClose))

# schedule an event to fire on certain days of the week
self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday, DayOfWeek.Friday), \
                 self.TimeRules.At(12, 0), \
                 Action(self.EveryMonFriAtNoon))

# the scheduling methods return the ScheduledEvent object which can be used 
# for other things here I set the event up to check the portfolio value every
# 10 minutes, and liquidate if we have too many losses
self.Schedule.On(self.DateRules.EveryDay(), \ 
                 self.TimeRules.Every(timedelta(minutes=10)), \
                 Action(self.LiquidateUnrealizedLosses))

# schedule an event to fire at the beginning of the month, the symbol is
# optional. 
# if specified, it will fire the first trading day for that symbol of the month,
# if not specified it will fire on the first day of the month
self.Schedule.On(self.DateRules.MonthStart("SPY"), \
                 self.TimeRules.AfterMarketOpen("SPY"), \
                 Action(self.RebalancingCode))
def SpecificTime(self):
    self.Log("SpecificTime: Fired at : {0}".format(self.Time))

def EveryDayAfterMarketOpen(self):
    self.Log("EveryDay.SPY 10 min after open: Fired at: {0}".format(self.Time))

def EveryDayAfterMarketClose(self):
    self.Log("EveryDay.SPY 10 min before close: Fired at: {0}".format(self.Time))

def EveryMonFriAtNoon(self):
    self.Log("Mon/Fri at 12pm: Fired at: {0}".format(self.Time))

def LiquidateUnrealizedLosses(self):
    ''' if we have over 1000 dollars in unrealized losses, liquidate'''
    if self.Portfolio.TotalUnrealizedProfit < -1000:
        self.Log("Liquidated due to unrealized losses at: {0}".format(self.Time))
        self.Liquidate()

def RebalancingCode(self):
    ''' Good spot for rebalancing code?'''
    pass

Indicators

Indicator Introduction

We provide more than 100 technical indicators for you to use in your algorithm. These are provided in two ways; through helper short cut methods, and as class objects. Indicators created through the short cut methods have already been wired up to receive data and are "ready to use". A full list of the indicators and their properties can be found in the reference table below.

One key indicator to learn is the Identity indicator which simply returns the value of the asset. This can be useful for combining indicators together. For example:

var pep = Identity("PEP");    // Pepsi ticker
var coke = Identity("KO");    // Coke ticker
var delta = pep.Minus(coke);  // Difference between them

Reference Table

Indicators Usage
AccelerationBands var abands = ABANDS(Symbol symbol, int period, decimal width = 4, MovingAverageType movingAverageType = null, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.TradeBar] selector = null)
AccumulationDistribution var ad = AD(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.TradeBar] selector = null)
AccumulationDistributionOscillator var adosc = ADOSC(Symbol symbol, int fastPeriod, int slowPeriod, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.TradeBar] selector = null)
AverageDirectionalIndex var adx = ADX(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
AverageDirectionalMovementIndexRating var adxr = ADXR(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
ArnaudLegouxMovingAverage var alma = ALMA(Symbol symbol, int period, int sigma = 6, decimal offset = 0.85, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
AbsolutePriceOscillator var apo = APO(Symbol symbol, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
AroonOscillator var aroon = AROON(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
AroonOscillator var aroon = AROON(Symbol symbol, int upPeriod, int downPeriod, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
AverageTrueRange var atr = ATR(Symbol symbol, int period, MovingAverageType type = null, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
BollingerBands var bb = BB(Symbol symbol, int period, decimal k, MovingAverageType movingAverageType = null, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
BalanceOfPower var bop = BOP(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
CommodityChannelIndex var cci = CCI(Symbol symbol, int period, MovingAverageType movingAverageType = null, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
ChandeMomentumOscillator var cmo = CMO(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
DonchianChannel var dch = DCH(Symbol symbol, int upperPeriod, int lowerPeriod, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
DonchianChannel var dch = DCH(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
DoubleExponentialMovingAverage var dema = DEMA(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
DetrendedPriceOscillator var dpo = DPO(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
ExponentialMovingAverage var ema = EMA(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
FractalAdaptiveMovingAverage var frama = FRAMA(Symbol symbol, int period, int longPeriod = 198, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
HullMovingAverage var hma = HMA(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
IchimokuKinkoHyo var ichimoku = ICHIMOKU(Symbol symbol, int tenkanPeriod, int kijunPeriod, int senkouAPeriod, int senkouBPeriod, int senkouADelayPeriod, int senkouBDelayPeriod, Resolution resolution = null)
KaufmanAdaptiveMovingAverage var kama = KAMA(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
KeltnerChannels var kch = KCH(Symbol symbol, int period, decimal k, MovingAverageType movingAverageType = null, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
LogReturn var logr = LOGR(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
LeastSquaresMovingAverage var lsma = LSMA(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
LinearWeightedMovingAverage var lwma = LWMA(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
MovingAverageConvergenceDivergence var macd = MACD(Symbol symbol, int fastPeriod, int slowPeriod, int signalPeriod, MovingAverageType type = null, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
MeanAbsoluteDeviation var mad = MAD(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
MassIndex var mass = MASS(Symbol symbol, int emaPeriod = 9, int sumPeriod = 25, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.TradeBar] selector = null)
Maximum var max = MAX(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
MoneyFlowIndex var mfi = MFI(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.TradeBar] selector = null)
MidPoint var midpoint = MIDPOINT(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
MidPrice var midprice = MIDPRICE(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Minimum var min = MIN(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
Momentum var mom = MOM(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
MomersionIndicator var momersion = MOMERSION(Symbol symbol, int minPeriod, int fullPeriod, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
MomentumPercent var momp = MOMP(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
NormalizedAverageTrueRange var natr = NATR(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
OnBalanceVolume var obv = OBV(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.TradeBar] selector = null)
PercentagePriceOscillator var ppo = PPO(Symbol symbol, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
ParabolicStopAndReverse var psar = PSAR(Symbol symbol, decimal afStart = 0.02, decimal afIncrement = 0.02, decimal afMax = 0.2, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
RegressionChannel var rc = RC(Symbol symbol, int period, decimal k, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
RateOfChange var roc = ROC(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
RateOfChangePercent var rocp = ROCP(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
RateOfChangeRatio var rocr = ROCR(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
RelativeStrengthIndex var rsi = RSI(Symbol symbol, int period, MovingAverageType movingAverageType = null, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
SimpleMovingAverage var sma = SMA(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
StandardDeviation var std = STD(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
Stochastic var sto = STO(Symbol symbol, int period, int kPeriod, int dPeriod, Resolution resolution = null)
Stochastic var sto = STO(Symbol symbol, int period, Resolution resolution = null)
Sum var sum = SUM(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
SwissArmyKnife var swiss = SWISS(Symbol symbol, int period, Double delta, SwissArmyKnifeTool tool, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
T3MovingAverage var t3 = T3(Symbol symbol, int period, decimal volumeFactor = 0.7, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
TripleExponentialMovingAverage var tema = TEMA(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
TrueRange var tr = TR(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
TriangularMovingAverage var trima = TRIMA(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
Trix var trix = TRIX(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
UltimateOscillator var ultosc = ULTOSC(Symbol symbol, int period1, int period2, int period3, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Variance var var = VAR(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
VolumeWeightedAveragePriceIndicator var vwap = VWAP(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.TradeBar] selector = null)
WilliamsPercentR var wilr = WILR(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Candlesticks Patterns Usage
TwoCrows var twocrows = CandlestickPatterns.TwoCrows(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
ThreeBlackCrows var threeblackcrows = CandlestickPatterns.ThreeBlackCrows(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
ThreeInside var threeinside = CandlestickPatterns.ThreeInside(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
ThreeLineStrike var threelinestrike = CandlestickPatterns.ThreeLineStrike(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
ThreeOutside var threeoutside = CandlestickPatterns.ThreeOutside(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
ThreeStarsInSouth var threestarsinsouth = CandlestickPatterns.ThreeStarsInSouth(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
ThreeWhiteSoldiers var threewhitesoldiers = CandlestickPatterns.ThreeWhiteSoldiers(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
AbandonedBaby var abandonedbaby = CandlestickPatterns.AbandonedBaby(Symbol symbol, decimal penetration = 0.3, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
AdvanceBlock var advanceblock = CandlestickPatterns.AdvanceBlock(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
BeltHold var belthold = CandlestickPatterns.BeltHold(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Breakaway var breakaway = CandlestickPatterns.Breakaway(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
ClosingMarubozu var closingmarubozu = CandlestickPatterns.ClosingMarubozu(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
ConcealedBabySwallow var concealedbabyswallow = CandlestickPatterns.ConcealedBabySwallow(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Counterattack var counterattack = CandlestickPatterns.Counterattack(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
DarkCloudCover var darkcloudcover = CandlestickPatterns.DarkCloudCover(Symbol symbol, decimal penetration = 0.5, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Doji var doji = CandlestickPatterns.Doji(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
DojiStar var dojistar = CandlestickPatterns.DojiStar(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
DragonflyDoji var dragonflydoji = CandlestickPatterns.DragonflyDoji(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Engulfing var engulfing = CandlestickPatterns.Engulfing(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
EveningDojiStar var eveningdojistar = CandlestickPatterns.EveningDojiStar(Symbol symbol, decimal penetration = 0.3, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
EveningStar var eveningstar = CandlestickPatterns.EveningStar(Symbol symbol, decimal penetration = 0.3, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
GapSideBySideWhite var gapsidebysidewhite = CandlestickPatterns.GapSideBySideWhite(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
GravestoneDoji var gravestonedoji = CandlestickPatterns.GravestoneDoji(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Hammer var hammer = CandlestickPatterns.Hammer(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
HangingMan var hangingman = CandlestickPatterns.HangingMan(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Harami var harami = CandlestickPatterns.Harami(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
HaramiCross var haramicross = CandlestickPatterns.HaramiCross(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
HighWaveCandle var highwavecandle = CandlestickPatterns.HighWaveCandle(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Hikkake var hikkake = CandlestickPatterns.Hikkake(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
HikkakeModified var hikkakemodified = CandlestickPatterns.HikkakeModified(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
HomingPigeon var homingpigeon = CandlestickPatterns.HomingPigeon(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
IdenticalThreeCrows var identicalthreecrows = CandlestickPatterns.IdenticalThreeCrows(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
InNeck var inneck = CandlestickPatterns.InNeck(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
InvertedHammer var invertedhammer = CandlestickPatterns.InvertedHammer(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Kicking var kicking = CandlestickPatterns.Kicking(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
KickingByLength var kickingbylength = CandlestickPatterns.KickingByLength(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
LadderBottom var ladderbottom = CandlestickPatterns.LadderBottom(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
LongLeggedDoji var longleggeddoji = CandlestickPatterns.LongLeggedDoji(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
LongLineCandle var longlinecandle = CandlestickPatterns.LongLineCandle(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Marubozu var marubozu = CandlestickPatterns.Marubozu(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
MatchingLow var matchinglow = CandlestickPatterns.MatchingLow(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
MatHold var mathold = CandlestickPatterns.MatHold(Symbol symbol, decimal penetration = 0.5, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
MorningDojiStar var morningdojistar = CandlestickPatterns.MorningDojiStar(Symbol symbol, decimal penetration = 0.3, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
MorningStar var morningstar = CandlestickPatterns.MorningStar(Symbol symbol, decimal penetration = 0.3, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
OnNeck var onneck = CandlestickPatterns.OnNeck(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Piercing var piercing = CandlestickPatterns.Piercing(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
RickshawMan var rickshawman = CandlestickPatterns.RickshawMan(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
RiseFallThreeMethods var risefallthreemethods = CandlestickPatterns.RiseFallThreeMethods(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
SeparatingLines var separatinglines = CandlestickPatterns.SeparatingLines(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
ShootingStar var shootingstar = CandlestickPatterns.ShootingStar(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
ShortLineCandle var shortlinecandle = CandlestickPatterns.ShortLineCandle(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
SpinningTop var spinningtop = CandlestickPatterns.SpinningTop(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
StalledPattern var stalledpattern = CandlestickPatterns.StalledPattern(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
StickSandwich var sticksandwich = CandlestickPatterns.StickSandwich(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Takuri var takuri = CandlestickPatterns.Takuri(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
TasukiGap var tasukigap = CandlestickPatterns.TasukiGap(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Thrusting var thrusting = CandlestickPatterns.Thrusting(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
Tristar var tristar = CandlestickPatterns.Tristar(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
UniqueThreeRiver var uniquethreeriver = CandlestickPatterns.UniqueThreeRiver(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
UpsideGapTwoCrows var upsidegaptwocrows = CandlestickPatterns.UpsideGapTwoCrows(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)
UpDownGapThreeMethods var updowngapthreemethods = CandlestickPatterns.UpDownGapThreeMethods(Symbol symbol, Resolution resolution = null, Func`2[Data.IBaseData,Data.Market.IBaseDataBar] selector = null)

// 1. Using basic indicator at the same resolution as source security:
// TIP -> You can use string "IBM" or the security.Symbol object
var ema = EMA("IBM", 14);

//2. Using indicator at different (higher) resolution to the source security:
var emaDaily = EMA("IBM", 14, Resolution.Daily);

//3. Indicator of a different property (default is close of bar/data):
// TIP -> You can use helper methods Field.Open, Field.High etc on the indicator selector:
var emaDailyHigh = EMA("IBM", 14, Resolution.Daily, point => ((TradeBar) point).High);

//NOTE. Some indicators require tradebars (ATR, AROON) so your selector must return a TradeBar object for those indicators.
# 1. Using basic indicator at the same resolution as source security:
ema = self.EMA("IBM", 14)

#2. Using indicator at different (higher) resolution to the source security:
emaDaily = self.EMA("IBM", 14, Resolution.Daily)

#3. Indicator of a different property (default is close of bar/data):
emaDailyHigh = self.EMA("IBM", 14, Resolution.Daily, Field.High)

Indicator Extensions

Indicators are composable - meaning they can be chained together to create unique combinations much like lego blocks. We support several indicator extensions as outlined below:

Extension Example Usage
.Plus()
var emaSum = ema5.Plus(ema20);
Add a fixed value or indicator value to another indicator
.Minus()
var emaDelta = ema20.Minus(ema5);
Find the difference between two indicators
.Times()
var rsiSafe = rsi.Times(0.95);
Multiply one indicator or constant value by another.
.Over()
var emaAverage = ema5.Plus(ema10).Over(2);
Divide indicator chain by constant or indicator.
.Of()
var sma = new SimpleMovingAverage("SPY", 14);
var rsiAverage= sma.Of( rsi );
Feed an indicator output into input of another.
.SMA(int period)
var rsiAvg = rsi.SMA(10);
Of extension helper for SMA method.
.EMA(int period)
var rsiAvg = rsi.EMA(10);
Of extension helper for EMA method.
.MAX(int period)
var rsiMax = rsi.MAX(10);
Of extension helper for MAX method, get max in i-samples.
.MIN(int period)
var rsiMin = rsi.MIN(10);
Of extension helper for MIN method, get min in i-samples.

Extension Example Usage
.Plus()
emaSum = IndicatorExtensions.Plus(ema20, ema5)
Add a fixed value or indicator value to another indicator
.Minus()
emaDelta = IndicatorExtensions.Minus(ema5, ema20)
Find the difference between two indicators
.Times()
rsiSafe = IndicatorExtensions.Times(rsi, 0.95)
Multiply one indicator or constant value by another.
.Over()
emaAverage = IndicatorExtensions.Over(IndicatorExtensions.Plus(ema10, ema5), 2)
Divide indicator chain by constant or indicator.
.Of()
sma = SimpleMovingAverage("SPY", 14)
rsiAverage= IndicatorExtensions.Of(rsi, sma)
Feed an indicator output into input of another.
.SMA(int period)
rsiAvg = IndicatorExtensions.SMA(rsi, 10)
Of extension helper for SMA method.
.EMA(int period)
rsiAvg = IndicatorExtensions.EMA(rsi, 10)
Of extension helper for EMA method.
.MAX(int period)
rsiMax = IndicatorExtensions.MAX(rsi, 10)
Of extension helper for MAX method, get max in i-samples.
.MIN(int period)
rsiMin = IndicatorExtensions.MIN(rsi, 10)
Of extension helper for MIN method, get min in i-samples.

public class IndicatorTests : QCAlgorithm
{
    //Save off reference to indicator objects
    RelativeStrengthIndex _rsi;
    SimpleMovingAverage _rsiSMA;

    public override void Initialize()
    {
       //In addition to other initialize logic:
       _rsi = RSI("SPY", 14); // Creating a RSI
       _rsiSMA = _rsi.SMA(3); // Creating the SMA on the RSI
    }
    
    public override void OnData(Slice data)
    {
       Plot("RSI", _rsi, _rsiSMA);
    }
}
class IndicatorTests(QCAlgorithm):
    def Initialize():
       # In addition to other initialize logic:
       self.rsi = self.RSI("SPY", 14)                     # Creating a RSI
       self.rsiSMA = IndicatorExtensions.SMA(self.rsi, 3) # Creating the SMA on the RSI
       self.PlotIndicator("RSI", self.rsi, self.rsiSMA)

Plotting Indicators

A helper method makes plotting indicators simple. Further information about the charting API can be found in the documentation below.

Plot<T>(string chart, params IndicatorBase<T>[] indicators) where T : BaseData
Note that not all indicators share the same base type(T) so may not work together.

//Plot array of indicator objects; extending "Indicator" type.
Plot("Indicators", sma, rsi); 

//Plot array of indicator objects; extending "TradeBarIndicator" type.
Plot("Indicators", atr, aroon); 

//For complex plotting it might be easiest to simply plot your indicators individually.
#Plot array of indicator objects; extending "Indicator" type.
self.Plot("Indicators", sma, rsi); 

#Plot array of indicator objects; extending "TradeBarIndicator" type.
self.Plot("Indicators", atr, aroon); 

#Currently, there is a limit of 4 indicators for each Plot call
#For complex plotting it might be easiest to simply plot your indicators individually.

Universes

Introduction to Universes

Often you may want to rotate securities in your algorithm based on filter criteria. You may only want equities above their 200 day EMA, or to only follow stocks on your custom list of symbols. This is possible using our universe selection API.

Universes are how LEAN organizes collections of data subscriptions under the hood. Each security and its data is controlled by a universe. When no universes are asking for data, the asset is removed from your algorithm. If your algorithm has open orders or holdings in a security we will not remove it from your subscriptions.

Every algorithm has a hidden "user-defined-universe". The assets in this universe are set by the AddEquity / AddForex methods. These assets are fixed and never removed from your algorithm.

Universes are refreshed every day by default, but can be refreshed as often as required. This is controlled in the algorithm.UniverseSettings variable which we'll describe in more detail below.

Basic Universe API

Adding Universes
Universes are added using the AddUniverse() method API. They are a type of data subscription which control what subscriptions are requested; and as such you can create custom universe data types. Depending on what type of universe you are adding there are many helper methods to make it easier. AddUniverse() methods take function filters as parameters, these filters must return an enumerable of Symbol objects.

Universe Settings
If you do not pass in a full universe object the UniverseSettings property is used to fill in the blanks. Changing the UniverseSettings algorithm property can be helpful to simplify adding universes. Universes have 4 key properties:

    //Popular universe settings:
    UniverseSettings.Resolution      // What resolution should added assets use
                    .Leverage        // What leverage should assets use in the universe?
                    .Fillforward     // Should asset data fill forward?
                    .MinimumTimeInUniverse // Minimum time assets should be in universe
                    .ExtendedMarketHours  // Should assets also feed extended market hours?

Once added universes are stored in the IDictionary<string, Universe> UniverseManager.

Universe Events
When universe contents are changed (securities are added or removed from the algorithm) we generate an OnSecuritiesChanged event. This allows your algorithm to know the changes in the universe state. The event passes in the SecurityChanges object containing references to the Added and Removed securities.

// Inside your initialize function:

// Subscriptions added via universe selection will have this resolution
UniverseSettings.Resolution = Resolution.Hour;

// Force securities to remain in the universe for a minimum of 30 days
UniverseSettings.MinimumTimeInUniverse = TimeSpan.FromDays(30);

// Helper: Add US-equity universe for the top 50 stocks by dollar volume
AddUniverse(Universe.DollarVolume.Top(50));

// Helper: Add US-equity universe for the bottom 50 stocks by dollar volume
AddUniverse(Universe.DollarVolume.Bottom(50));

// Helper: Add US-equity universe for the 90th dollar volume percentile
AddUniverse(Universe.DollarVolume.Percentile(90));

// Helper: Add US-equity universe for stocks between the 70th and 80th dollar volume percentile
AddUniverse(Universe.DollarVolume.Percentile(70, 80));
// Overriding the on changes event handler.
public override void OnSecuritiesChanged(SecurityChanges changes)
{
     _changes = changes;
}
# Overriding the on changes event handler.
def OnSecuritiesChanged(self, changes):
     self._changes = changes
// Use UniverseManager to find symbols from the Universe Selection
foreach (var universe in UniverseManager.Values)
{    
    // User defined universe has symbols from AddSecurity/AddEquity calls
    if (universe is UserDefinedUniverse)
    {
        continue;
    }
    var symbols = universe.Members.Keys;
}
# Use UniverseManager to find symbols from the Universe Selection
for universe in self.UniverseManager.Values:

    # User defined universe has symbols from AddSecurity/AddEquity calls
    if universe is UserDefinedUniverse:
        continue
    
    symbols = universe.Members.Keys

Coarse Universe Selection

Coarse Universe selection is the built in universe data provided by QuantConnect. Using financial data we generate a few key properties for each symbol and allow you to filter the universe of 16,400+ symbols to receive the symbols matching your filter criteria. It uses the CoarseFundamental type.

Coarse fundamental has the following properties you can use to perform rough filtering.

class CoarseFundamental {
    public long Volume;             // Traded shares
    public decimal DollarVolume;    // Traded shares x Price
    public decimal Price;           // Yesterday close price
    public Symbol Symbol;           // Asset symbol
    public bool HasFundamentalData; // Whether it has fundamental
}

Coarse filtering allows you to select an unlimited universe of symbols to analyse. You are only limited by practical memory and speed limits and may quickly run out of memory if you backtest too many symbols in parallel. These limits can be increased with a subscription.

// Take the top 50 by dollar volume using coarse 
AddUniverse(coarse => {
    return (from c in coarse
	    where c.Price > 10
	    orderby c.DollarVolume descending 
            select c.Symbol).Take(50);
});
# In Initialize:
self.AddUniverse(self.CoarseSelectionFunction)

def CoarseSelectionFunction(self, coarse):
    '''Take the top 50 by dollar volume using coarse'''
    # sort descending by daily dollar volume
    sortedByDollarVolume = sorted(coarse, \
        key=lambda x: x.DollarVolume, reverse=True) 

    # we need to return only the symbol objects
    return [ x.Symbol for x in sortedByDollarVolume[:50] ]
// We can use the following helper to reproduce the same result
AddUniverse(Universe.DollarVolume.Top(50));

Fundamentals Selection

QuantConnect provides MorningstarĀ® corporate fundamentals data for US Equities symbols. The available dataset includes about 5000 ticker with 900 fields starting from January 1998. It uses the FineFundamental type.

For the FineFundamental properties, please checkout our database.

Like coarse universes, fine universes allow you to select an unlimited universe of symbols to analyse. You are only limited by practical memory and speed limits and may quickly run out of memory if you backtest too many symbols in parallel. These limits can be increased with a subscription. Also you must use coarse fundamental universe to narrow down the universe as a "pre-filter".

// Take the top 50 by dollar volume using coarse
// Then the top 10 by PERatio using fine
AddUniverse(
    coarse => {
        return (from c in coarse
            where c.Price > 10
            orderby c.DollarVolume descending
            select c.Symbol).Take(50);
    },
    fine => {
        return (from f in fine
            orderby f.ValuationRatios.PERatio descending
            select f.Symbol).Take(10);
    });
# In Initialize:
self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)

def CoarseSelectionFunction(self, coarse):
    '''Take the top 50 by dollar volume using coarse'''
    # sort descending by daily dollar volume
    sortedByDollarVolume = sorted(coarse, \
        key=lambda x: x.DollarVolume, reverse=True) 

    # we need to return only the symbol objects
    return [ x.Symbol for x in sortedByDollarVolume[:50] ]

def FineSelectionFunction(self, fine):
    '''sort the data by P/E ratio and take the top 10 '''
    # sort descending by P/E ratio
    sortedByPeRatio = sorted(fine, \
        key=lambda x: x.ValuationRatios.PERatio, reverse=True)

    # take the top entries from our sorted collection
    return [ x.Symbol for x in sortedByPeRatio[:10] ]

Custom Universe Selection

Custom universes allow using an external data source as the security filtering source. Like normal custom data sources, custom universes are provided by extending BaseData. With this system you can define data formats to filter and select the data.

Each BaseData of the custom universe is 1 line of the source file. The Reader method will be called repeatedly until the date/time advances or the end of file is reached. This way you the engine can group universe data together, and pass it as a single collection into the filter function.

# In Initialize
self.AddUniverse(NyseTopGainers, "myCustomUniverse", Resolution.Daily, self.nyseTopGainers)

def nyseTopGainers(self, data):
    return [ x.Symbol for x in data if x["Rank"] > 5 ]
# Example custom universe data; it is virtually identical to other custom data types.
class NyseTopGainers(PythonData):

    def GetSource(self, config, date, isLiveMode):
        return SubscriptionDataSource(@"your-remote-universe-data", SubscriptionTransportMedium.RemoteFile)
    
    def Reader(self, config, line, date, isLiveMode):
        # Generate required data, then return an instance of your class.
        nyse = NyseTopGainers()
        nyse.Time = date
        # define end time as exactly 1 day after Time
        nyse.EndTime = nyse.Time + timedelta(1)
        nyse.Symbol = Symbol.Create(symbolString, SecurityType.Equity, Market.USA)
        nyse["Rank"] = rank
        return nyse

Option Universes

When you add an option to the algorithm it adds many many individual option contract securities. These are modelled as a "universe" of option contracts. We provide the SetFilter method to help narrow the option strike and expiry dates down to a range you are interested.

Future Universes

Historical Data

Introduction to Historical Data

Historical data can be provided in a batch request, or by "warming up" your algorithm. Batch requests feed requested data back as an enumerable you can use to manually prime your algorithm. The warm up feature feeds data to your event handlers from before your start date for a fixed period.

In live mode the history API can return data up to 5 seconds before the present moment.

Historical Data Requests

Batch history API is often easier to understand as you can manually feed data into your components which need it. If Resolution of the data request is not specified the history API uses the resolution of data you've specified with AddSecurity() or your Universe. If the Symbol is not specified then history for all symbols is returned for the period.

Batch data returned as IEnumerable<Slice> slices, IEnumerable<TradeBar> slices or IEnumerable<QuoteBar> slices has all the normal slice helpers - to assist using the data in your strategy, for example:

//From slice -> tradebars, or slice -> decimals.
IEnumerable<Slice> slices = History(TimeSpan.FromDays(7), Resolution.Minute);
IEnumerable<TradeBar> bars = slices.Get("SPY"); // Bars 
IEnumerable<decimal> decimals = slices.Get("SPY", Field.Close); // Close from slice
// Many math libraries need double arrays, decimals -> double[]
double[] doubleArray = decimals.ToDoubleArray();

In Python batch data can also be returned as pandas.DataFrame. It is a multi-index dataframe where the first index is the symbol.

slices = self.History(["SPY","EURUSD"], 14)
bars = slices.loc["EURUSD"]
doubleArray = bars["close"]   # use lowercase
// Request history for specific symbol, default to AddSecurity resolution.
IEnumerable<TradeBar> bars = History("SPY", TimeSpan.FromDays(7));
// Request history for specific symbol, at specific resolution.
IEnumerable<TradeBar> bars = History("SPY", TimeSpan.FromDays(7), Resolution.Minute);

//Get last 14 bars of SPY, default to AddSecurity resolution.
//Note you can't get "14 ticks" -- getting a specific number of bars only applies to TradeBar data.
IEnumerable<TradeBar> bars = History("SPY", 14);
//Get last 14 bars of SPY, at specific resolution.
IEnumerable<TradeBar> bars = History("SPY", 14, Resolution.Minute);

// Request history for specific symbol, default to AddSecurity resolution.
IEnumerable<QuoteBar> bars = History<QuoteBar>("EURUSD", TimeSpan.FromDays(7));
// Request history for specific symbol, at specific resolution.
IEnumerable<QuoteBar> bars = History<QuoteBar>("EURUSD", TimeSpan.FromDays(7), Resolution.Minute);

//Get last 14 bars of EURUSD, default to AddSecurity resolution.
//Note you can't get "14 ticks" -- getting a specific number of bars only applies to QuoteBar data.
IEnumerable<QuoteBar> bars = History<QuoteBar>("EURUSD", 14);
//Get last 14 bars of EURUSD, at specific resolution.
IEnumerable<QuoteBar> bars = History<QuoteBar>("EURUSD", 14, Resolution.Minute);

// Get history for all tickers we're subscribed to, at their native resolution
IEnumerable<Slice> slices = History(TimeSpan.FromDays(7));
// Get history for all tickers we're subscribed to, at a specific resolution
IEnumerable<Slice> slices = History(TimeSpan.FromDays(7), Resolution.Minute);

// For custom data, we need to define the type. E.g.: Quandl
AddData<Quandl>("SYMBOL")
IEnumerable<Quandl> bars = History<Quandl>("SYMBOL", TimeSpan.FromDays(7));
IEnumerable<Quandl> bars = History<Quandl>("SYMBOL", 14);
# Get history for all tickers we're subscribed to, at their native resolution
slices = self.History(timedelta(7))
# Get history for all tickers we're subscribed to, at a specific resolution
slices = self.History(timedelta(7), Resolution.Minute)

# Equity case:
# Request history for specific symbol, default to AddSecurity resolution.
bars = self.History("SPY", TimeSpan.FromDays(7))
# Request history for specific symbol, at specific resolution.
bars = self.History("SPY", TimeSpan.FromDays(7), Resolution.Minute)

# Get last 14 bars of SPY, default to AddSecurity resolution.
# Note you can't get "14 ticks" -- getting a specific number of bars only applies to TradeBar data.
bars = self.History("SPY", 14)
# Get last 14 bars of SPY, at specific resolution.
bars = self.History("SPY", 14, Resolution.Minute)

# Other assets (QuoteBar) case:
# We need to use map method to select only the specific symbol
bars = map(lambda x: x["EURUSD"], self.History(timedelta(7)))
bars = map(lambda x: x["EURUSD"], self.History(timedelta(7), Resolution.Minute))
bars = map(lambda x: x["EURUSD"], self.History(14))
bars = map(lambda x: x["EURUSD"], self.History(14, Resolution.Minute))

# Get history in pandas.DataFrame format, use list of string
df = self.History(["EURUSD"], timedelta(7))
df = self.History(["EURUSD"], timedelta(7), Resolution.Minute)
df = self.History(["EURUSD"], 14)
df = self.History(["EURUSD"], 14, Resolution.Minute)

Warming Your Algorithm

Warming up your algorithm causes data from before the algorithm starts to be fed into the conventional data event handlers. This system of warm up lends itself to stream style algorithms.

The data flowing to your algorithm will seamlessly pass from historical to live data. The flag bool IsWarmingUp can be used to monitor this transition.

During the warm up period you cannot submit orders. Warm up also does not support universe selection while the algorithm is warming up.

SetWarmUp(200); //Warm up 200 bars for all subscribed data.
SetWarmUp(TimeSpan.FromDays(7)); //Warm up 7 days of data.
self.SetWarmUp(200) //Warm up 200 bars for all subscribed data.
self.SetWarmUp(timedelta(7)) //Warm up 7 days of data.

Reality Modelling

Introduction to Models

Models can be used to improve the accuracy of your backtesting. We provide basic default models which assume you are trading on highly liquid assets, but if you are trading high volumes, or on low volume assets you should update these models to be more realistic.

All models are set on a per security basis. To set a model first fetch the security object and apply your model.

//Set IBM to have a constant $1 transaction fee. 
Securities["IBM"].FeeModel = new ConstantFeeTransactionModel(1); 

All models should be setup in your Initialize() method.

Brokerage Models

We provide a shortcut to set common models and properties relating to each of the brokerages we support. These brokerage models set fees, fill models, slippage models and trading markets for a brokerage. In addition they validate it is possible to submit trades to the brokerage (e.g. submitting equity trades to a forex only brokerage).

  • Transaction fees models
  • Supported markets
  • Slippage model
  • Validate orders and updates before they are submitted
  • Default account type (margin or cash account)
  • Support for extended market hours
  • How splits and dividends are applied to open order tickets
  • Default leverage for assets
  • Default settlement models
This gives you enormous control over your algorithm behavior and allow you to model virtually any brokerage in the world.

In addition to our default brokerage model ( DefaultBrokerageModel ), we provide brokerage models for Interactive Brokers ( InteractiveBrokersBrokerageModel ) , FXCM ( FxcmBrokerageModel ), OANDA ( OandaBrokerageModel ) and Tradier ( TradierBrokerageModel ).

Brokerage models override any other models you may set for a security.

// Set brokerage model using helper methods:
SetBrokerageModel(BrokerageName.FxcmBrokerage); // Defaults to margin account
SetBrokerageModel(BrokerageName.TradierBrokerage, AccountType.Cash); //Or override account type

// Supported brokerage names:
BrokerageName.FxcmBrokerage
             .OandaBrokerage
             .TradierBrokerage
             .InteractiveBrokersBrokerage
// You can also create your own brokerage model: IBrokerageModel
class MyBrokerage: DefaultBrokerage {
   // Custom implementation of brokerage here.
} 

SetBrokerageModel(new MyBrokerage());
# Set brokerage model using helper methods:
self.SetBrokerageModel(BrokerageName.FxcmBrokerage) # Defaults to margin account
self.SetBrokerageModel(BrokerageName.TradierBrokerage, \ 
                       AccountType.Cash) # Or override account type

# Supported brokerage names:
BrokerageName.FxcmBrokerage
             .OandaBrokerage
             .TradierBrokerage
             .InteractiveBrokersBrokerage

Transaction Fee Models

Transaction fee models set the fees for each order. We provide customized transaction models for all brokerages, but you can also set your own. Like all models they must be set on a security by security basis.

Transaction models implement the ISecurityTransactionModel interface. If you wish to implement your own transaction model you can start with the SecurityTransactionModel and override methods you wish to change.

// Set IBM to use a fixed $1.5 per trade fee model.
Securities["IBM"].FeeModel = new ConstantFeeTransactionModel(1.5);

// Set EURUSD to use FXCM's transaction fees:
Securities["EURUSD"].FeeModel = new FxcmTransactionModel();
# Set IBM to use a fixed $1.5 per trade fee model.
self.Securities["IBM"].FeeModel = ConstantFeeTransactionModel(1.5)

# Set EURUSD to use FXCM's transaction fees:
self.Securities["EURUSD"].FeeModel = new FxcmTransactionModel()
// Assigning securities custom fee models:
Securities["SPY"].SetFeeModel(new CustomFeeModel());

// Custom fee implementation
public class CustomFeeModel : IFeeModel {
    public decimal GetOrderFee(Security security, Order order) {
        return 1;
    }
}
# Assigning securities custom fee models:
self.Securities["SPY"].SetFeeModel(CustomFeeModel()) 

# Custom fee implementation
class CustomFeeModel:
    def GetOrderFee(self, security, order):
        return 1

Slippage Models

Slippage is the difference in price between your last reported quote and the real price the trade filled at. This difference can be positive or negative, as sometimes the price can slip in your favor. In volatile markets you are likely to experience more slippage.

Slippage models implement the ISlippageModel interface. We provide the SpreadSlippageModel for forex based securities, and the ConstantSlippageModel for Equities.

Advanced users may wish to implement their own volatility based slippage model - increasing the accuracy of your backtests in volatile markets.

// Assigning securities custom slippage models:
Securities["SPY"].SetSlippageModel(new CustomSlippageModel());

// Custom slippage implementation
public class CustomSlippageModel : ISlippageModel {
    public decimal GetSlippageApproximation(Security asset, Order order) {
        return 0.1m;
    }
}
# Assigning securities custom slippage models:
self.Securities["SPY"].SetSlippageModel(CustomSlippageModel())

# Custom slippage implementation
class CustomSlippageModel:
    def GetSlippageApproximation(self, asset, order):
        return 0.1

Fill Models

Fill models give you control over order fills. Each supported order type is passed through a dedicated method and returns an OrderEvent object. OrderEvents are used to carry information about order partial fills or errors.

The Fill Models implement the IFillModel interface. They have the following key methods:

public interface IFillModel {
    OrderEvent MarketFill(Security asset, MarketOrder order);
    OrderEvent StopMarketFill(Security asset, StopMarketOrder order);
    OrderEvent StopLimitFill(Security asset, StopLimitOrder order);
    OrderEvent LimitFill(Security asset, LimitOrder order);
    OrderEvent MarketOnOpenFill(Security asset, MarketOnOpenOrder order);
    OrderEvent MarketOnCloseFill(Security asset, MarketOnCloseOrder order);
}
We provide the ImmediateFillModel which assumes orders and immediately and completely filled.

// Set the fill models in initialize:
Securities["IBM"].SetFillModel(new PartialFillModel());

// Custom fill model implementation stub
public class PartialFillModel : ImmediateFillModel {
    public override OrderEvent MarketFill(Security asset, MarketOrder order) {
        //Override order event handler and return partial order fills, 
    }
}
# Set the fill models in initialize:
self.Securities["IBM"].SetFillModel(PartialFillModel())

# Custom fill model implementation stub
class PartialFillModel(ImmediateFillModel):
    def MarketFill(self, asset, order):
        # Override order event handler and return partial order fills
        pass

Margin Models

Margin models control how much buying power your algorithm has to make trades. Margin calculations can be very complex and depends on many factors including the brokerage or even time of day.

Margin model implement the ISecurityMarginModel interface and default to the SecurityMarginModel class. We also provide the PatternDayTradingMarginModel to model intraday pattern day trading for US equities.

// Example of setting a security to use PDT margin models:
// Generally you do not need to adjust margin models
Securities["AAPL"].MarginModel = new PatternDayTradingMarginModel();
# Example of setting a security to use PDT margin models:
# Generally you do not need to adjust margin models
self.Securities["AAPL"].MarginModel =  PatternDayTradingMarginModel()

Settlement Models

After a trade is made brokerages settle the cash depending on the markets and account type. This is managed by our Settlement Models. The most common settlement type is immediate - where the funds are available for trading immediately. This is handled by the ImmediateSettlementModel . US Equities trading with cash accounts is typically settled 3 days after the transaction occurred. This is managed by the DelayedSettlementModel .

Settlement models implement the ISettlementModel interface. You can create your own settlement model by implementing this method. Most users will not need to create their own settlement model and can use one of the ones provided above.

// Set a security to a delayed settlement model: settle 7 days later, at 8am.
Securities["IBM"].SettlementModel = new DelayedSettlementModel(7, new TimeSpan(8, 0, 0));
# Set a security to a delayed settlement model: settle 7 days later, at 8am.
self.Securities["IBM"].SettlementModel =  DelayedSettlementModel(7, timedelta(hours = 8))

Portfolio Models

Portfolio models control how order fills are applied to your portfolio. They take an OrderEvent , Security and SecurityPortfolioManager object and update the holdings to reflect the new final position. You should only need to update your portfolio model when you are create a new asset type.

Portfolio models implement the ISecurityPortfolioModel interface.

Volatility Model

The volatility model is a property of a security. Exactly how volatility is calculated varies a lot between strategies so we've provided an override point here. Volatility models get updated with data each time step and are expected to be updated immediately. This is primarily require for options backtesting.

Volatility models implement the IVolatilityModel interface. We default to the NullVolatilityModel which returns 0 volatility at all times. As a helper we also provide the RelativeStandardDeviationVolatilityModel which calculates the volatility based on standard deviation.

Charting

Introduction to Charting

We provide a powerful charting API which can be build many chart types. At its simplest it can be used with a single line of code:

Plot("Series Name", value);
Plot("Series Name", value)

With this code a line-graph is added underneath your Strategy Equity chart and your requested values are displayed over time. To create a new chart (new tab) you should also specify the chart name in your request:

Plot("My Indicators", "EMA", ema);

Behind the scenes these methods create a new Chart object and add it to your algorithm, and then add a new Series object to that chart. A chart is made from many series. You can also initialize your charts manually to get more control over their look and feel.

Manually Creating Charts

In your initialize method you can use the AddChart(Chart obj) method to insert a new chart. Each chart object has an internal collection of Series objects.

In creating Series objects you must specify the name of the series, the SeriesType and the index the series operates on. The series index refers to its position in the chart - for example; if all the series are index 0, they will lay on top of each other. If each series has its own index, it will be have several mini-charts stack next to each other.

The picture below shows an EMA cross chart with both EMA series set to the same index: Using different indexes the chart looks as follows:

// In your initialize method:

// Chart - Master Container for the Chart:
var stockPlot = new Chart("Trade Plot");
// On the Trade Plotter Chart we want 3 series: trades and price:
var buyOrders = new Series("Buy", SeriesType.Scatter, 0);
var sellOrders = new Series("Sell", SeriesType.Scatter, 0);
var assetPrice = new Series("Price", SeriesType.Line, 0);
stockPlot.AddSeries(buyOrders);
stockPlot.AddSeries(sellOrders);
stockPlot.AddSeries(assetPrice);
AddChart(stockPlot);

// Later in your OnData(Slice data):
Plot("Trade Plot", "Price", data.Bars["SPY"].Close);
# In your initialize method:
# Note - use single quotation marks: ' instead of double "
# Chart - Master Container for the Chart:
stockPlot = Chart('Trade Plot')
# On the Trade Plotter Chart we want 3 series: trades and price:
stockPlot.AddSeries(Series('Buy', SeriesType.Scatter, 0))
stockPlot.AddSeries(Series('Sell', SeriesType.Scatter, 0))
stockPlot.AddSeries(Series('Price', SeriesType.Line, 0))
self.AddChart(stockPlot)

// Later in your OnData(self, data):
self.Plot('Trade Plot', 'Price', self.lastPrice)

Supported Series Types

The charting API supports the follow series types. Nothing special is required to use these series, simply specify them for your series when creating your chart.

   SeriesType.Line
             .Scatter
             .Candle
             .Bar
             .Flag

Charting Limitations

Intensive charting generates hundreds of megabytes (200MB) of data which is far too much to stream online or display in a web browser. Because of this we limit the number of points a chart can have to 4000. If you see an error Exceeded maximum points per chart, data skipped you have hit this limit and should reduce your sampling frequency.

Logging and Debug

Debug Messages

Algorithms can send debug messages to the console using the Debug(string message) method. Debug messages are capped at 200 characters long. If multiple identical messages are sent within 1 second we rate limit the messages to avoid crashing your browser.

Debug(Time.ToString("o") + " Purchasing AAPL: " + data["AAPL"].Price);
self.Debug(str(self.Time) + " Purchasing AAPL: " + str(slice["SPY"].Price))
this.Debug("Hello from FSharp")

Errors Messages

Algorithms can send error messages to the console using the Error(string message) method. Error messages appear red in the console so you can see them easily. Like debug messages, error messages are rate limited to avoid flooding your browser.

Error("Volatility too high, terminating algorithm.");
Quit(); //Option: Instruct algorithm to stop.
self.Error("Volatility too high, terminating algorithm.")
self.Quit() # Optional: Instruct algorithm to stop.
this.Error("Volatility too high, triggering exit")
this.Quit()

Logging

Algorithms can save more detailed messaging to log files for later analysis using Log(string message). At the end of the backtest a link will be presented to view your results. In live trading a log viewer lets you view log results while the algorithm is running. Because of data vendor limitations price information cannot be recorded in logs.

Because of vendor limitations free users are capped to 10kb of logs per backtest, with a maximum of 3Mb per day. Users with a subscription can generate up to 100kb of logs per backtest.

Log("Additional detailed logging messages");
self.Log("Additional detailed logging messages")
this.Log("Additional detailed logging messages")

Asset Classes

Equities

Backtesting

There are roughly 16,400 symbols of survivorship bias free, split and dividend adjusted US equities data from Jan 1998 to today provided by QuantQuote. US Equities data by default arrives in adjusted format.

Our data is provided by QuantQuote and is trade data only only with tick, second, minute, hour and daily resolutions available.

The Tick data is raw and unfiltered - which includes suspicious, untradable and off market ticks. This can often result in unrealistic backtests. Before using tick data you should fully understand all the exchange codes and the "suspicious" flag which indicates a tick you should ignore. Unless you're an expert you should use the pre-filtered second and minute data.

In backtesting QuantConnect tick data is ordered but rounded to the previous second. There is no millisecond timestamp on the data.

Live Trading

QuantConnect live tick data comes directly from the exchanges. Like backtesting tick data, it is also raw and unfiltered.

When deploying an algorithm to Interactive Brokers you also have the option to use them for your datafeed. When using Interactive Brokers for your datafeed you must make sure you're subscribed to the asset classes you need.

Selecting Data

Subscribe to equity data:

// Complete Add Equity API - Including Default Parameters:
AddEquity(string ticker,
          Resolution resolution = Resolution.Minute,
          string market = Market.USA, 
          bool fillDataForward = true,
          decimal leverage = 0m,
          bool extendedMarketHours = false)

Using Data

Trades can be accessed in the Slice or TradeBars object in OnData event handler:

var bar = data["SPY"];

Other information about the equity can be found in the security object:

var equity = Securities["SPY"];

Live Trading

Only available with Interactive Brokers.

// In Initialize
AddEquity("SPY", Resolution.Minute);
# In Initialize
self.AddEquity("SPY", Resolution.Minute)
// In OnData(Slice data) or OnData(TradeBars data)
var bar = data["SPY"];

// Anywhere in the code
var equity = Securities["SPY"];
# In OnData(self, data)
bar = data["SPY"]

# Anywhere in the code
equity = self.Securities["SPY"]

Forex

Data Available

13 major currency pairs from Apr 2007 to now provided by FXCM and 71 major currency pairs from Apr 2004 to now provided by OANDA.

Backtesting mode

Quotes with tick, second, minute, hour and daily resolutions are available.

Live mode

Tick data is available from FXCM and OANDA.

Selecting Data

Subscribe to forex data:

// Complete Add Forex API - Including Default Parameters:
AddForex(string pair,
         Resolution resolution = Resolution.Minute,
         string market = null,
         bool fillDataForward = true,
         decimal leverage = 0m)

By default, FXCM is the data provider. If we want to use OANDA instead, we have to explicitly select it:

AddForex("EURUSD", Resolution.Minute, Market.Oanda);

Accessing data

Quotes can be accessed in the Slice or TradeBars object in OnData event handler:

var bar = data["EURUSD"];

Other information about the forex pair can be found in the security object:

var forex = Securities["EURUSD"];

Live Trading

Available with FXCM, OANDA and Interactive Brokers.

// In Initialize
AddForex("EURUSD", Resolution.Minute);   // or
AddForex("EURUSD", Resolution.Minute, Market.FXCM);

// For OANDA, we need to explictly define the market
AddForex("EURUSD", Resolution.Minute, Market.Oanda);
# In Initialize
self.AddForex("EURUSD", Resolution.Minute)   # or
self.AddForex("EURUSD", Resolution.Minute, Market.FXCM)

# For OANDA, we need to explictly define the market
self.AddForex("EURUSD", Resolution.Minute, Market.Oanda)
// In OnData(Slice data) or OnData(QuoteBars data)
var bar = data["EURUSD"];

// Anywhere in the code
var forex = Securities["EURUSD"];
# In OnData(self, data)
bar = data["EURUSD"]

# Anywhere in the code
equity = self.Securities["EURUSD"]

Futures

Data Available

Backtesting mode

4000 symbols of futures contracts from Jan 2009 to now provided by AlgoSeek.

Quotes and trades with tick, second, minute resolutions are available.

Live mode

Live tick data from Interactive Brokers are available. You MUST have a valid data subscription with IB).

Selecting Data

Subscribe to futures data:

// Complete Add Future API - Including Default Parameters:
AddFuture(string symbol,
          Resolution resolution = Resolution.Minute,
          string market = null,
          bool fillDataForward = true,
          decimal leverage = 0m)      

By default, the futures universe is filtered down to contracts that expire within 35 days. A difference set of contracts can be chosen with the SetFilter method:

var future = AddFuture(Futures.Indices.SP500EMini);
future.SetFilter(TimeSpan.FromDays(30), TimeSpan.FromDays(180));

Quotes and trades can be accessed in the Slice object in OnData event handler.

The FuturesChains member contains a FutureChain object for each subscribed future:

// In Initialize
FutureSymbol = future.Symbol;

// In OnData
FuturesChain chain;
slice.FuturesChains.TryGetValue(FutureSymbol, out chain);

An FuturesChain object has information about the undelying and futures contracts that were filtered by SetFilter:

var underlying = chain.Underlying;
var contracts = chain.Contracts; 

Finally, we can use Linq to select the contract(s) we want to trade.

Live Trading

Only available with Interactive Brokers.

// In Initialize
var future = AddFuture(Futures.Indices.SP500EMini, Resolution.Minute);
future.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(182));
// or Linq
future.SetFilter(universe => universe.Expiration(TimeSpan.Zero, TimeSpan.FromDays(182)));
# In Initialize
future = self.AddFuture(Futures.Indices.SP500EMini, Resolution.Minute)
future.SetFilter(timedelta(0), timedelta(182))
# or Lambda
future.SetFilter(universe => universe.Expiration(timedelta(0), timedelta(182)))
// In Initialize
FutureSymbol = future.Symbol;

// In OnData(Slice slice)
FuturesChain chain;
if (slice.FuturesChains.TryGetValue(FutureSymbol, out chain))
{
    var underlying = chain.Underlying;
    var contracts = chain.Contracts.Value; 
    foreach (var contract in contracts)
    {
        //
    }
}
# In Initialize
self.FutureSymbol = future.Symbol;

// In OnData(self, slice)
chain = slice.FuturesChains[self.FutureSymbol]
underlying = chain.Underlying
contracts = chain.Contracts.Value
for contract in contracts:
    pass

Options

Data Available

Backtesting mode

4000 symbols of US equity options from Jan 2010 to now provided by AlgoSeek.

Quotes and trades with minute resolution only.

Live mode

Live tick data from Interactive Brokers are available. You MUST have a valid data subscription with IB).

Selecting Data

Subscribe to options data:

// Complete Add Option API - Including Default Parameters:
AddOption(string underlying,
          Resolution resolution = Resolution.Minute,
          string market = null,
          bool fillDataForward = true,
          decimal leverage = 0m)

By default, the option universe is filtered down to contracts that expire within 35 days, one contract below and another above ATM, and exclude weeklys. A difference set of contracts can be chosen with the SetFilter method:

var option = AddOption("GOOG");
option.SetFilter(-2, 2, TimeSpan.FromDays(30), TimeSpan.FromDays(180));

SetFilter also accepts Linq expressions and enables the section of weeklys and define the desired option right:

var option = AddOption("GOOG");
option.SetFilter(universe =>
		 from symbol in universe                                .WeeklysOnly()                                .Expiration(TimeSpan.Zero, TimeSpan.FromDays(10))                                    where symbol.ID.OptionRight != OptionRight.Put &&                                    universe.Underlying.Price - symbol.ID.StrikePrice 
	< 60
                                    select symbol);

Accessing data

Quotes and trades can be accessed in the Slice object in OnData event handler.
The OptionChains member contains an OptionChain object for each subscribed option:
// In Initialize
OptionSymol = option.Symbol;

// In OnData
OptionChain chain;
slice.OptionChains.TryGetValue(OptionSymbol, out chain);

An OptionChain object has information about the undelying and options contracts that were filtered by SetFilter:
var underlying = chain.Underlying;
var contracts = chain.Contracts; 

Finally, we can use Linq to select the contract(s) we want to trade.

Live Trading

Only available with Interactive Brokers.

// In Initialize
var option = AddOption("GOOG");
option.SetFilter(-2, 2, TimeSpan.Zero, TimeSpan.FromDays(182));
// or Linq
option.SetFilter(universe => from symbol in universe
                                .WeeklysOnly()
                                .Expiration(TimeSpan.Zero, TimeSpan.FromDays(10))
                                    where symbol.ID.OptionRight != OptionRight.Put &&
                                    universe.Underlying.Price - symbol.ID.StrikePrice < 60
                                    select symbol);
# In Initialize
option = self.AddOption("GOOG");
option.SetFilter(-2, 2, timedelta(0), timedelta(182))
# or Lambda
option.SetFilter(lambda universe: universe.IncludeWeeklys().Strikes(-2, +2).Expiration(timedelta(0), timedelta(182)))
// In Initialize
OptionSymol = option.Symbol;

// In OnData
OptionChain chain;
if (slice.OptionChains.TryGetValue(OptionSymbol, out chain))
{
    // we find at the money (ATM) put contract with farthest expiration
    var atmContract = chain
        .OrderByDescending(x => x.Expiry)
        .ThenBy(x => Math.Abs(chain.Underlying.Price - x.Strike))
        .ThenByDescending(x => x.Right)
        .FirstOrDefault();
}
# In Initialize
self.OptionSymol = option.Symbol;

// In OnData
chain = slice.OptionChains[self.OptionSymbol].Value
# we sort the contracts to find at the money (ATM) contract with farthest expiration
contracts = sorted(sorted(chain, \
    key = lambda x: abs(chain.Underlying.Price - x.Strike)), \
    key = lambda x: x.Expiry, reverse=True)

CFD

Data Available

50 contracts from Apr 2004 to now provided by OANDA.

Backtesting mode

Quotes with tick, second, minute, hour and daily resolutions are available.

Live mode

Tick data is available from OANDA.

Selecting Data

Subscribe to forex data:

// Complete Add CFD API - Including Default Parameters:
AddCfd(string ticker,
       Resolution resolution = Resolution.Minute,
       string market = null,
       bool fillDataForward = true,
       decimal leverage = 0m)

Accessing data

Quotes can be accessed in the Slice or TradeBars object in OnData event handler:

var bar = data["XAUUSD"];

Other information about the contract can be found in the security object:

var cfd = Securities["XAUUSD"];

Live Trading

Only available with OANDA.

// In Initialize
AddCfd("XAUUSD", Resolution.Minute, Market.Oanda);
# In Initialize
self.AddCfd("XAUUSD", Resolution.Minute. Market.Oanda)
// In OnData(Slice data) or OnData(QuoteBars data)
var bar = data["XAUUSD"];

// Anywhere in the code
var cfd = Securities["XAUUSD"];
// In OnData(self, data)
bar = data["XAUUSD"];

// Anywhere in the code
cfd = self.Securities["XAUUSD"]

Crypto

Data Available

Backtesting mode GDAX trades and quotes are currently available from 20150615 to the present. We have added the trade and quote data for all historical pairs BTCUSD, BTCLTC, BTCETH, LTCUSD, LTCBTC, LTCETH, ETHUSD, ETHLTC and ETHBTC.

Live mode GDAX offers live quote and trade data for BTCUSD, BTCLTC, BTCETH, LTCUSD, LTCBTC, LTCETH, ETHUSD, ETHLTC and ETHBTC data.

Selecting Data

Subscribe to cryptocurrency data:
AddCrypto(string pair, Resolution resolution = Resolution.Minute)

The default market for crypto is assumed to be GDAX. To change the market, specify the market name in the
AddCrypto
command. For example, to subscribe to hourly resolution, BTCUSD, Bitfinex data in your algorithm, use the following method:
AddCrypto("BTCUSD", Resolution.Hour, Market.Bitfinex)

Accessing data

Quotes can be accessed in the Slice or TradeBars object in OnData event handler:

var bar = data["BTCUSD"];

var forex = Securities["BTCUSD"];

Live Trading

CryptoCurrency live trading is available through the GDAX brokerage. In order to live trade with GDAX, QuantConnect users must sign up for a GDAX account here: https://gdax.com. After obtaining an account, the next step is to create a GDAX api token. Sign into your GDAX account and click 'API' from the menu in the upper right. On the API page, users should select the 'View' and 'Trade' permissions. Click 'Create API key' on the bottom of the page. Be sure to record the api key, api passphrase and api secret.
Return to QuantConnect.com and go to the algorithm that you want to trade live. Select, 'Go Live' from the upper right hand corner. Follow the 'Live' wizard and select 'Gdax' as your brokerage. Be sure to copy your api key, api secret and api passcode correctly in the wizard.
Once potential stumbling block that users face deploying their algorithms live with GDAX is misunderstanding what type of account they have with GDAX. Typically, when users first open their account with GDAX, they are given a Cash account. In other words, margin trading is not available. However, margin accounts are the default account type specified in QCAlgorithm. Therefore, when users try to place trades using methods like
SetHoldings()
they will get errors that crash their algorithm. Be sure to set your account type using the
SetBrokerage()
method.
For example, to specify a Cash account, place the following above any data subscriptions.
SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash)

// In Initialize
AddCrypto("BTCUSD", Resolution.Minute);
# In Initialize
self.AddCrypto("BTCUSD", Resolution.Minute)
// In OnData(Slice data) or OnData(QuoteBars data)
var bar = data["BTCUSD"];

// Anywhere in the code
var crypto = Securities["BTCUSD"];
# In OnData(self, data)
bar = data["BTCUSD"]

# Anywhere in the code
crypto = self.Securities["BTCUSD"]

Live Trading

Live Settings

The LiveMode boolean property indicates whether your algorithm is running in live or backtest mode.

Supported Brokerages

Algorithms designed in QuantConnect can be seamlessly live traded on your brokerage accounts. We send the algorithm signals to your brokerage and track the algorithm state. Algorithms can be deployed immediately at any time of the day or night. A subscription is required for live trading however many brokerages sponsor live trading for their clients.

Brokerage Description
FXCM FOREX, CFD FXCM is a direct market access (DMA) broker offering low spreads and brokerage fees as low as £0.07 per side for popular currencies. FXCM trading is available to usersworld-wide and accounts can be opened with as 50 GBP. Live trading is free for FXCM clients.
Interactive Brokers Equity, FOREX, Futures, Options Interactive Brokers (IB) is a low cost provider of trade execution and clearing services for individuals, advisors, prop trading groups, brokers and hedge funds. IB's premier technology provides direct access to stocks, options, futures, forex, bonds and funds on over 100 markets worldwide from a single IB Universal account. Member NYSE, FINRA, SIPC. Subscription required for live trading.
OANDA FOREX, CFD Through our integration with OANDA Brokerage we can offer FOREX or CFD trading to users world-wide. Accounts can be opened with as little as $1 USD.Live trading is free for OANDA clients.
GDAX Crypto GDAX is the largest US based cryptocurrency exchange. Owned by Coinbase, users can easily purchase cryptocurrency through coinbase and transfer it to their GDAX account. Our GDAX integration allows users to trade BTC, LTC and ETH cryptocurrency pairs.
Paper TradingEquity, FOREX, CFD See how your algorithm would have performed with our paper trading feature. We use real live-data feeds but a virtual brokerage to execute your trades. Each project is allocated $100,000 virtual currency to track how you've performed.

Live Trading Highlights.

Notifications

In live trading mode we allow sending Email, SMS and Web-Hook notifications to notify you of significant events. You can send up to 20 notifications per hour. These are only sent during live trading.

Method Code Snippet
SMS Notify.Sms(string phoneNumber, string message);
Email Notify.Email(string address, string subject, string message, string data = "");
Web Hook Notify.Web(string address, object data = null);

//Send yourself an email on live trade executions
Notify.Email("myEmailAddress@gmail.com", "Live Trade Executed", "Bought 100 Shares of AAPL");
#Send yourself an email on live trade executions
self.Notify.Email("myEmailAddress@gmail.com", "Live Trade Executed", "Bought 100 Shares of AAPL")

Runtime Statistics

Runtime statistics are custom defined banner statistics displayed across the top of your live algorithm.

You can add your own runtime-statistics using the SetRuntimeStatistic(string name, string value); method. In the image above the user displays the current value of BTC: SetRuntimeStatistic("BTC", data["BTC"].Close);

// User displays the current value of BTC
SetRuntimeStatistic("BTC", data["BTC"].Close);
# User displays the current value of BTC
btc = self.Securities["BTC"].Symbol
self.SetRuntimeStatistic("BTC", data[btc].Close)

Research

Introduction to Jupyter

Introduction

QuantConnect provides an environment for you to perform exploratory research and brainstorm new ideas for algorithm. We simply call this the research environment. Here you can run Python CLI commands and explore the data directly from a Jupyter notebook installed in QuantConnect.

Inside a notebook you can perform virtually any command inside a safe disposable environment. We automatically save your notebook for you. Currently we just support Python 2.7 notebooks.

You can share a notebook by clicking the icon in the bottom right of the page. You can also share a notebook directly to the forums when you create a new discussion or comment.

The foundational class for access QuantConnect data in Jupyter is the QuantBook. This is a wrapper on the QCAlgorithm class and has many of the same methods. The research environment is currently in beta but we are slowly adding new methods to the QuantBook to expand your research potential. The basic template provides the foundation code required to import the QuantBook class. Specifically:

from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Jupyter")
AddReference("QuantConnect.Indicators")
from System import *
from QuantConnect import *
from QuantConnect.Data.Market import TradeBar, QuoteBar
from QuantConnect.Jupyter import *
from QuantConnect.Indicators import *
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import pandas as pd

# Create an instance
qb = QuantBook()

Historical Data

Using Indicators

Other

Frequently Asked Questions

For a full list of Frequently Asked Questions please see the FAQ page.

Common Errors

Runtime Error: 'AAPL' wasn't found in the TradeBars object

You're attempting to access data which is not in the TradeBars dictionary. There are two key reasons for this:
1. You have not requested data for this security in the Initialize method.
2. The data has gaps because it is not filling forward, or you're accessing the data after-hours when there won't be any price information.

Backtest Error: Error initializing algorithm: Date Invalid

You may have accidentally put invalid start and end dates into your algorithm. Or potentially you pressed backtest before the algorithm was fully saved. Please Ctrl+S to save the document, wait for its confirmation, and then click Backtest again.

 

Coding Environment

Local Development

We recommend using Visual Studio Community Edition as your programming environment. The community edition has the full power of Visual Studio and enables programming in C#, F#, VB and Python. If you're running on Mac or Linux you can also use MonoDevelop or Xamarin Studio.

If you prefer coding locally, you can run LEAN inside Visual Studio. The LEAN installation takes about 5 minutes and allows you to backtest locally and copy-paste your algorithms into QuantConnect.com. Check out the LEAN-Getting Started Tutorial for more information.

Learning Programming

We aim to make it as easy as possible to use QuantConnect but you still need to be able to program. We've provided some links below to get you started:

Language Type Name Producer
C# Video C# Fundamentals for Absolute Beginners Microsoft
C# Video C# Jump Start - Advanced Concepts Microsoft
C# Video Top 20 C# Questions Microsoft
F# Interactive Getting Started with F# Microsoft
F# Interactive Advanced Programming with F# Microsoft
F# Video F# Talks, Videos and Podcasts F# Foundation
Python Text/Video Introduction to Python Google
Python Interactive Code Academy - Python Code Academy
Java Video Java Tutorials Derek Banas
Java Video Java for Beginners New Boston
Visual Basic Video Visual Basic First Concepts New Boston
Visual Basic Video How To: Visual Basic Microsoft

Example Algorithms

Video Tutorials

Introduction to the IDE

The best source for example algorithms are shared community discussions. However we provide the example video tutorials below to help get you started with QuantConnect.

Name Description
Moving Average Cross The iconic moving average cross strategy from first principles. Watch on YouTube
Sell In May Fact or Fiction? Test the Sell in May Theory with hard data to see if it really is better to make your portfolio flat for May-October each year.Watch on YouTube
RSI with Martingale In this tutorial we use Martingale; a bet sizing technique for increasing odds of winning at the expense of increased risk. Watch on YouTube

There are hundreds of code snippets and example algorithms in the QuantConnect University accessible through the Terminal.

QuantConnect University

Language Name  
C# Basic Template Clone
C# Moving Average Cross Clone
C# Sell In May Clone
C# RSI with Martingale Position Sizing Clone
C# How Do I Use Live Custom Data? Clone
C# How Do I Make Any TimeSpan TradeBars? Clone
C# How Do I Create Custom Charts? Clone
F# How Do I Filter Bad Data-Ticks? (F#) Clone
C# How Do I Use Scheduled Events? Clone
Py Basic Template (Py) Clone
Py Clone of: Basic Template (Py) Clone
C# Strategy Example: Hello World - Basic Template Clone
C# Strategy Example: Complete Algorithm Framework Clone
C# How Do I Use FOREX-Currency Data? Clone
C# How Do I Use FOREX-Currency Data? Clone
F# How Do I Import Yahoo Data? (F#) Clone
C# How Do I Use Bitcoin Data? Clone
C# How Do I Import Custom Data? Clone
C# Strategy Example: Moving Average Cross Strategy Clone
C# How Do I Warm Up an Algorithm? Clone
C# How Do I Use Order Tickets? Clone
C# How Do I Use Stop-Limit Orders? Clone
C# How do I Retrieve Historical Data? Clone
C# How Do I Import Custom Data? Clone
C# How Do I Import Quandl Data? Clone
C# Strategy Example: RSI with Martingale Position Sizing Clone
C# How Do I Use Indicators? (ATR, BB, MACD, EMA, SMA, RSI) Clone
C# How do I Use the Stochastic Indicator? Clone
C# How do I Use Consolidators? Clone
C# How Do I Create a Rolling Window of Data? Clone
C# Strategy Example: Moving Average Cross Strategy Clone
C# How Do I Import My Training Data Sets? Clone
C# How Do I Set Zero Transaction Fees? Clone
C# How Do I Use EMA-SMA Indicator? Clone
C# Strategy Example: Sell In May Clone
C# How Do I Use Limit Orders? Clone
C# How Do I Warm Up an Algorithm? Clone
C# How Do I Use Live Custom Data? Clone
C# Strategy Example: Rotating Portfolio of Global ETFs Clone
C# How Do I Create a Parameterized Algorithm? Clone
C# How Do I Filter Bad Data-Ticks? Clone
F# Strategy Example: Hello World - Basic Template (F#) Clone
C# How Do I Create Custom Charts? Clone
C# Strategy Example: SPY Dollar Cost Average Clone
C# Strategy Example: Chilean Portfolio Rotation Clone
C# Weather Based Rebalancing Clone
C# How Do I Use Raw (Unadjusted) Data? Clone
C# How do I Retrieve Historical Data? Clone
C# How Do I Import Yahoo Data? Clone
C# How Do I Use End of Day Events? Clone
C# How Do I Ensure There Is Always Data? Clone
C# How Do I Use Tick Data? Clone
F# How Do I Create a Rolling Window of Data? (F#) Clone
C# How do I Use the Stochastic Indicator? Clone
C# Strategy Example: Sell In May Clone
F# How do I Use Renko Consolidators? (F#) Clone
C# How Do I Use Stop-Limit Orders? Clone
C# How Do I Use Bitcoin Data? Clone
C# How Do I Use Total Returns Price Normalization? Clone
C# How Do I Create Custom Transaction Models? Clone
C# How Do I Use Live Custom Data? Clone
C# What Features Are Available In Live Trading? Clone
C# How Do I Import Futures Data? Clone
C# How Do I Use Limit Orders? Clone
C# How Do I Import Multiple Quandl Data Sets? Clone
C# How Do I Handle Brokerage Error Messages? Clone