Overall Statistics |
Total Trades 213 Average Win 0.23% Average Loss -0.03% Compounding Annual Return 11.512% Drawdown 3.800% Expectancy 4.730 Net Profit 23.667% Sharpe Ratio 0.865 Loss Rate 27% Win Rate 73% Profit-Loss Ratio 6.86 Alpha 0.069 Beta 0.286 Annual Standard Deviation 0.092 Annual Variance 0.009 Information Ratio 0.356 Tracking Error 0.122 Treynor Ratio 0.279 Total Fees $207.00 |
using System; using System.Collections.Generic; using System.Linq; using QuantConnect.Algorithm; using QuantConnect.Data.Market; 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 Symbol _cashAsset; private Symbol _vixSymbol = QuantConnect.Symbol.Create("VIX", SecurityType.Base, Market.USA); private decimal _vix = 20m; private decimal _vixLowerBound = 10m; private decimal _vixUpperBound = 40m; private int _rebalancePeriod = 4; private decimal _cashTolerance = 0.01m; private decimal _minimumDeployedCapital = -0.25m; //Working Variables: private DateTime _lastRebalance = new DateTime(2004, 1, 2); private decimal _activePortfolioFraction = 0.3333m; private decimal _deployedCapital = 1m; private QCUQuantFramework _algorithm; private List<Symbol> _assets = new List<Symbol>(); private decimal _safeCapital = 0m; private decimal _adjustLeverageToOne = 0.5m; private Dictionary<Symbol, decimal> _historicalPrices = new Dictionary<Symbol, decimal>(); private Dictionary<Symbol, decimal> _activeFractionsBySymbol = new Dictionary<Symbol, decimal>(); private Dictionary<Symbol, decimal> _relativePrices = new Dictionary<Symbol, decimal>(); /******************************************************** * PUBLIC PROPERTIES *********************************************************/ /******************************************************** * PUBLIC CONSTRUCTOR *********************************************************/ /// <summary> /// Initialize the Alpha Manager: /// </summary> /// <param name="algorithm">Algorithm instance</param> public ModuleAlpha(QCUQuantFramework algorithm) { this._algorithm = algorithm; _cashAsset = _algorithm.CashAsset; _activePortfolioFraction = 1m; } public void UpdateAssets(List<Symbol> assets) { this._assets = assets; if (assets.Count > 0) { _activePortfolioFraction = 1m / ((decimal)assets.Count); //Remove the cash asset from the active portfolio. _assets.Remove(_cashAsset); } //Find default fraction of assets foreach (var symbol in _assets) { if (!_activeFractionsBySymbol.ContainsKey(symbol)) { _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<Symbol, PortfolioTarget> Scan(TradeBars prices, List<Symbol> universe) { var targets = new Dictionary<Symbol, PortfolioTarget>(); if (!prices.ContainsKey(_vixSymbol)) return targets; try { if (_algorithm.Time > _lastRebalance.Date.AddDays(_rebalancePeriod)) { _vix = prices[_vixSymbol].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 (Symbol symbol in prices.Keys) { 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 (Symbol symbol in _assets) { //HACK: this is quite dangerous to leave a asset when you don't have price // to make this work quickly I am going with this approach. if (!prices.ContainsKey(symbol)) continue; 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 + err.ToString()); } return targets; } } } // End of QCU QuantFramework } // End of QuantConnect Namespace
using System; using System.Collections.Generic; using QuantConnect.Algorithm; using QuantConnect.Data.UniverseSelection; using QuantConnect.Data.Market; namespace 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 decimal emaPeriod = 10m; /******************************************************** * PRIVATE VARIABLES *********************************************************/ //Working Variables: private QCUQuantFramework _algorithm; private Dictionary<Symbol, Asset> _assets; private int _daysAnalysed; private List<Symbol> _universe; /******************************************************** * PUBLIC PROPERTIES *********************************************************/ /// <summary> /// Public access to the asset properties: /// </summary> public Dictionary<Symbol, 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) { _daysAnalysed = 0; _algorithm = algorithm; _universe = new List<Symbol>(); _assets = new Dictionary<Symbol, Asset>(); // subscriptions added via universe selection will have this resolution _algorithm.UniverseSettings.Resolution = Resolution.Daily; // force securities to remain in the universe for a minimm of 7 hours _algorithm.UniverseSettings.MinimumTimeInUniverse = TimeSpan.FromHours(7); // add universe for the 90th dollar volume percentile //_algorithm.AddUniverse(_algorithm.Universe.DollarVolume.Percentile(90)); _algorithm.AddUniverse(_algorithm.Universe.DollarVolume.Top(10)); // special case cash asset _algorithm.AddEquity(_algorithm.CashAsset.ToString()); } public void OnSecuritiesChanged(SecurityChanges changes) { // liquidate securities that fell out of our universe foreach (var security in changes.RemovedSecurities) { if (_assets.ContainsKey(security.Symbol)) { _assets.Remove(security.Symbol); } } // invest in securities just added to our universe foreach (var security in changes.AddedSecurities) { if (!_assets.ContainsKey(security.Symbol)) { _assets.Add(security.Symbol, new Asset(security.Symbol, Industry.All, 0, 0)); } } } /// <summary> /// At the start of end of each trading day, select the stock universe for next day: /// </summary> /// <returns></returns> public List<Symbol> 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(Symbol symbol, TradeBar tradeBar) { if (_assets.ContainsKey(symbol)) { Asset asset = _assets[symbol]; if (asset.Price == 0) asset.Price = tradeBar.Close; if (asset.Volume == 0) asset.Volume = tradeBar.Volume; decimal multiplier = 1 / emaPeriod; //E10 Exponential moving average prices: asset.Price = multiplier * tradeBar.Close + (1 - multiplier) * asset.Price; asset.Volume = multiplier * tradeBar.Volume + (1 - multiplier) * asset.Volume; // Update the end of day count of days counted: _daysAnalysed++; } } } } // End of QCU QuantFramework } // End of QuantConnect Namespace
using System; using System.Collections.Generic; using MathNet.Numerics; using MathNet.Numerics.Statistics; using QuantConnect.Algorithm; using QuantConnect.Data.Market; using System.Linq; 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<Symbol, 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<Symbol, RunningStatistics> _deviationsStatistics; private Dictionary<Symbol, double> _deviations; private Dictionary<Symbol, 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<Symbol, decimal>(); this._technique = technique; //StdDev Working Parameters this._deviations = new Dictionary<Symbol, double>(); this._deviationsStatistics = new Dictionary<Symbol, RunningStatistics>(); this._priceQueue = new Dictionary<Symbol, 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<Symbol, 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 (Symbol security in _target.Keys) { string symbol = security.ToString(); 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: }
using System; using System.Collections.Generic; using QuantConnect.Algorithm; using QuantConnect.Data.Market; 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<Symbol, 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 Namespace
using System; using QuantConnect.Algorithm; namespace 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 Namespace
using System; using System.Collections.Generic; using QuantConnect.Algorithm; using QuantConnect.Data.Market; namespace 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<Symbol, PortfolioTarget> targets) { try { //Control the total exposure: // // NOP. // } catch (Exception err) { _algorithm.Error("RiskModule.Analyse(): " + err.Message); } } } } // End of QCU QuantFramework } // End of QuantConnect Namespace
using System.Globalization; using System.Collections.Concurrent; using QuantConnect.Algorithm; using QuantConnect.Data; using System; 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 = "fameoflight@gmail.com"; /// Primary SMS Notification public static string PhoneNumber = "415-355-4946"; } /// <summary> /// Portfolio Target from a signal decision: /// </summary> public class PortfolioTarget { /// Symbol to Trade: public Symbol Symbol; /// Direction Signal: -1 to +1 public decimal Signal; public PortfolioTarget(Symbol 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 Symbol 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(Symbol 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 = Symbol.Create("VIX", SecurityType.Base, Market.USA); } 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=2016-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.Value = fear.Close; //} //catch //{ } return fear; } } // End of VIX } // End of QuantConnect Namespace
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using QuantConnect.Algorithm; using QuantConnect.Data.Market; using QuantConnect.Data.UniverseSelection; using QuantConnect.Indicators.CandlestickPatterns; namespace 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 Symbol _cashAsset = QuantConnect.Symbol.Create("AGG", SecurityType.Equity, Market.USA); public Symbol CashAsset { get { return _cashAsset; } } /******************************************************** * 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<Symbol> _universe = new List<Symbol>(); /******************************************************** * 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() { SetWarmUp(TimeSpan.FromDays(45)); //Backtest Range: // Make sure you check the start dates of the assets you trade. SetStartDate(2015, 1, 1); SetEndDate(DateTime.Now.Date.AddDays(-1)); //Set Cash to $250k SetCash(FundParameters.AlgorithmMaximumAllocation); //Initalize Algorithm-A Modules: AssetManager = new ModuleAssets(this); // Analyse Generation of New Positions: AlphaManager = new ModuleAlpha(this); // 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); //Add custom data: AddData<VIX>("VIX", Resolution.Minute); } /// <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; if (!this.IsWarmingUp) { // 2. Update the Modules: var targets = AlphaManager.Scan(_prices, _universe); if (targets.Count > 0) { Debug(string.Format("Alpha Generated {0} universe {1} price {2}", targets.Count, _universe.Count, _prices.Count)); } // 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[data.Symbol.ToString()] = vixBar; } public override void OnEndOfDay(Symbol symbol) { if (_prices.ContainsKey(symbol)) { AssetManager.UpdateAssetProperties(symbol, _prices[symbol.ToString()]); } _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.ToString()] = bar; } Debug(string.Format("Prices {0}", _prices.Count)); //return (_prices.Count == Portfolio.Count); return _prices.Count > 0; } public override void OnSecuritiesChanged(SecurityChanges changes) { AssetManager.OnSecuritiesChanged(changes); _universe = AssetManager.UpdateUniverse(); AlphaManager.UpdateAssets(_universe); List<Symbol> obsolteSymbols = new List<Symbol>(); foreach (var symbol in _prices.Keys) { if (!_universe.Contains(symbol)) { obsolteSymbols.Add(symbol); } } foreach (var symbol in obsolteSymbols) { _prices.Remove(symbol); } } } // End of QCU QuantFramework } // End of QuantConnect Namespace