| Overall Statistics |
|
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 |
namespace QuantConnect
{
/// <summary>
/// QuantConnect QuantFramework Algorithm
///
/// Alpha Generation Module:
///
/// </summary>
public partial class QCUQuantFramework : QCAlgorithm
{
/// <summary>
/// Alpha Generator Module:
/// </summary>
public class ModuleAlpha
{
/********************************************************
* PRIVATE VARIABLES
*********************************************************/
//Strategy Settings:
private decimal _vix = 20m;
private decimal _vixLowerBound = 10m;
private decimal _vixUpperBound = 32m;
private int _rebalancePeriod = 4;
private decimal _cashTolerance = 0.01m;
private decimal _minimumDeployedCapital = -0.25m;
private string _cashAsset = "AGG";
//Working Variables:
private DateTime _lastRebalance = new DateTime(2004, 1, 2);
private decimal _activePortfolioFraction = 0.3333m;
private decimal _deployedCapital = 1m;
private QCUQuantFramework _algorithm;
private List<string> _assets = new List<string>();
private decimal _safeCapital = 0m;
private decimal _adjustLeverageToOne = 0.5m;
private Dictionary<string, decimal> _historicalPrices = new Dictionary<string, decimal>();
private Dictionary<string, decimal> _activeFractionsBySymbol = new Dictionary<string, decimal>();
private Dictionary<string, decimal> _relativePrices = new Dictionary<string, decimal>();
/********************************************************
* PUBLIC PROPERTIES
*********************************************************/
/********************************************************
* PUBLIC CONSTRUCTOR
*********************************************************/
/// <summary>
/// Initialize the Alpha Manager:
/// </summary>
/// <param name="algorithm">Algorithm instance</param>
public ModuleAlpha(QCUQuantFramework algorithm, List<string> assetList, string cashAsset = "AGG")
{
this._algorithm = algorithm;
this._assets = assetList;
_cashAsset = cashAsset;
//Remove the cash asset from the active portfolio.
_assets.Remove(_cashAsset);
//Find default fraction of assets
_activePortfolioFraction = 1m / ((decimal)assetList.Count);
foreach (var symbol in _assets)
{
_activeFractionsBySymbol.Add(symbol, _activePortfolioFraction);
_relativePrices.Add(symbol, 1);
}
}
/********************************************************
* PUBLIC METHODS
*********************************************************/
/// <summary>
/// Generate the Alpha Signal. Create a Symbol with a Strength of Conviction Indicator:
/// </summary>
/// <param name="prices">Latest prices data</param>
/// <returns>List of commands to trade</returns>
public Dictionary<string, PortfolioTarget> Scan(TradeBars prices, List<string> universe)
{
var targets = new Dictionary<string, PortfolioTarget>();
try
{
if (_algorithm.Time > _lastRebalance.Date.AddDays(_rebalancePeriod))
{
_vix = prices["VIX"].Close;
_lastRebalance = _algorithm.Time;
//Scale VIX fractionally 0-1 for 10-30.
_deployedCapital = 1 - ((_vix - _vixLowerBound) / (_vixUpperBound - _vixLowerBound));
//Set minimum deployed (set min to negative to allow shorts)
if (_deployedCapital < _minimumDeployedCapital) _deployedCapital = _minimumDeployedCapital;
//Fraction of capital preserved for bonds:
_safeCapital = 1 - _deployedCapital - _cashTolerance;
targets.Add(_cashAsset, new PortfolioTarget(_cashAsset, _safeCapital * _adjustLeverageToOne));
//Use rotational logic to reduce allocation to poorly performing stocks:
foreach(var symbol in _assets)
{
var price = prices[symbol].Close;
//Find the relative prices of each stock sinc rebalance. e.g. 0.97, 1.03, 0.80
if (!_historicalPrices.ContainsKey(symbol)) _historicalPrices.Add(symbol, price);
_relativePrices[symbol] = (price / _historicalPrices[symbol]);
}
// Baseline of all asset performance
var sum = _relativePrices.Values.Sum();
foreach(var symbol in _assets)
{
if (sum > 0) {
_activeFractionsBySymbol[symbol] = (_relativePrices[symbol] / sum);
} else {
_activeFractionsBySymbol[symbol] = 0;
}
if (symbol != _cashAsset) {
targets.Add(symbol, new PortfolioTarget(symbol, _deployedCapital * _activeFractionsBySymbol[symbol] * _adjustLeverageToOne));
}
//Save to calculate the rotational fraction.
_historicalPrices[symbol] = prices[symbol].Close;
}
}
}
catch (Exception err)
{
_algorithm.Error("AlphaModule.Scan: Error -" + err.Message);
}
return targets;
}
}
} // End of QCU QuantFramework
} // End of QuantConnect Namespacenamespace QuantConnect
{
/// <summary>
/// QuantConnect QuantFramework Algorithm
///
/// Asset/Universe Selection Module:
///
/// </summary>
public partial class QCUQuantFramework : QCAlgorithm
{
/// <summary>
/// Asset Screening Module:
/// </summary>
public partial class ModuleAssets
{
/********************************************************
* PRIVATE VARIABLES
*********************************************************/
//Strategy Variables:
public string _cashAsset = "AGG";
//Working Variables:
private QCUQuantFramework _algorithm;
private Dictionary<string, Asset> _assets;
private int _daysAnalysed;
private List<string> _universe;
/********************************************************
* PUBLIC PROPERTIES
*********************************************************/
/// <summary>
/// Public access to the asset properties:
/// </summary>
public Dictionary<string, Asset> Assets
{
get
{
return _assets;
}
}
/********************************************************
* PUBLIC CONSTRUCTOR
*********************************************************/
/// <summary>
/// Initialize the Asset Manager:
/// </summary>
/// <param name="algorithm">Instance of the algorithm required</param>
public ModuleAssets(QCUQuantFramework algorithm, string cashAsset = "AGG")
{
_daysAnalysed = 0;
_algorithm = algorithm;
_cashAsset = cashAsset;
_universe = new List<string>();
_assets = new Dictionary<string, Asset>()
{
{ "IBM", new Asset("IBM", Industry.Energy, 0, 0) },
{ "AAPL", new Asset("AAPL", Industry.All, 0, 0) },
{ "MSFT", new Asset("MSFT", Industry.All, 0, 0) },
{ "SPY", new Asset("SPY", Industry.All, 0, 0) }
};
}
/********************************************************
* PUBLIC METHODS
*********************************************************/
public void LoadAssets()
{
//Load the assets:
foreach (var symbol in _assets.Keys)
{
_algorithm.AddSecurity(SecurityType.Equity, symbol, Resolution.Minute, fillDataForward:true, leverage:2, extendedMarketHours:false);
}
}
/// <summary>
/// At the start of end of each trading day, select the stock universe for next day:
/// </summary>
/// <returns></returns>
public List<string> UpdateUniverse()
{
_universe.Clear();
try
{
//Perform any math / filtering / data search required to select the algorithm symbols for this next period.
foreach (var symbol in _assets.Keys)
{
_universe.Add(symbol);
}
}
catch (Exception err)
{
_algorithm.Error("AssetModule.ScreenUniverse(): Error - " + err.Message);
}
return _universe;
}
/// <summary>
/// Update the asset properties where possible
/// </summary>
/// <param name="symbol">Symbol of the asset we're setting.</param>
/// <param name="volume"></param>
public void UpdateAssetProperties(string symbol, decimal close, decimal volume)
{
Asset asset;
if (!_assets.TryGetValue(symbol, out asset)) return;
if (asset.Price == 0) asset.Price = close;
if (asset.Volume == 0) asset.Volume = close;
//E10 Exponential moving average prices:
asset.Price = 0.1m * close + 0.9m * asset.Price;
asset.Volume = 0.1m * volume + 0.9m * asset.Volume;
// Update the end of day count of days counted:
_daysAnalysed++;
}
}
} // End of QCU QuantFramework
} // End of QuantConnect Namespaceusing MathNet.Numerics;
using MathNet.Numerics.Statistics;
namespace QuantConnect
{
/// <summary>
/// QuantConnect QuantFramework Algorithm
///
/// Execution Management Module:
///
/// </summary>
public partial class QCUQuantFramework : QCAlgorithm
{
/// <summary>
/// Trading Execution Module: with two execution style out of the box:
/// -> ImmediateExecution - Send to market now.
/// -> StandardDeviation - Send to market later.
/// </summary>
public class ModuleExecute
{
/********************************************************
* PRIVATE VARIABLES
*********************************************************/
private QCUQuantFramework _algorithm;
private Dictionary<string, decimal> _target;
private ExecutionTechnique _technique;
private TradeBars _prices;
//Standard deviation strategy variable:
private int _devWindowPeriod = 60;
private double _buyPoint = -2;
private double _sellPoint = 2;
private double _extremePoint = 3.6;
//Standard deviation working varibles
private Dictionary<string, RunningStatistics> _deviationsStatistics;
private Dictionary<string, double> _deviations;
private Dictionary<string, FixedLengthQueue<double>> _priceQueue;
private int _devSampleCount = 0;
/********************************************************
* PUBLIC PROPERTIES
*********************************************************/
/********************************************************
* PUBLIC CONSTRUCTOR
*********************************************************/
/// <summary>
/// Initialize the Execution Manager:
/// </summary>
/// <param name="algorithm">Algorithm instance</param>
public ModuleExecute(QCUQuantFramework algorithm, ExecutionTechnique technique = ExecutionTechnique.Immediate)
{
//Common Execution Parameters
this._algorithm = algorithm;
this._target = new Dictionary<string, decimal>();
this._technique = technique;
//StdDev Working Parameters
this._deviations = new Dictionary<string, double>();
this._deviationsStatistics = new Dictionary<string, RunningStatistics>();
this._priceQueue = new Dictionary<string, FixedLengthQueue<double>>();
}
/********************************************************
* PUBLIC METHODS
*********************************************************/
/// <summary>
/// Set the target quantity for a symbol. Let the risk manager processing get us to this target:
/// </summary>
/// <param name="symbol">Desired asset</param>
/// <param name="quantity">Desired quantity</param>
public void SetPortfolioTarget(Dictionary<string, PortfolioTarget> targets)
{
try
{
foreach (var symbol in targets.Keys)
{
if (!_target.ContainsKey(symbol))
{
_target.Add(symbol, targets[symbol].Signal);
}
else
{
_target[symbol] = targets[symbol].Signal;
}
}
}
catch (Exception err)
{
_algorithm.Error("ModuleExecute.SetPortfolioTarget(): " + err.Message);
}
}
/// <summary>
/// Manage the execution of the algorithm delta of desired -> actual portfolio holdings:
/// </summary>
public void Execute(TradeBars prices)
{
try
{
_prices = prices;
switch (_technique)
{
//Send the order to market immediate:
case ExecutionTechnique.Immediate:
ExecuteImmediate();
break;
//Execute with at favourable standard deviations:
// - Use online stdDev techinque to track prices, when significantly better than mean purchase.
case ExecutionTechnique.StandardDeviation:
ExecuteStandardDeviation();
break;
}
}
catch (Exception err)
{
_algorithm.Error("ModuleExecute.Analyse(): " + err.Message);
}
}
/// <summary>
/// Execute the trade immediately
/// </summary>
private void ExecuteImmediate()
{
int orderId = 0;
decimal deltaQuantity = 0;
var delta = new Dictionary<string, decimal>();
var remove = new List<string>();
//Find the difference in number target to holdings:
foreach (string symbol in _target.Keys)
{
decimal total = _algorithm.Portfolio.TotalHoldingsValue + _algorithm.Portfolio.Cash * _algorithm.Securities[symbol].Leverage;
//2. Difference between our target % and our current holdings: (relative +- number).
decimal deltaValue = (total * _target[symbol]) - _algorithm.Portfolio[symbol].HoldingsValue;
//Potential divide by zero error for zero prices assets.
if (Math.Abs(_algorithm.Securities[symbol].Price) > 0)
{
//3. Now rebalance the symbol requested:
deltaQuantity = Math.Floor(deltaValue / _algorithm.Securities[symbol].Price);
}
//Determine if we need to place an order:
if (Math.Abs(deltaQuantity) > 0)
{
delta.Add(symbol, deltaQuantity);
}
else
{
//Remove the targets which have 0-more stocks to fill.
remove.Add(symbol);
}
}
//If there are any decrease holdings order process them first:
foreach (var symbol in delta.Keys)
{
deltaQuantity = delta[symbol];
if (!IncreaseHoldings(symbol, delta[symbol]))
{
orderId = _algorithm.MarketOrder(symbol, (int)deltaQuantity, false, "Decrease: " + symbol + " " + deltaQuantity);
if (orderId < 0) {
//Error placing order: adjust execution...
_algorithm.Error("DECREASE Order Error: " + orderId + " " + symbol + " Quantity:" + deltaQuantity);
}
}
}
//After processed the decrease of holdings, send the increase of holdings:
foreach (var symbol in delta.Keys)
{
deltaQuantity = delta[symbol];
if (IncreaseHoldings(symbol, delta[symbol]))
{
orderId = _algorithm.MarketOrder(symbol, (int)deltaQuantity, false, "Increase: " + symbol + " " + deltaQuantity);
if (orderId < 0) {
//Error placing order: adjust execution...
_algorithm.Error("INCREASE Order Error: " + orderId + " " + symbol + " Quantity:" + deltaQuantity);
}
}
}
//Strip the stocks already filled:
foreach (var symbol in remove)
{
_target.Remove(symbol);
}
}
/// <summary>
/// Using the supplied portfolio targets execute the trades when stddeviation is ideal.
/// </summary>
private void ExecuteStandardDeviation()
{
var badTick = false;
decimal deltaQuantity = 0;
var delta = new Dictionary<string, decimal>();
var remove = new List<string>();
var decreaseHoldings = false;
//Update standard deviation queue:
foreach (var kvp in _prices)
{
var symbol = kvp.Key;
var price = Convert.ToDouble(kvp.Value.Close);
if (!_priceQueue.ContainsKey(symbol)) {
_priceQueue.Add(symbol, new FixedLengthQueue<double>(_devWindowPeriod));
}
//Enqueue new data:
_priceQueue[symbol].Enqueue(price);
}
//Only do analysis once we have sufficient data:
if (_devSampleCount < _devWindowPeriod) {
_devSampleCount++; return;
}
//Calculate current deviations from mean:
foreach (var kvp in _prices)
{
var symbol = kvp.Key;
var price = Convert.ToDouble(kvp.Value.Close);
if (!_deviations.ContainsKey(symbol)) {
_deviations.Add(symbol, 0);
_deviationsStatistics.Add(symbol, new RunningStatistics());
}
_deviationsStatistics[symbol] = new RunningStatistics(_priceQueue[symbol].ToList());
//Update the standard deviation for this symbol: filter anything too extreme as fake tick.
var deviation = (price - _deviationsStatistics[symbol].Mean) / _deviationsStatistics[symbol].StandardDeviation;
if (Math.Abs(deviation) < _extremePoint) {
_deviations[symbol] = deviation;
} else {
badTick = true;
}
}
//Filter out bad ticks:
if (badTick) return;
//Find the difference in number target to holdings:
foreach (string symbol in _target.Keys)
{
var total = _algorithm.Portfolio.TotalHoldingsValue + _algorithm.Portfolio.Cash * _algorithm.Securities[symbol].Leverage;
var price = _algorithm.Securities[symbol].Price;
//2. Difference between our target % and our current holdings: (relative +- number).
decimal deltaValue = (total * _target[symbol]) - _algorithm.Portfolio[symbol].HoldingsValue;
//Potential divide by zero error for zero prices assets.
if (Math.Abs(_algorithm.Securities[symbol].Price) > 0)
{
//3. Now rebalance the symbol requested:
deltaQuantity = Math.Floor(deltaValue / _algorithm.Securities[symbol].Price);
}
//Determine if we need to place an order: if transaction volume more than $500. $1 fee on 1 share @ $25 trade is silly.
if (Math.Abs(deltaQuantity) > 0 && (price * Math.Abs(deltaQuantity) > 500))
{
delta.Add(symbol, deltaQuantity);
if (!IncreaseHoldings(symbol, deltaQuantity)) decreaseHoldings = true;
}
else
{
//Remove the targets which have 0-more stocks to fill.
remove.Add(symbol);
}
}
//If there are any decrease holdings order process them first:
foreach (var symbol in delta.Keys)
{
deltaQuantity = delta[symbol];
if (!IncreaseHoldings(symbol, deltaQuantity))
{
if ( (deltaQuantity > 0 && _deviations[symbol] < _buyPoint) || (deltaQuantity < 0 && _deviations[symbol] > _sellPoint) )
{
_algorithm.MarketOrder(symbol, (int)deltaQuantity, false, "Decrease: " + symbol + " " + deltaQuantity);
}
}
}
//If there are any decrease holdings commands outstanding, process them first; don't run increase holdings.
if (!decreaseHoldings)
{
//After processed the decrease of holdings, send the increase of holdings:
foreach (var symbol in delta.Keys)
{
deltaQuantity = delta[symbol];
if (IncreaseHoldings(symbol, deltaQuantity))
{
if ( (deltaQuantity > 0 && _deviations[symbol] < _buyPoint) || (deltaQuantity < 0 && _deviations[symbol] > _sellPoint) )
{
_algorithm.MarketOrder(symbol, (int)deltaQuantity, false, "Increase: " + symbol + " " + deltaQuantity);
}
}
}
}
}
/// <summary>
/// Return true if the order would increase the holdings (long/short) of the symbol.
/// </summary>
private bool IncreaseHoldings(string symbol, decimal deltaQuantity)
{
var increaseHoldings = false;
if (_algorithm.Portfolio.ContainsKey(symbol))
{
if ( (_algorithm.Portfolio[symbol].IsLong && deltaQuantity > 0) || (_algorithm.Portfolio[symbol].IsShort && deltaQuantity < 0) )
{
increaseHoldings = true;
}
if (_algorithm.Portfolio[symbol].Quantity == 0)
{
increaseHoldings = true;
}
} else {
_algorithm.Error("IncreaseHoldings(): Symbol not found in portfolio");
}
return increaseHoldings;
}
}
} // End of RV Fund:
}namespace QuantConnect
{
/// <summary>
/// QuantConnect QuantFramework Algorithm
///
/// Exit Management Module:
///
/// </summary>
public partial class QCUQuantFramework : QCAlgorithm
{
/// <summary>
/// Exit Management Module:
/// </summary>
public class ModuleExit
{
/********************************************************
* PRIVATE VARIABLES
*********************************************************/
private QCUQuantFramework _algorithm;
private ExitTechnique _technique;
/********************************************************
* PUBLIC PROPERTIES
*********************************************************/
/********************************************************
* PUBLIC CONSTRUCTOR
*********************************************************/
/// <summary>
/// Initialize the Exit Strategy Manager:
/// </summary>
/// <param name="algorithm">Algorithm instance</param>
public ModuleExit(QCUQuantFramework algorithm, ExitTechnique technique = ExitTechnique.Momentum)
{
this._algorithm = algorithm;
this._technique = technique;
}
/********************************************************
* PUBLIC METHODS
*********************************************************/
/// <summary>
/// Scan the portfolio holdings for exit opportunities:
/// </summary>
public void Scan(TradeBars prices, Dictionary<string, PortfolioTarget> targets)
{
try
{
//Based on set exit technique, scan and apply
switch(_technique)
{
//No exit system (portfolio algorithms)
case ExitTechnique.None:
break;
}
}
catch (Exception err)
{
_algorithm.Error("ExitManager.Scan(): " + err.Message);
}
}
}
} // End of QCU QuantFramework
} // End of QuantConnect Namespacenamespace QuantConnect
{
/// <summary>
/// QuantConnect QuantFramework Algorithm
///
/// Notification Management Module:
///
/// </summary>
public partial class QCUQuantFramework : QCAlgorithm
{
/// <summary>
/// Notification Module:
/// </summary>
public class ModuleNotify
{
/********************************************************
* PRIVATE VARIABLES
*********************************************************/
private QCUQuantFramework _algorithm;
private string _defaultToEmail = "";
private string _defaultPhoneNumber = "";
/********************************************************
* PUBLIC PROPERTIES
*********************************************************/
/********************************************************
* PUBLIC CONSTRUCTOR
*********************************************************/
/// <summary>
/// Initialize the Notification Manager:
/// </summary>
/// <param name="algorithm">Algorithm instance</param>
public ModuleNotify(QCUQuantFramework algorithm, string toEmail, string phoneNumber)
{
this._algorithm = algorithm;
this._defaultToEmail = toEmail;
this._defaultPhoneNumber = phoneNumber;
}
/********************************************************
* PUBLIC METHODS
*********************************************************/
/// <summary>
/// Send an email to the notification addresses
/// </summary>
/// <param name="message"></param>
public void Send(string message, string toEmail = "", string ccEmail = "")
{
try
{
//Send Email
if (toEmail == "") toEmail = _defaultToEmail;
}
catch (Exception err)
{
_algorithm.Error("ModuleNotify.Send(): " + err.Message);
}
}
/// <summary>
/// Send a SMS to this phone number
/// </summary>
/// <param name="phoneNumber"></param>
public void SMS(string message, string phoneNumber = "")
{
try
{
//Send SMS
if (phoneNumber == "") phoneNumber = _defaultPhoneNumber;
}
catch (Exception err)
{
_algorithm.Error("ModuleNotify.SMS(): " + err.Message);
}
}
}
} // End of QCU QuantFramework
} // End of QuantConnect Namespacenamespace QuantConnect
{
/// <summary>
/// QuantConnect QuantFramework Algorithm
///
/// Risk Management Module:
///
/// </summary>
public partial class QCUQuantFramework : QCAlgorithm
{
/// <summary>
/// Risk Management Module:
/// </summary>
public class ModuleRisk
{
/********************************************************
* PRIVATE VARIABLES
*********************************************************/
private QCUQuantFramework _algorithm;
/********************************************************
* PUBLIC PROPERTIES
*********************************************************/
/********************************************************
* PUBLIC CONSTRUCTOR
*********************************************************/
/// <summary>
/// Initialize the Risk Manager:
/// </summary>
/// <param name="algorithm">Algorithm instance</param>
public ModuleRisk(QCUQuantFramework algorithm)
{
this._algorithm = algorithm;
}
/********************************************************
* PUBLIC METHODS
*********************************************************/
/// <summary>
/// Analyse the list of directives, generate a quantity position size adjusting for market volatility
/// </summary>
/// <param name="directives">Directives to transfor.</param>
public void Analyse(TradeBars prices, Dictionary<string, PortfolioTarget> targets)
{
try
{
//Control the total exposure:
//
// NOP.
//
}
catch (Exception err)
{
_algorithm.Error("RiskModule.Analyse(): " + err.Message);
}
}
}
} // End of QCU QuantFramework
} // End of QuantConnect Namespaceusing System.Globalization;
using System.Collections.Concurrent;
namespace QuantConnect
{
/// <summary>
/// QuantConnect QuantFramework Algorithm
///
/// Initialization and Parameters:
///
/// </summary>
public partial class QCUQuantFramework : QCAlgorithm
{
/// <summary>
/// Algorithm Parameters:
/// </summary>
public static class FundParameters
{
/// Total Assets Under Management:
public static decimal TotalFundAssets = 250000;
/// Maximum Allocation Per Algorithm
public static decimal AlgorithmMaximumAllocation = 50000;
}
/// <summary>
/// Strategy Risk Parameters:
/// </summary>
public static class RiskParameters
{
/// Any position we take, set the maximum allowable risk.
public static decimal RiskPerTrade = 0.18m; // 15%
}
/// <summary>
/// Universe Selection Criteria
/// </summary>
public static class UniverseSelection
{
//10 Days Analysis Before Filtering Universe:
public static decimal MinimumAnalysisPeriod = 10;
//Other ideal parameters if we had data:
//public static decimal MinimumMarketCapitalization = 0; etc
}
/// <summary>
/// Contact Settings for the Algorithm Notifier
/// </summary>
public static class Contacts
{
/// Primary Contact Email Addresses
public static string ToEmail = "contact@quantconnect.com";
/// Primary SMS Notification
public static string PhoneNumber = "555-5555-55";
}
/// <summary>
/// Portfolio Target from a signal decision:
/// </summary>
public class PortfolioTarget
{
/// Symbol to Trade:
public string Symbol;
/// Direction Signal: -1 to +1
public decimal Signal;
public PortfolioTarget(string symbol, decimal signal = 1)
{
this.Symbol = symbol;
this.Signal = signal;
}
}
/// <summary>
/// Asset industry categories:
/// </summary>
public enum Industry
{
All,
Bonds,
BasicMaterials,
CapitalGoods,
Consumer,
Energy,
Financial,
Services,
Transportation,
Technology,
Healthcare,
RealEstate,
Utilities
}
/// <summary>
/// Property group of an asset - Symbol, Volume, Industry, PE.. etc. For expansion later:
/// </summary>
public class Asset
{
/// Symbol of this asset:
public string Symbol;
/// Asset Industry Catgegory:
public Industry Industry;
///Volume of the asset in millions:
public decimal Volume;
/// 20 Day Average Closing Price of the Asset:
public decimal Price;
/// Initialise the Asset Property Group:
public Asset(string symbol, Industry industry, decimal price, decimal volume)
{
this.Symbol = symbol;
this.Industry = industry;
this.Volume = 0;
this.Price = 0;
}
}
/// <summary>
/// Stoploss / exit technique to apply
/// </summary>
public enum ExitTechnique
{
/// No exit technique. Do not interfere.
None,
//Mebane Faber 10 Month Average Exit.
Momentum,
/// Exit immediately after achieving a prefixed gain
FixedGain,
/// Use a rolling stoploss immediately after taking position.
FixedRollingStoploss,
/// Rolling stoploss which increases closing speed exponentially.
ParabolicRollingStoploss,
/// Sell 20% of holdings with each 0.1% return achieved.
FractionalProfitTaking
}
/// <summary>
/// Determine execution technique for the algorithm:
/// </summary>
public enum ExecutionTechnique
{
/// Execute immediately, as fast as possible.
Immediate,
/// Volume weighted average price execution, wait for VWAP price or better before executing.
VWAP,
/// Wait for negative stddev before ordering (price favourable).
StandardDeviation
}
} // End of RV Fund:
/// <summary>
/// Queue which automatically dequeues old data.
/// </summary>
public class FixedLengthQueue<T> : ConcurrentQueue<T>
{
public int Size { get; private set; }
public FixedLengthQueue(int size)
{
Size = size;
}
public new void Enqueue(T obj)
{
base.Enqueue(obj);
lock (this)
{
while (base.Count > Size)
{
T outObj;
base.TryDequeue(out outObj);
}
}
}
}
/// <summary>
/// Custom imported data -- VIX indicator:
/// </summary>
public class VIX : BaseData
{
public decimal Open = 0;
public decimal High = 0;
public decimal Low = 0;
public decimal Close = 0;
public VIX()
{ this.Symbol = "VIX"; }
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLive)
{
return new SubscriptionDataSource("https://www.quandl.com/api/v1/datasets/YAHOO/INDEX_VIX.csv?trim_start=2000-01-01&trim_end=2014-10-27&sort_order=asc&exclude_headers=true", SubscriptionTransportMedium.RemoteFile);
}
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLive)
{
VIX fear = new VIX();
//try
//{
//Date Open High Low Close Volume Adjusted Close
//10/27/2014 17.24 17.87 16 16.04 0 16.04
string[] data = line.Split(',');
fear.Time = DateTime.ParseExact(data[0], "yyyy-MM-dd", CultureInfo.InvariantCulture);
fear.Open = Convert.ToDecimal(data[1]); fear.High = Convert.ToDecimal(data[2]);
fear.Low = Convert.ToDecimal(data[3]); fear.Close = Convert.ToDecimal(data[4]);
fear.Symbol = "VIX"; fear.Value = fear.Close;
//}
//catch
//{ }
return fear;
}
} // End of VIX
} // End of QuantConnect Namespacenamespace QuantConnect
{
/// <summary>
///
/// QuantConnect University - Quant-Framework Implementation
///
/// Basic algorithm framework implementation to design a robust, thorough and
/// thoughtful algorithm which can meet the challenges of live trading
///
/// </summary>
public partial class QCUQuantFramework : QCAlgorithm
{
/********************************************************
* PRIVATE VARIABLES
*********************************************************/
/// <summary>
/// Prices of all Assets Stores Rolling Forward:
/// </summary>
private TradeBars _prices = new TradeBars();
/// <summary>
/// Universe of symbols for today:
/// </summary>
private List<string> _universe = new List<string>();
/********************************************************
* PUBLIC PROPERTIES
*********************************************************/
/// <summary>
/// Module 1: Screen assets daily to match criteria; generate list of matching assets.
/// </summary>
public ModuleAssets AssetManager;
/// <summary>
/// Module 2: Generate alpha / signals based on desired behaviour. Signals from -1 to +1.
/// </summary>
public ModuleAlpha AlphaManager;
/// <summary>
/// Module 3: Manage Net Portfolio Cash Risk to ensure maximum 1% Exposed.
/// </summary>
public ModuleRisk RiskManager;
/// <summary>
/// Module 4: Factoring in the signal strength, apply stop loss techniques to control the position exit.
/// </summary>
public ModuleExit ExitManager;
/// <summary>
/// Module 5: Given a Desired Portfolio; Execute trades to reach this portfolio in the optimial manner possible
/// </summary>
public ModuleExecute ExecutionManager;
/// <summary>
/// Module 6: Send instant email/SMS notifications on issuing trades.
/// </summary>
public ModuleNotify NotificationManager;
/********************************************************
* PUBLIC METHODS
*********************************************************/
/// <summary>
/// Initialize algorithm and create instances of all the portfolio modules
/// </summary>
public override void Initialize()
{
//Cash Asset: (asset for when market is volatile and we go to cash, using AAPL is fun)
string cashAsset = "AGG";
//Backtest Range:
// Make sure you check the start dates of the assets you trade.
SetStartDate(2004, 12, 1);
SetEndDate(DateTime.Now.Date.AddDays(-1));
//Set Cash to $250k
SetCash(FundParameters.AlgorithmMaximumAllocation);
//Initalize Algorithm-A Modules:
AssetManager = new ModuleAssets(this, cashAsset);
// Analyse Generation of New Positions:
AlphaManager = new ModuleAlpha(this, AssetManager.Assets.Keys.ToList(), cashAsset);
// Monitor the Risk Profile
RiskManager = new ModuleRisk(this);
// Analysis of Exit Positions:
ExitManager = new ModuleExit(this);
// Time and Split the Orders:
ExecutionManager = new ModuleExecute(this, ExecutionTechnique.StandardDeviation);
// Send Notifications of Positions:
NotificationManager = new ModuleNotify(this, Contacts.ToEmail, Contacts.PhoneNumber);
//Load the assets universe we're trading
AssetManager.LoadAssets();
//Add custom data:
AddData<VIX>("VIX", Resolution.Minute);
//Get the universe for the first analysis:
_universe = AssetManager.UpdateUniverse();
}
/// <summary>
/// New Data Event: Process new data signal into the modules:
/// </summary>
/// <param name="data"></param>
public void OnData(TradeBars bars)
{
//1. Initialize: only continue when prices completely full:
if (!UpdatePrices(bars)) return;
// 2. Update the Modules:
var targets = AlphaManager.Scan(_prices, _universe);
// 3. Quantify directives into risk-adjusted positions:
RiskManager.Analyse(_prices, targets);
// 4. Before Sending to Execution Manager, Scan for Exit Signal:
ExitManager.Scan(_prices, targets);
// 5. Issue Quantified Directives to Execution Manager:
ExecutionManager.SetPortfolioTarget(targets);
// 6. Issue Trade Orders to Actually Create Portfolio
ExecutionManager.Execute(_prices);
}
/// <summary>
/// New Data Event: VIX daily pricing:
/// </summary>
public void OnData(VIX data)
{
TradeBar vixBar = new TradeBar();
vixBar.Open = data.Open;
vixBar.High = data.High;
vixBar.Low = data.Low;
vixBar.Close = data.Close;
vixBar.Value = data.Value;
vixBar.Time = data.Time;
_prices["VIX"] = vixBar;
}
/// <summary>
/// End of Day Scan to Update Algorithm Parameters
/// </summary>
/// <param name="symbol"></param>
public override void OnEndOfDay(string symbol)
{
//Ignore non-tradeable symbols
if (Securities[symbol].Type == SecurityType.Base) return;
//Update the asset moving average price and volumes:
AssetManager.UpdateAssetProperties(symbol, _prices[symbol].Close, Convert.ToDecimal(_prices[symbol].Volume));
//Update the universe for tomorrow.
_universe = AssetManager.UpdateUniverse();
}
/// <summary>
/// Update the price store:
/// </summary>
private bool UpdatePrices(TradeBars bars)
{
foreach (var bar in bars.Values)
{
// 1.1 Record the prices for future reference:
_prices[bar.Symbol] = bar;
}
return (_prices.Count == Portfolio.Count);
}
} // End of QCU QuantFramework
} // End of QuantConnect Namespace