chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using Accord.MachineLearning.VectorMachines.Learning;
|
||||
using QuantConnect.Indicators;
|
||||
using System;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Machine Learning example using Accord VectorMachines Learning
|
||||
/// In this example, the algorithm forecasts the direction based on the last 5 days of rate of return
|
||||
/// </summary>
|
||||
public class AccordVectorMachinesAlgorithm : QCAlgorithm
|
||||
{
|
||||
// Define the size of the data used to train the model
|
||||
// It will use _lookback sets with _inputSize members
|
||||
// Those members are rate of return
|
||||
private const int _lookback = 30;
|
||||
private const int _inputSize = 5;
|
||||
private RollingWindow<double> _window = new RollingWindow<double>(_inputSize * _lookback + 2);
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07);
|
||||
SetEndDate(2013, 10, 11);
|
||||
SetCash(100000);
|
||||
|
||||
var symbol = AddEquity("SPY").Symbol;
|
||||
|
||||
ROC(symbol, 1, Resolution.Daily).Updated += (s, e) => _window.Add((double)e.Value);
|
||||
|
||||
Schedule.On(DateRules.Every(DayOfWeek.Monday),
|
||||
TimeRules.AfterMarketOpen(symbol, 10),
|
||||
TrainAndTrade);
|
||||
|
||||
SetWarmUp(_window.Size, Resolution.Daily);
|
||||
}
|
||||
|
||||
private void TrainAndTrade()
|
||||
{
|
||||
if (!_window.IsReady) return;
|
||||
|
||||
// Convert the rolling window of rate of change into the Learn method
|
||||
var returns = new double[_inputSize];
|
||||
var targets = new double[_lookback];
|
||||
var inputs = new double[_lookback][];
|
||||
|
||||
// Use the sign of the returns to predict the direction
|
||||
for (var i = 0; i < _lookback; i++)
|
||||
{
|
||||
for (var j = 0; j < _inputSize; j++)
|
||||
{
|
||||
returns[j] = Math.Sign(_window[i + j + 1]);
|
||||
}
|
||||
|
||||
targets[i] = Math.Sign(_window[i]);
|
||||
inputs[i] = returns;
|
||||
}
|
||||
|
||||
// Train SupportVectorMachine using SetHoldings("SPY", percentage);
|
||||
var teacher = new LinearCoordinateDescent();
|
||||
teacher.Learn(inputs, targets);
|
||||
|
||||
var svm = teacher.Model;
|
||||
|
||||
// Compute the value for the last rate of change
|
||||
var last = (double) Math.Sign(_window[0]);
|
||||
var value = svm.Compute(new[] {last});
|
||||
if (value.IsNaNOrZero()) return;
|
||||
|
||||
SetHoldings("SPY", Math.Sign(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Test algorithm using <see cref="AccumulativeInsightPortfolioConstructionModel"/> and <see cref="ConstantAlphaModel"/>
|
||||
/// generating a constant <see cref="Insight"/> with a 0.25 confidence
|
||||
/// </summary>
|
||||
public class AccumulativeInsightPortfolioRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
// Set requested data resolution
|
||||
UniverseSettings.Resolution = Resolution.Minute;
|
||||
|
||||
SetStartDate(2013, 10, 07); //Set Start Date
|
||||
SetEndDate(2013, 10, 11); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
|
||||
// set algorithm framework models
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel(QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA)));
|
||||
SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, 0.25));
|
||||
SetPortfolioConstruction(new AccumulativeInsightPortfolioConstructionModel());
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (// holdings value should be 0.03 - to avoid price fluctuation issue we compare with 0.06 and 0.01
|
||||
Portfolio.TotalHoldingsValue > Portfolio.TotalPortfolioValue * 0.06m
|
||||
||
|
||||
Portfolio.TotalHoldingsValue < Portfolio.TotalPortfolioValue * 0.01m)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected Total Holdings Value: {Portfolio.TotalHoldingsValue}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 3943;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "199"},
|
||||
{"Average Win", "0.00%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "-12.611%"},
|
||||
{"Drawdown", "0.200%"},
|
||||
{"Expectancy", "-0.585"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "99827.80"},
|
||||
{"Net Profit", "-0.172%"},
|
||||
{"Sharpe Ratio", "-11.13"},
|
||||
{"Sortino Ratio", "-16.704"},
|
||||
{"Probabilistic Sharpe Ratio", "10.330%"},
|
||||
{"Loss Rate", "78%"},
|
||||
{"Win Rate", "22%"},
|
||||
{"Profit-Loss Ratio", "0.87"},
|
||||
{"Alpha", "-0.156"},
|
||||
{"Beta", "0.035"},
|
||||
{"Annual Standard Deviation", "0.008"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-9.603"},
|
||||
{"Tracking Error", "0.215"},
|
||||
{"Treynor Ratio", "-2.478"},
|
||||
{"Total Fees", "$199.00"},
|
||||
{"Estimated Strategy Capacity", "$26000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "119.89%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d06c26f557b83d8d42ac808fe2815a1e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Test algorithm using <see cref="QCAlgorithm.AddAlphaModel(IAlphaModel)"/>
|
||||
/// </summary>
|
||||
public class AddAlphaModelAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _spy;
|
||||
private Symbol _fb;
|
||||
private Symbol _ibm;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07); //Set Start Date
|
||||
SetEndDate(2013, 10, 11); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
|
||||
UniverseSettings.Resolution = Resolution.Daily;
|
||||
|
||||
_spy = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
|
||||
_fb = QuantConnect.Symbol.Create("FB", SecurityType.Equity, Market.USA);
|
||||
_ibm = QuantConnect.Symbol.Create("IBM", SecurityType.Equity, Market.USA);
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel(_spy, _fb, _ibm));
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
AddAlpha(new OneTimeAlphaModel(_spy));
|
||||
AddAlpha(new OneTimeAlphaModel(_fb));
|
||||
AddAlpha(new OneTimeAlphaModel(_ibm));
|
||||
|
||||
InsightsGenerated += OnInsightsGeneratedVerifier;
|
||||
}
|
||||
|
||||
private void OnInsightsGeneratedVerifier(IAlgorithm algorithm,
|
||||
GeneratedInsightsCollection insightsCollection)
|
||||
{
|
||||
if (insightsCollection.Insights.Count(insight => insight.Symbol == _fb) != 1
|
||||
|| insightsCollection.Insights.Count(insight => insight.Symbol == _spy) != 1
|
||||
|| insightsCollection.Insights.Count(insight => insight.Symbol == _ibm) != 1)
|
||||
{
|
||||
throw new RegressionTestException("Unexpected insights were emitted");
|
||||
}
|
||||
}
|
||||
|
||||
private class OneTimeAlphaModel : AlphaModel
|
||||
{
|
||||
private readonly Symbol _symbol;
|
||||
private bool _triggered;
|
||||
|
||||
public OneTimeAlphaModel(Symbol symbol)
|
||||
{
|
||||
_symbol = symbol;
|
||||
}
|
||||
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
if (!_triggered)
|
||||
{
|
||||
_triggered = true;
|
||||
yield return Insight.Price(
|
||||
_symbol,
|
||||
Resolution.Daily,
|
||||
1,
|
||||
InsightDirection.Down
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 58;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "9"},
|
||||
{"Average Win", "0.86%"},
|
||||
{"Average Loss", "-0.27%"},
|
||||
{"Compounding Annual Return", "206.404%"},
|
||||
{"Drawdown", "1.700%"},
|
||||
{"Expectancy", "1.781"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "101441.92"},
|
||||
{"Net Profit", "1.442%"},
|
||||
{"Sharpe Ratio", "4.836"},
|
||||
{"Sortino Ratio", "10.481"},
|
||||
{"Probabilistic Sharpe Ratio", "59.374%"},
|
||||
{"Loss Rate", "33%"},
|
||||
{"Win Rate", "67%"},
|
||||
{"Profit-Loss Ratio", "3.17"},
|
||||
{"Alpha", "4.164"},
|
||||
{"Beta", "-1.322"},
|
||||
{"Annual Standard Deviation", "0.321"},
|
||||
{"Annual Variance", "0.103"},
|
||||
{"Information Ratio", "-0.795"},
|
||||
{"Tracking Error", "0.532"},
|
||||
{"Treynor Ratio", "-1.174"},
|
||||
{"Total Fees", "$14.78"},
|
||||
{"Estimated Strategy Capacity", "$120000000.00"},
|
||||
{"Lowest Capacity Asset", "IBM R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "41.18%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "713c956deb193bed2290e9f379c0f9f9"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm reproducing GH issue #5748 where in some cases an option underlying symbol was not being
|
||||
/// removed from all universes it was hold
|
||||
/// </summary>
|
||||
public class AddAndRemoveOptionContractRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _contract;
|
||||
private bool _hasRemoved;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2014, 06, 06);
|
||||
SetEndDate(2014, 06, 09);
|
||||
|
||||
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
|
||||
UniverseSettings.MinimumTimeInUniverse = TimeSpan.Zero;
|
||||
|
||||
var aapl = QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA);
|
||||
|
||||
_contract = OptionChain(aapl)
|
||||
.OrderBy(symbol => symbol.ID.OptionRight)
|
||||
.ThenBy(symbol => symbol.ID.StrikePrice)
|
||||
.ThenBy(symbol => symbol.ID.Date)
|
||||
.ThenBy(symbol => symbol.ID)
|
||||
.FirstOrDefault(optionContract => optionContract.ID.OptionRight == OptionRight.Call);
|
||||
AddOptionContract(_contract);
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (slice.HasData)
|
||||
{
|
||||
if (!_hasRemoved)
|
||||
{
|
||||
RemoveOptionContract(_contract);
|
||||
RemoveSecurity(_contract.Underlying);
|
||||
_hasRemoved = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RegressionTestException("Expect a single call to OnData where we removed the option and underlying");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_hasRemoved)
|
||||
{
|
||||
throw new RegressionTestException("Expect a single call to OnData where we removed the option and underlying");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 26;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 1;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "-9.486"},
|
||||
{"Tracking Error", "0.008"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Portfolio Turnover", "0%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm reproducing GH issue #5971 where we add and remove an option in the same loop
|
||||
/// </summary>
|
||||
public class AddAndRemoveSecuritySameLoopRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _contract;
|
||||
private bool _hasRemoved;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2014, 06, 06);
|
||||
SetEndDate(2014, 06, 09);
|
||||
|
||||
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
|
||||
UniverseSettings.MinimumTimeInUniverse = TimeSpan.Zero;
|
||||
|
||||
var aapl = AddEquity("AAPL").Symbol;
|
||||
|
||||
_contract = OptionChain(aapl)
|
||||
.OrderBy(x => x.ID.Symbol)
|
||||
.FirstOrDefault(optionContract => optionContract.ID.OptionRight == OptionRight.Call
|
||||
&& optionContract.ID.OptionStyle == OptionStyle.American);
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (_hasRemoved)
|
||||
{
|
||||
throw new RegressionTestException("Expect a single call to OnData where we removed the option and underlying");
|
||||
}
|
||||
|
||||
_hasRemoved = true;
|
||||
AddOptionContract(_contract);
|
||||
|
||||
// changed my mind!
|
||||
RemoveOptionContract(_contract);
|
||||
RemoveSecurity(_contract.Underlying);
|
||||
|
||||
RemoveSecurity(AddEquity("SPY", Resolution.Daily).Symbol);
|
||||
}
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_hasRemoved)
|
||||
{
|
||||
throw new RegressionTestException("We did not remove the option contract!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 25;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 1;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "-9.486"},
|
||||
{"Tracking Error", "0.008"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Portfolio Turnover", "0%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Brokerages;
|
||||
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression test to explain how Beta indicator works
|
||||
/// </summary>
|
||||
public class AddBetaIndicatorNewAssetsRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Beta _beta;
|
||||
private SimpleMovingAverage _sma;
|
||||
private decimal _lastSMAValue;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2015, 05, 08);
|
||||
SetEndDate(2017, 06, 15);
|
||||
SetCash(10000);
|
||||
|
||||
AddCrypto("BTCUSD", Resolution.Daily);
|
||||
AddEquity("SPY", Resolution.Daily);
|
||||
|
||||
EnableAutomaticIndicatorWarmUp = true;
|
||||
_beta = B("BTCUSD", "SPY", 3, Resolution.Daily);
|
||||
_sma = SMA("SPY", 3, Resolution.Daily);
|
||||
_lastSMAValue = 0;
|
||||
|
||||
if (!_beta.IsReady)
|
||||
{
|
||||
throw new RegressionTestException("Beta indicator was expected to be ready");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
var price = Securities["BTCUSD"].Price;
|
||||
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
var quantityToBuy = (int)(Portfolio.Cash * 0.05m / price);
|
||||
Buy("BTCUSD", quantityToBuy);
|
||||
}
|
||||
|
||||
if (Math.Abs(_beta.Current.Value) > 2)
|
||||
{
|
||||
Liquidate("BTCUSD");
|
||||
Log("Liquidated BTCUSD due to high Beta");
|
||||
}
|
||||
|
||||
Log($"Beta between BTCUSD and SPY is: {_beta.Current.Value}");
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
var order = Transactions.GetOrderById(orderEvent.OrderId);
|
||||
var goUpwards = _lastSMAValue < _sma.Current.Value;
|
||||
_lastSMAValue = _sma.Current.Value;
|
||||
|
||||
if (order.Status == OrderStatus.Filled)
|
||||
{
|
||||
if (order.Type == OrderType.Limit && Math.Abs(_beta.Current.Value - 1) < 0.2m && goUpwards)
|
||||
{
|
||||
Transactions.CancelOpenOrders(order.Symbol);
|
||||
}
|
||||
}
|
||||
|
||||
if (order.Status == OrderStatus.Canceled)
|
||||
{
|
||||
Log(orderEvent.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public virtual List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 5798;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 26;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "327"},
|
||||
{"Average Win", "0.32%"},
|
||||
{"Average Loss", "-0.02%"},
|
||||
{"Compounding Annual Return", "1.274%"},
|
||||
{"Drawdown", "1.100%"},
|
||||
{"Expectancy", "0.904"},
|
||||
{"Start Equity", "10000.00"},
|
||||
{"End Equity", "10270.95"},
|
||||
{"Net Profit", "2.710%"},
|
||||
{"Sharpe Ratio", "-0.126"},
|
||||
{"Sortino Ratio", "-0.112"},
|
||||
{"Probabilistic Sharpe Ratio", "2.398%"},
|
||||
{"Loss Rate", "90%"},
|
||||
{"Win Rate", "10%"},
|
||||
{"Profit-Loss Ratio", "17.14"},
|
||||
{"Alpha", "-0.002"},
|
||||
{"Beta", "0.004"},
|
||||
{"Annual Standard Deviation", "0.01"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.536"},
|
||||
{"Tracking Error", "0.111"},
|
||||
{"Treynor Ratio", "-0.335"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$100000.00"},
|
||||
{"Lowest Capacity Asset", "BTCUSD 2XR"},
|
||||
{"Portfolio Turnover", "1.69%"},
|
||||
{"Drawdown Recovery", "104"},
|
||||
{"OrderListHash", "52a71939d45d41e0c585301b2ae71f21"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression test to explain how Beta indicator works
|
||||
/// </summary>
|
||||
public class AddBetaIndicatorRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Beta _beta;
|
||||
private SimpleMovingAverage _sma;
|
||||
private decimal _lastSMAValue;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07);
|
||||
SetEndDate(2013, 10, 15);
|
||||
SetCash(10000);
|
||||
|
||||
AddEquity("IBM");
|
||||
AddEquity("SPY");
|
||||
|
||||
EnableAutomaticIndicatorWarmUp = true;
|
||||
_beta = B("IBM", "SPY", 3, Resolution.Daily);
|
||||
_sma = SMA("SPY", 3, Resolution.Daily);
|
||||
_lastSMAValue = 0;
|
||||
|
||||
if (!_beta.IsReady)
|
||||
{
|
||||
throw new RegressionTestException("Beta indicator was expected to be ready");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
var price = slice["IBM"].Close;
|
||||
Buy("IBM", 10);
|
||||
LimitOrder("IBM", 10, price * 0.1m);
|
||||
StopMarketOrder("IBM", 10, price / 0.1m);
|
||||
}
|
||||
|
||||
if (_beta.Current.Value < 0m || _beta.Current.Value > 2.80m)
|
||||
{
|
||||
throw new RegressionTestException($"_beta value was expected to be between 0 and 2.80 but was {_beta.Current.Value}");
|
||||
}
|
||||
|
||||
Log($"Beta between IBM and SPY is: {_beta.Current.Value}");
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
var order = Transactions.GetOrderById(orderEvent.OrderId);
|
||||
var goUpwards = _lastSMAValue < _sma.Current.Value;
|
||||
_lastSMAValue = _sma.Current.Value;
|
||||
|
||||
if (order.Status == OrderStatus.Filled)
|
||||
{
|
||||
if (order.Type == OrderType.Limit && Math.Abs(_beta.Current.Value - 1) < 0.2m && goUpwards)
|
||||
{
|
||||
Transactions.CancelOpenOrders(order.Symbol);
|
||||
}
|
||||
}
|
||||
|
||||
if (order.Status == OrderStatus.Canceled)
|
||||
{
|
||||
Log(orderEvent.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public virtual List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 10977;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 11;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "3"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "12.939%"},
|
||||
{"Drawdown", "0.300%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "10000"},
|
||||
{"End Equity", "10028.93"},
|
||||
{"Net Profit", "0.289%"},
|
||||
{"Sharpe Ratio", "3.924"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "66.659%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.028"},
|
||||
{"Beta", "0.122"},
|
||||
{"Annual Standard Deviation", "0.024"},
|
||||
{"Annual Variance", "0.001"},
|
||||
{"Information Ratio", "-3.181"},
|
||||
{"Tracking Error", "0.142"},
|
||||
{"Treynor Ratio", "0.78"},
|
||||
{"Total Fees", "$1.00"},
|
||||
{"Estimated Strategy Capacity", "$35000000.00"},
|
||||
{"Lowest Capacity Asset", "IBM R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "1.51%"},
|
||||
{"Drawdown Recovery", "2"},
|
||||
{"OrderListHash", "1db1ce949db995bba20ed96ea5e2438a"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Securities.Future;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Continuous Futures Regression algorithm. Asserting and showcasing the behavior of adding a continuous future
|
||||
/// and a future contract at the same time
|
||||
/// </summary>
|
||||
public class AddFutureContractWithContinuousRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Future _continuousContract;
|
||||
private Future _futureContract;
|
||||
private bool _ended;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 6);
|
||||
SetEndDate(2013, 10, 10);
|
||||
|
||||
_continuousContract = AddFuture(Futures.Indices.SP500EMini,
|
||||
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
|
||||
dataMappingMode: DataMappingMode.LastTradingDay,
|
||||
contractDepthOffset: 0
|
||||
);
|
||||
|
||||
_futureContract = AddFutureContract(FuturesChain(_continuousContract.Symbol).First());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="slice">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (_ended)
|
||||
{
|
||||
throw new RegressionTestException($"Algorithm should of ended!");
|
||||
}
|
||||
if (slice.Keys.Count > 2)
|
||||
{
|
||||
throw new RegressionTestException($"Getting data for more than 2 symbols! {string.Join(",", slice.Keys.Select(symbol => symbol))}");
|
||||
}
|
||||
if (UniverseManager.Count != 3)
|
||||
{
|
||||
throw new RegressionTestException($"Expecting 3 universes (chain, continuous and user defined) but have {UniverseManager.Count}");
|
||||
}
|
||||
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
Buy(_futureContract.Symbol, 1);
|
||||
Buy(_continuousContract.Mapped, 1);
|
||||
|
||||
RemoveSecurity(_futureContract.Symbol);
|
||||
RemoveSecurity(_continuousContract.Symbol);
|
||||
|
||||
_ended = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
if (orderEvent.Status == OrderStatus.Filled)
|
||||
{
|
||||
Log($"{orderEvent}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
Debug($"{Time}-{changes}");
|
||||
|
||||
if (changes.AddedSecurities.Any(security => security.Symbol != _continuousContract.Symbol && security.Symbol != _futureContract.Symbol)
|
||||
|| changes.RemovedSecurities.Any(security => security.Symbol != _continuousContract.Symbol && security.Symbol != _futureContract.Symbol))
|
||||
{
|
||||
throw new RegressionTestException($"We got an unexpected security changes {changes}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 61;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 1;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "4"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.10%"},
|
||||
{"Compounding Annual Return", "-14.232%"},
|
||||
{"Drawdown", "0.200%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "99803.9"},
|
||||
{"Net Profit", "-0.196%"},
|
||||
{"Sharpe Ratio", "-7.95"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0.401%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.128"},
|
||||
{"Beta", "0.026"},
|
||||
{"Annual Standard Deviation", "0.016"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-1.186"},
|
||||
{"Tracking Error", "0.237"},
|
||||
{"Treynor Ratio", "-4.747"},
|
||||
{"Total Fees", "$8.60"},
|
||||
{"Estimated Strategy Capacity", "$2000.00"},
|
||||
{"Lowest Capacity Asset", "ES VU1EHIDJYLMP"},
|
||||
{"Portfolio Turnover", "66.50%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "4720516462fcabb4db1aead46051cb4a"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This regression algorithm tests that we receive the expected data when
|
||||
/// we add future option contracts individually using <see cref="AddFutureOptionContract"/>
|
||||
/// </summary>
|
||||
public class AddFutureOptionContractDataStreamingRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private bool _onDataReached;
|
||||
private bool _invested;
|
||||
private Symbol _es20h20;
|
||||
private Symbol _es19m20;
|
||||
|
||||
private readonly HashSet<Symbol> _symbolsReceived = new HashSet<Symbol>();
|
||||
private readonly HashSet<Symbol> _expectedSymbolsReceived = new HashSet<Symbol>();
|
||||
private readonly Dictionary<Symbol, List<QuoteBar>> _dataReceived = new Dictionary<Symbol, List<QuoteBar>>();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2020, 1, 4);
|
||||
SetEndDate(2020, 1, 8);
|
||||
|
||||
_es20h20 = AddFutureContract(
|
||||
QuantConnect.Symbol.CreateFuture(Futures.Indices.SP500EMini, Market.CME, new DateTime(2020, 3, 20)),
|
||||
Resolution.Minute).Symbol;
|
||||
|
||||
_es19m20 = AddFutureContract(
|
||||
QuantConnect.Symbol.CreateFuture(Futures.Indices.SP500EMini, Market.CME, new DateTime(2020, 6, 19)),
|
||||
Resolution.Minute).Symbol;
|
||||
|
||||
// Get option contract lists for 2020/01/05 (Time.AddDays(1)) because Lean has local data for that date
|
||||
var optionChains = OptionChainProvider.GetOptionContractList(_es20h20, Time.AddDays(1))
|
||||
.Concat(OptionChainProvider.GetOptionContractList(_es19m20, Time.AddDays(1)));
|
||||
|
||||
foreach (var optionContract in optionChains)
|
||||
{
|
||||
_expectedSymbolsReceived.Add(AddFutureOptionContract(optionContract, Resolution.Minute).Symbol);
|
||||
}
|
||||
|
||||
if (_expectedSymbolsReceived.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Expected Symbols receive count is 0, expected >0");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!slice.HasData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_onDataReached = true;
|
||||
|
||||
var hasOptionQuoteBars = false;
|
||||
foreach (var qb in slice.QuoteBars.Values)
|
||||
{
|
||||
if (qb.Symbol.SecurityType != SecurityType.FutureOption)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
hasOptionQuoteBars = true;
|
||||
|
||||
_symbolsReceived.Add(qb.Symbol);
|
||||
if (!_dataReceived.ContainsKey(qb.Symbol))
|
||||
{
|
||||
_dataReceived[qb.Symbol] = new List<QuoteBar>();
|
||||
}
|
||||
|
||||
_dataReceived[qb.Symbol].Add(qb);
|
||||
}
|
||||
|
||||
if (_invested || !hasOptionQuoteBars)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (slice.ContainsKey(_es20h20) && slice.ContainsKey(_es19m20))
|
||||
{
|
||||
SetHoldings(_es20h20, 0.2);
|
||||
SetHoldings(_es19m20, 0.2);
|
||||
|
||||
_invested = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
base.OnEndOfAlgorithm();
|
||||
|
||||
if (!_onDataReached)
|
||||
{
|
||||
throw new RegressionTestException("OnData() was never called.");
|
||||
}
|
||||
if (_symbolsReceived.Count != _expectedSymbolsReceived.Count)
|
||||
{
|
||||
throw new AggregateException($"Expected {_expectedSymbolsReceived.Count} option contracts Symbols, found {_symbolsReceived.Count}");
|
||||
}
|
||||
|
||||
var missingSymbols = new List<Symbol>();
|
||||
foreach (var expectedSymbol in _expectedSymbolsReceived)
|
||||
{
|
||||
if (!_symbolsReceived.Contains(expectedSymbol))
|
||||
{
|
||||
missingSymbols.Add(expectedSymbol);
|
||||
}
|
||||
}
|
||||
|
||||
if (missingSymbols.Count > 0)
|
||||
{
|
||||
throw new RegressionTestException($"Symbols: \"{string.Join(", ", missingSymbols)}\" were not found in OnData");
|
||||
}
|
||||
|
||||
foreach (var expectedSymbol in _expectedSymbolsReceived)
|
||||
{
|
||||
var data = _dataReceived[expectedSymbol];
|
||||
var nonDupeDataCount = data.Select(x =>
|
||||
{
|
||||
x.EndTime = default(DateTime);
|
||||
return x;
|
||||
}).Distinct().Count();
|
||||
|
||||
if (nonDupeDataCount < 1000)
|
||||
{
|
||||
throw new RegressionTestException($"Received too few data points. Expected >=1000, found {nonDupeDataCount} for {expectedSymbol}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 311881;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 2;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "5512.811%"},
|
||||
{"Drawdown", "1.000%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "105332.8"},
|
||||
{"Net Profit", "5.333%"},
|
||||
{"Sharpe Ratio", "64.084"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "95.688%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "25.763"},
|
||||
{"Beta", "2.914"},
|
||||
{"Annual Standard Deviation", "0.423"},
|
||||
{"Annual Variance", "0.179"},
|
||||
{"Information Ratio", "66.11"},
|
||||
{"Tracking Error", "0.403"},
|
||||
{"Treynor Ratio", "9.308"},
|
||||
{"Total Fees", "$8.60"},
|
||||
{"Estimated Strategy Capacity", "$22000000.00"},
|
||||
{"Lowest Capacity Asset", "ES XFH59UK0MYO1"},
|
||||
{"Portfolio Turnover", "122.11%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d744fa8beaa60546c84924ed68d945d9"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This regression algorithm tests we can add future option contracts from contracts in the future chain
|
||||
/// </summary>
|
||||
public class AddFutureOptionContractFromFutureChainRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private bool _addedOptions;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2020, 1, 4);
|
||||
SetEndDate(2020, 1, 6);
|
||||
|
||||
var es = AddFuture(Futures.Indices.SP500EMini, Resolution.Minute, Market.CME);
|
||||
es.SetFilter((futureFilter) =>
|
||||
{
|
||||
return futureFilter.Expiration(0, 365).ExpirationCycle(new[] { 3, 6 });
|
||||
});
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!_addedOptions)
|
||||
{
|
||||
_addedOptions = true;
|
||||
foreach (var futuresContracts in slice.FutureChains.Values)
|
||||
{
|
||||
foreach (var contract in futuresContracts)
|
||||
{
|
||||
var option_contract_symbols = OptionChain(contract.Symbol).ToList();
|
||||
if(option_contract_symbols.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var option_contract_symbol in option_contract_symbols.OrderBy(x => x.ID.Date)
|
||||
.ThenBy(x => x.ID.StrikePrice)
|
||||
.ThenBy(x => x.ID.OptionRight).Take(5))
|
||||
{
|
||||
AddOptionContract(option_contract_symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Portfolio.Invested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var chain in slice.OptionChains.Values)
|
||||
{
|
||||
foreach (var option in chain.Contracts.Keys)
|
||||
{
|
||||
MarketOrder(option, 1);
|
||||
MarketOrder(option.Underlying, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 9922;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 2;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "20"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "88398927.578%"},
|
||||
{"Drawdown", "5.200%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "111911.55"},
|
||||
{"Net Profit", "11.912%"},
|
||||
{"Sharpe Ratio", "1604181.904"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "2144882.02"},
|
||||
{"Beta", "31.223"},
|
||||
{"Annual Standard Deviation", "1.337"},
|
||||
{"Annual Variance", "1.788"},
|
||||
{"Information Ratio", "1657259.526"},
|
||||
{"Tracking Error", "1.294"},
|
||||
{"Treynor Ratio", "68696.045"},
|
||||
{"Total Fees", "$35.70"},
|
||||
{"Estimated Strategy Capacity", "$2600000.00"},
|
||||
{"Lowest Capacity Asset", "ES 31C3JQS9DCF1G|ES XCZJLC9NOB29"},
|
||||
{"Portfolio Turnover", "495.15%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "af830085995d0b8fa0d33a6e80dd1241"}
|
||||
};
|
||||
}
|
||||
}
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Future;
|
||||
using QuantConnect.Securities.Option;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm asserting AddFutureOptionContract does not throw even when the underlying security configurations are internal
|
||||
/// </summary>
|
||||
public class AddFutureOptionContractWithInternalMappedUnderlyingRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Future _continuousContract;
|
||||
private Option _fopContract;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2020, 01, 04);
|
||||
SetEndDate(2020, 01 , 06);
|
||||
|
||||
_continuousContract = AddFuture(Futures.Indices.SP500EMini,
|
||||
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
|
||||
dataMappingMode: DataMappingMode.LastTradingDay,
|
||||
contractDepthOffset: 0);
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
if (changes.AddedSecurities.Any(security => security.Symbol == _continuousContract.Symbol))
|
||||
{
|
||||
if (SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(_continuousContract.Mapped).Count != 0 ||
|
||||
SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(_continuousContract.Mapped, includeInternalConfigs: true).Count == 0)
|
||||
{
|
||||
throw new RegressionTestException("Continuous future underlying should only have internal subscription configs");
|
||||
}
|
||||
|
||||
var contract = OptionChain(_continuousContract.Mapped).FirstOrDefault()?.Symbol;
|
||||
|
||||
try
|
||||
{
|
||||
_fopContract = AddFutureOptionContract(contract);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RegressionTestException($"Failed to add future option contract {contract}", e);
|
||||
}
|
||||
}
|
||||
else if (_fopContract != null && changes.AddedSecurities.Any(security => security.Symbol == _fopContract.Symbol))
|
||||
{
|
||||
var underlyingSubscriptions = SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(_fopContract.Symbol.Underlying);
|
||||
if (underlyingSubscriptions.Any(x => x.DataNormalizationMode == DataNormalizationMode.Raw))
|
||||
{
|
||||
throw new RegressionTestException("Future option underlying should not have raw data normalization mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (_fopContract == null)
|
||||
{
|
||||
throw new RegressionTestException("Failed to add future option contract");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 3181;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 1;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "-14.395"},
|
||||
{"Tracking Error", "0.043"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Portfolio Turnover", "0%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
+270
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Future;
|
||||
using QuantConnect.Securities.Option;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This regression algorithm tests that we only receive the option chain for a single future contract
|
||||
/// in the option universe filter.
|
||||
/// </summary>
|
||||
public class AddFutureOptionSingleOptionChainSelectedInUniverseFilterRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private bool _invested;
|
||||
private bool _onDataReached;
|
||||
private bool _optionFilterRan;
|
||||
private readonly HashSet<Symbol> _symbolsReceived = new HashSet<Symbol>();
|
||||
private readonly HashSet<Symbol> _expectedSymbolsReceived = new HashSet<Symbol>();
|
||||
private readonly Dictionary<Symbol, List<QuoteBar>> _dataReceived = new Dictionary<Symbol, List<QuoteBar>>();
|
||||
|
||||
private Future _es;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2020, 1, 4);
|
||||
SetEndDate(2020, 1, 8);
|
||||
|
||||
_es = AddFuture(Futures.Indices.SP500EMini, Resolution.Minute, Market.CME);
|
||||
_es.SetFilter((futureFilter) =>
|
||||
{
|
||||
return futureFilter.Expiration(0, 365).ExpirationCycle(new[] { 3, 6 });
|
||||
});
|
||||
|
||||
AddFutureOption(_es.Symbol, optionContracts =>
|
||||
{
|
||||
_optionFilterRan = true;
|
||||
|
||||
var expiry = new HashSet<DateTime>(optionContracts.Select(x => x.Symbol.Underlying.ID.Date)).SingleOrDefault();
|
||||
// Cast to List<Symbol> because OptionFilterContract overrides some LINQ operators like `Select` and `Where`
|
||||
// and cause it to mutate the underlying Symbol collection when using those operators.
|
||||
var symbol = new HashSet<Symbol>(((List<Symbol>)optionContracts).Select(x => x.Underlying)).SingleOrDefault();
|
||||
|
||||
if (expiry == null || symbol == null)
|
||||
{
|
||||
throw new InvalidOperationException("Expected a single Option contract in the chain, found 0 contracts");
|
||||
}
|
||||
|
||||
var enumerator = optionContracts.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
_expectedSymbolsReceived.Add(enumerator.Current);
|
||||
}
|
||||
|
||||
return optionContracts;
|
||||
});
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!slice.HasData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_onDataReached = true;
|
||||
|
||||
var hasOptionQuoteBars = false;
|
||||
foreach (var qb in slice.QuoteBars.Values)
|
||||
{
|
||||
if (qb.Symbol.SecurityType != SecurityType.FutureOption)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
hasOptionQuoteBars = true;
|
||||
|
||||
_symbolsReceived.Add(qb.Symbol);
|
||||
if (!_dataReceived.ContainsKey(qb.Symbol))
|
||||
{
|
||||
_dataReceived[qb.Symbol] = new List<QuoteBar>();
|
||||
}
|
||||
|
||||
_dataReceived[qb.Symbol].Add(qb);
|
||||
}
|
||||
|
||||
if (_invested || !hasOptionQuoteBars)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var chain in slice.OptionChains.Values.OrderBy(x => x.Symbol.Underlying.ID.Date))
|
||||
{
|
||||
var futureInvested = false;
|
||||
var optionInvested = false;
|
||||
|
||||
foreach (var option in chain.Contracts.Keys)
|
||||
{
|
||||
if (futureInvested && optionInvested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var future = option.Underlying;
|
||||
|
||||
if (!optionInvested && slice.ContainsKey(option))
|
||||
{
|
||||
var optionContract = Securities[option];
|
||||
var marginModel = optionContract.BuyingPowerModel as FuturesOptionsMarginModel;
|
||||
if (marginModel.InitialIntradayMarginRequirement == 0
|
||||
|| marginModel.InitialOvernightMarginRequirement == 0
|
||||
|| marginModel.MaintenanceIntradayMarginRequirement == 0
|
||||
|| marginModel.MaintenanceOvernightMarginRequirement == 0)
|
||||
{
|
||||
throw new RegressionTestException("Unexpected margin requirements");
|
||||
}
|
||||
|
||||
if (marginModel.GetInitialMarginRequirement(optionContract, 1) == 0)
|
||||
{
|
||||
throw new RegressionTestException("Unexpected Initial Margin requirement");
|
||||
}
|
||||
if (marginModel.GetMaintenanceMargin(optionContract) != 0)
|
||||
{
|
||||
throw new RegressionTestException("Unexpected Maintenance Margin requirement");
|
||||
}
|
||||
|
||||
MarketOrder(option, 1);
|
||||
_invested = true;
|
||||
optionInvested = true;
|
||||
|
||||
if (marginModel.GetMaintenanceMargin(optionContract) == 0)
|
||||
{
|
||||
throw new RegressionTestException("Unexpected Maintenance Margin requirement");
|
||||
}
|
||||
}
|
||||
if (!futureInvested && slice.ContainsKey(future))
|
||||
{
|
||||
MarketOrder(future, 1);
|
||||
_invested = true;
|
||||
futureInvested = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_optionFilterRan)
|
||||
{
|
||||
throw new InvalidOperationException("Option chain filter was never ran");
|
||||
}
|
||||
if (!_onDataReached)
|
||||
{
|
||||
throw new RegressionTestException("OnData() was never called.");
|
||||
}
|
||||
if (_symbolsReceived.Count != _expectedSymbolsReceived.Count)
|
||||
{
|
||||
throw new AggregateException($"Expected {_expectedSymbolsReceived.Count} option contracts Symbols, found {_symbolsReceived.Count}");
|
||||
}
|
||||
|
||||
var missingSymbols = new List<Symbol>();
|
||||
foreach (var expectedSymbol in _expectedSymbolsReceived)
|
||||
{
|
||||
if (!_symbolsReceived.Contains(expectedSymbol))
|
||||
{
|
||||
missingSymbols.Add(expectedSymbol);
|
||||
}
|
||||
}
|
||||
|
||||
if (missingSymbols.Count > 0)
|
||||
{
|
||||
throw new RegressionTestException($"Symbols: \"{string.Join(", ", missingSymbols)}\" were not found in OnData");
|
||||
}
|
||||
|
||||
foreach (var expectedSymbol in _expectedSymbolsReceived)
|
||||
{
|
||||
var data = _dataReceived[expectedSymbol];
|
||||
var nonDupeDataCount = data.Select(x =>
|
||||
{
|
||||
x.EndTime = default(DateTime);
|
||||
return x;
|
||||
}).Distinct().Count();
|
||||
|
||||
if (nonDupeDataCount < 1000)
|
||||
{
|
||||
throw new RegressionTestException($"Received too few data points. Expected >=1000, found {nonDupeDataCount} for {expectedSymbol}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 319494;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "430.834%"},
|
||||
{"Drawdown", "4.200%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "102313.03"},
|
||||
{"Net Profit", "2.313%"},
|
||||
{"Sharpe Ratio", "17.721"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "95.297%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "2.663"},
|
||||
{"Beta", "1.264"},
|
||||
{"Annual Standard Deviation", "0.184"},
|
||||
{"Annual Variance", "0.034"},
|
||||
{"Information Ratio", "16.514"},
|
||||
{"Tracking Error", "0.169"},
|
||||
{"Treynor Ratio", "2.574"},
|
||||
{"Total Fees", "$3.57"},
|
||||
{"Estimated Strategy Capacity", "$28000000.00"},
|
||||
{"Lowest Capacity Asset", "ES XCZJLCA62LNO|ES XCZJLC9NOB29"},
|
||||
{"Portfolio Turnover", "33.84%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "7c82013ecabca41591e0253a477025dd"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Interfaces;
|
||||
using System;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to use the FutureUniverseSelectionModel to select futures contracts for a given underlying asset.
|
||||
/// The model is set to update daily, and the algorithm ensures that the selected contracts meet specific criteria.
|
||||
/// This also includes a check to ensure that only future contracts are added to the algorithm's universe.
|
||||
/// </summary>
|
||||
public class AddFutureUniverseSelectionModelRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 08);
|
||||
SetEndDate(2013, 10, 10);
|
||||
|
||||
SetUniverseSelection(new FutureUniverseSelectionModel(
|
||||
TimeSpan.FromDays(1),
|
||||
time => new List<Symbol> {
|
||||
QuantConnect.Symbol.Create(Futures.Indices.SP500EMini, SecurityType.Future, Market.CME)
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
if (changes.AddedSecurities.Count > 0)
|
||||
{
|
||||
foreach (var security in changes.AddedSecurities)
|
||||
{
|
||||
if (security.Symbol.SecurityType != SecurityType.Future)
|
||||
{
|
||||
throw new RegressionTestException($"Expected future security, but found '{security.Symbol.SecurityType}'");
|
||||
}
|
||||
if (security.Symbol.ID.Symbol != "ES")
|
||||
{
|
||||
throw new RegressionTestException($"Expected future symbol 'ES', but found '{security.Symbol.ID.Symbol}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (ActiveSecurities.Count == 0)
|
||||
{
|
||||
throw new RegressionTestException("No active securities found. Expected at least one active security");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 26094;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "-66.775"},
|
||||
{"Tracking Error", "0.243"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Portfolio Turnover", "0%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// We add an option contract using <see cref="QCAlgorithm.AddOptionContract"/> and place a trade and wait till it expires
|
||||
/// later will liquidate the resulting equity position and assert both option and underlying get removed
|
||||
/// </summary>
|
||||
public class AddOptionContractExpiresRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private DateTime _expiration = new DateTime(2014, 06, 21);
|
||||
private Symbol _option;
|
||||
private Symbol _twx;
|
||||
private bool _traded;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2014, 06, 05);
|
||||
SetEndDate(2014, 06, 30);
|
||||
|
||||
_twx = QuantConnect.Symbol.Create("TWX", SecurityType.Equity, Market.USA);
|
||||
|
||||
AddUniverse("my-daily-universe-name", time => new List<string> { "AAPL" });
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (_option == null)
|
||||
{
|
||||
var option = OptionChain(_twx)
|
||||
.OrderBy(x => x.ID.Symbol)
|
||||
.FirstOrDefault(optionContract => optionContract.ID.Date == _expiration
|
||||
&& optionContract.ID.OptionRight == OptionRight.Call
|
||||
&& optionContract.ID.OptionStyle == OptionStyle.American);
|
||||
if (option != null)
|
||||
{
|
||||
_option = AddOptionContract(option).Symbol;
|
||||
}
|
||||
}
|
||||
|
||||
if (_option != null && Securities[_option].Price != 0 && !_traded)
|
||||
{
|
||||
_traded = true;
|
||||
Buy(_option, 1);
|
||||
|
||||
foreach (var symbol in new [] { _option, _option.Underlying })
|
||||
{
|
||||
var config = SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(symbol).ToList();
|
||||
|
||||
if (!config.Any())
|
||||
{
|
||||
throw new RegressionTestException($"Was expecting configurations for {symbol}");
|
||||
}
|
||||
if (config.Any(dataConfig => dataConfig.DataNormalizationMode != DataNormalizationMode.Raw))
|
||||
{
|
||||
throw new RegressionTestException($"Was expecting DataNormalizationMode.Raw configurations for {symbol}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Time.Date > _expiration)
|
||||
{
|
||||
if (SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(_option).Any())
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected configurations for {_option} after it has been delisted");
|
||||
}
|
||||
|
||||
if (Securities[_twx].Invested)
|
||||
{
|
||||
if (!SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(_twx).Any())
|
||||
{
|
||||
throw new RegressionTestException($"Was expecting configurations for {_twx}");
|
||||
}
|
||||
|
||||
// first we liquidate the option exercised position
|
||||
Liquidate(_twx);
|
||||
}
|
||||
}
|
||||
else if (Time.Date > _expiration && !Securities[_twx].Invested)
|
||||
{
|
||||
if (SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(_twx).Any())
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected configurations for {_twx} after it has been liquidated");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 37598;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 1;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "3"},
|
||||
{"Average Win", "2.67%"},
|
||||
{"Average Loss", "-2.98%"},
|
||||
{"Compounding Annual Return", "-5.432%"},
|
||||
{"Drawdown", "0.400%"},
|
||||
{"Expectancy", "-0.052"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "99608"},
|
||||
{"Net Profit", "-0.392%"},
|
||||
{"Sharpe Ratio", "-5.487"},
|
||||
{"Sortino Ratio", "-2.607"},
|
||||
{"Probabilistic Sharpe Ratio", "0.000%"},
|
||||
{"Loss Rate", "50%"},
|
||||
{"Win Rate", "50%"},
|
||||
{"Profit-Loss Ratio", "0.90"},
|
||||
{"Alpha", "-0.028"},
|
||||
{"Beta", "-0.01"},
|
||||
{"Annual Standard Deviation", "0.005"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-2.949"},
|
||||
{"Tracking Error", "0.049"},
|
||||
{"Treynor Ratio", "3.063"},
|
||||
{"Total Fees", "$2.00"},
|
||||
{"Estimated Strategy Capacity", "$5700000.00"},
|
||||
{"Lowest Capacity Asset", "AOL VRKS95ENPM9Y|AOL R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "0.54%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "65d9c6a5991648c8c54a23423a51340d"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// We add an option contract using <see cref="QCAlgorithm.AddOptionContract"/> and place a trade, the underlying
|
||||
/// gets deselected from the universe selection but should still be present since we manually added the option contract.
|
||||
/// Later we call <see cref="QCAlgorithm.RemoveOptionContract"/> and expect both option and underlying to be removed.
|
||||
/// </summary>
|
||||
public class AddOptionContractFromUniverseRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private DateTime _expiration = new DateTime(2014, 06, 21);
|
||||
private SecurityChanges _securityChanges = SecurityChanges.None;
|
||||
private Symbol _option;
|
||||
private Symbol _aapl;
|
||||
private Symbol _twx;
|
||||
private bool _traded;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
_twx = QuantConnect.Symbol.Create("TWX", SecurityType.Equity, Market.USA);
|
||||
_aapl = QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA);
|
||||
UniverseSettings.Resolution = Resolution.Minute;
|
||||
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
|
||||
|
||||
SetStartDate(2014, 06, 05);
|
||||
SetEndDate(2014, 06, 09);
|
||||
|
||||
AddUniverse(enumerable => new[] { Time.Date <= new DateTime(2014, 6, 5) ? _twx : _aapl },
|
||||
enumerable => new[] { Time.Date <= new DateTime(2014, 6, 5) ? _twx : _aapl });
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (_option != null && Securities[_option].Price != 0 && !_traded)
|
||||
{
|
||||
_traded = true;
|
||||
Buy(_option, 1);
|
||||
}
|
||||
|
||||
if (Time.Date > new DateTime(2014, 6, 5))
|
||||
{
|
||||
if (Time < new DateTime(2014, 6, 6, 14, 0, 0))
|
||||
{
|
||||
var configs = SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(_twx);
|
||||
// assert underlying still there after the universe selection removed it, still used by the manually added option contract
|
||||
if (!configs.Any())
|
||||
{
|
||||
throw new RegressionTestException($"Was expecting configurations for {_twx}" +
|
||||
$" even after it has been deselected from coarse universe because we still have the option contract.");
|
||||
}
|
||||
}
|
||||
else if (Time == new DateTime(2014, 6, 6, 14, 0, 0))
|
||||
{
|
||||
// liquidate & remove the option
|
||||
RemoveOptionContract(_option);
|
||||
}
|
||||
// assert underlying was finally removed
|
||||
else if(Time > new DateTime(2014, 6, 6, 14, 0, 0))
|
||||
{
|
||||
foreach (var symbol in new[] { _option, _option.Underlying })
|
||||
{
|
||||
var configs = SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(symbol);
|
||||
if (configs.Any())
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected configuration for {symbol} after it has been deselected from coarse universe and option contract is removed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
if (_securityChanges.RemovedSecurities.Intersect(changes.RemovedSecurities).Any())
|
||||
{
|
||||
throw new RegressionTestException($"SecurityChanges.RemovedSecurities intersect {changes.RemovedSecurities}. We expect no duplicate!");
|
||||
}
|
||||
if (_securityChanges.AddedSecurities.Intersect(changes.AddedSecurities).Any())
|
||||
{
|
||||
throw new RegressionTestException($"SecurityChanges.AddedSecurities intersect {changes.RemovedSecurities}. We expect no duplicate!");
|
||||
}
|
||||
// keep track of all removed and added securities
|
||||
_securityChanges += changes;
|
||||
|
||||
if (changes.AddedSecurities.Any(security => security.Symbol.SecurityType == SecurityType.Option))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var addedSecurity in changes.AddedSecurities)
|
||||
{
|
||||
var option = OptionChain(addedSecurity.Symbol)
|
||||
.OrderBy(contractData => contractData.ID.Symbol)
|
||||
.First(optionContract => optionContract.ID.Date == _expiration
|
||||
&& optionContract.ID.OptionRight == OptionRight.Call
|
||||
&& optionContract.ID.OptionStyle == OptionStyle.American);
|
||||
AddOptionContract(option);
|
||||
|
||||
foreach (var symbol in new[] { option.Symbol, option.UnderlyingSymbol })
|
||||
{
|
||||
var config = SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(symbol).ToList();
|
||||
|
||||
if (!config.Any())
|
||||
{
|
||||
throw new RegressionTestException($"Was expecting configurations for {symbol}");
|
||||
}
|
||||
if (config.Any(dataConfig => dataConfig.DataNormalizationMode != DataNormalizationMode.Raw))
|
||||
{
|
||||
throw new RegressionTestException($"Was expecting DataNormalizationMode.Raw configurations for {symbol}");
|
||||
}
|
||||
}
|
||||
|
||||
// just keep the first we got
|
||||
if (_option == null)
|
||||
{
|
||||
_option = option;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (SubscriptionManager.Subscriptions.Any(dataConfig => dataConfig.Symbol == _twx || dataConfig.Symbol.Underlying == _twx))
|
||||
{
|
||||
throw new RegressionTestException($"Was NOT expecting any configurations for {_twx} or it's options, since we removed the contract");
|
||||
}
|
||||
|
||||
if (SubscriptionManager.Subscriptions.All(dataConfig => dataConfig.Symbol != _aapl))
|
||||
{
|
||||
throw new RegressionTestException($"Was expecting configurations for {_aapl}");
|
||||
}
|
||||
if (SubscriptionManager.Subscriptions.All(dataConfig => dataConfig.Symbol.Underlying != _aapl))
|
||||
{
|
||||
throw new RegressionTestException($"Was expecting options configurations for {_aapl}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 5800;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 2;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.23%"},
|
||||
{"Compounding Annual Return", "-15.596%"},
|
||||
{"Drawdown", "0.200%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "99768"},
|
||||
{"Net Profit", "-0.232%"},
|
||||
{"Sharpe Ratio", "-8.903"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0.024%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.015"},
|
||||
{"Beta", "-0.171"},
|
||||
{"Annual Standard Deviation", "0.006"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-11.082"},
|
||||
{"Tracking Error", "0.043"},
|
||||
{"Treynor Ratio", "0.335"},
|
||||
{"Total Fees", "$2.00"},
|
||||
{"Estimated Strategy Capacity", "$2800000.00"},
|
||||
{"Lowest Capacity Asset", "AOL VRKS95ENPM9Y|AOL R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "1.14%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "e33b98d8e94ed92d0441fc6fe0d461fb"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm reproducing GH issue #6073 where we remove and re add an option and expect it to work
|
||||
/// </summary>
|
||||
public class AddOptionContractTwiceRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _contract;
|
||||
private bool _hasRemoved;
|
||||
private bool _reAdded;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2014, 06, 06);
|
||||
SetEndDate(2014, 06, 09);
|
||||
|
||||
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
|
||||
UniverseSettings.MinimumTimeInUniverse = TimeSpan.Zero;
|
||||
UniverseSettings.FillForward = false;
|
||||
|
||||
AddEquity("SPY", Resolution.Hour);
|
||||
|
||||
var aapl = QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA);
|
||||
|
||||
_contract = OptionChain(aapl)
|
||||
.OrderBy(x => x.ID.StrikePrice)
|
||||
.FirstOrDefault(optionContract => optionContract.ID.OptionRight == OptionRight.Call
|
||||
&& optionContract.ID.OptionStyle == OptionStyle.American);
|
||||
AddOptionContract(_contract);
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (_hasRemoved)
|
||||
{
|
||||
if (!_reAdded && slice.ContainsKey(_contract) && slice.ContainsKey(_contract.Underlying))
|
||||
{
|
||||
throw new RegressionTestException("Getting data for removed option and underlying!");
|
||||
}
|
||||
|
||||
if (!Portfolio.Invested && _reAdded)
|
||||
{
|
||||
var option = Securities[_contract];
|
||||
var optionUnderlying = Securities[_contract.Underlying];
|
||||
if (option.IsTradable && optionUnderlying.IsTradable
|
||||
&& slice.ContainsKey(_contract) && slice.ContainsKey(_contract.Underlying))
|
||||
{
|
||||
Buy(_contract, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Securities[_contract].IsTradable
|
||||
&& !Securities[_contract.Underlying].IsTradable
|
||||
&& !_reAdded)
|
||||
{
|
||||
// ha changed my mind!
|
||||
AddOptionContract(_contract);
|
||||
_reAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (slice.ContainsKey(_contract) && slice.ContainsKey(_contract.Underlying))
|
||||
{
|
||||
if (!_hasRemoved)
|
||||
{
|
||||
RemoveOptionContract(_contract);
|
||||
RemoveSecurity(_contract.Underlying);
|
||||
_hasRemoved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_hasRemoved)
|
||||
{
|
||||
throw new RegressionTestException("We did not remove the option contract!");
|
||||
}
|
||||
if (!_reAdded)
|
||||
{
|
||||
throw new RegressionTestException("We did not re add the option contract!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 3818;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 1;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.50%"},
|
||||
{"Compounding Annual Return", "-39.406%"},
|
||||
{"Drawdown", "0.700%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "99498"},
|
||||
{"Net Profit", "-0.502%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-9.486"},
|
||||
{"Tracking Error", "0.008"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$2.00"},
|
||||
{"Estimated Strategy Capacity", "$5000000.00"},
|
||||
{"Lowest Capacity Asset", "AAPL VXBK4R62H7S6|AAPL R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "22.70%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "71511e4929377cd55fbf5e7e9555c248"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Interfaces;
|
||||
using System;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to use the OptionUniverseSelectionModel to select options contracts based on specified conditions.
|
||||
/// The model is updated daily and selects different options based on the current date.
|
||||
/// The algorithm ensures that only valid option contracts are selected for the universe.
|
||||
/// </summary>
|
||||
public class AddOptionUniverseSelectionModelRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private int _optionCount;
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2014, 06, 05);
|
||||
SetEndDate(2014, 06, 06);
|
||||
|
||||
UniverseSettings.Resolution = Resolution.Minute;
|
||||
SetUniverseSelection(new OptionUniverseSelectionModel(
|
||||
TimeSpan.FromDays(1),
|
||||
SelectOptionChainSymbols
|
||||
));
|
||||
}
|
||||
|
||||
private static IEnumerable<Symbol> SelectOptionChainSymbols(DateTime utcTime)
|
||||
{
|
||||
var newYorkTime = utcTime.ConvertFromUtc(TimeZones.NewYork);
|
||||
if (newYorkTime.Date < new DateTime(2014, 06, 06))
|
||||
{
|
||||
yield return QuantConnect.Symbol.Create("TWX", SecurityType.Option, Market.USA);
|
||||
}
|
||||
|
||||
if (newYorkTime.Date >= new DateTime(2014, 06, 06))
|
||||
{
|
||||
yield return QuantConnect.Symbol.Create("AAPL", SecurityType.Option, Market.USA);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
if (changes.AddedSecurities.Count > 0)
|
||||
{
|
||||
foreach (var security in changes.AddedSecurities)
|
||||
{
|
||||
var symbol = security.Symbol.Underlying == null ? security.Symbol : security.Symbol.Underlying;
|
||||
if (symbol != "AAPL" && symbol != "TWX")
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected security {security.Symbol}");
|
||||
}
|
||||
_optionCount += (security.Symbol.SecurityType == SecurityType.Option) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (ActiveSecurities.Count == 0)
|
||||
{
|
||||
throw new RegressionTestException("No active securities found. Expected at least one active security");
|
||||
}
|
||||
if (_optionCount == 0)
|
||||
{
|
||||
throw new RegressionTestException("The option count should be greater than 0");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 2349547;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Portfolio Turnover", "0%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm asserting that using OnlyApplyFilterAtMarketOpen along with other dynamic filters will make the filters be applied only on market
|
||||
/// open, regardless of the order of configuration of the filters
|
||||
/// </summary>
|
||||
public class AddOptionWithOnMarketOpenOnlyFilterRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2014, 6, 5);
|
||||
SetEndDate(2014, 6, 10);
|
||||
|
||||
// OnlyApplyFilterAtMarketOpen as first filter
|
||||
AddOption("AAPL", Resolution.Minute).SetFilter(u =>
|
||||
u.OnlyApplyFilterAtMarketOpen()
|
||||
.Strikes(-5, 5)
|
||||
.Expiration(0, 100)
|
||||
.IncludeWeeklys());
|
||||
|
||||
// OnlyApplyFilterAtMarketOpen as last filter
|
||||
AddOption("TWX", Resolution.Minute).SetFilter(u =>
|
||||
u.Strikes(-5, 5)
|
||||
.Expiration(0, 100)
|
||||
.IncludeWeeklys()
|
||||
.OnlyApplyFilterAtMarketOpen());
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
// This will be the first call, the underlying securities are added.
|
||||
if (changes.AddedSecurities.All(s => s.Type != SecurityType.Option))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var changeOptions = changes.AddedSecurities.Concat(changes.RemovedSecurities)
|
||||
.Where(s => s.Type == SecurityType.Option);
|
||||
|
||||
if (Time != Time.Date)
|
||||
{
|
||||
throw new RegressionTestException($"Expected options filter to be run only at midnight. Actual was {Time}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all time slices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 470217;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "-10.144"},
|
||||
{"Tracking Error", "0.033"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Portfolio Turnover", "0%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Util;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
// ReSharper disable InvokeAsExtensionMethod -- .net 4.7.2 added ToHashSet and it looks like our version of mono has it as well causing ambiguity in the cloud
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
public class AddRemoveOptionUniverseRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private const string UnderlyingTicker = "GOOG";
|
||||
private readonly Symbol Underlying = QuantConnect.Symbol.Create(UnderlyingTicker, SecurityType.Equity, Market.USA);
|
||||
private readonly Symbol OptionChainSymbol = QuantConnect.Symbol.Create(UnderlyingTicker, SecurityType.Option, Market.USA);
|
||||
private readonly HashSet<Symbol> _expectedSecurities = new HashSet<Symbol>();
|
||||
private readonly HashSet<Symbol> _expectedData = new HashSet<Symbol>();
|
||||
private readonly HashSet<Symbol> _expectedUniverses = new HashSet<Symbol>();
|
||||
private bool _expectUniverseSubscription;
|
||||
private DateTime _universeSubscriptionTime;
|
||||
|
||||
// order of expected contract additions as price moves
|
||||
private int _expectedContractIndex;
|
||||
private readonly List<Symbol> _expectedContracts = new List<Symbol>
|
||||
{
|
||||
SymbolRepresentation.ParseOptionTickerOSI("GOOG 151224P00750000"),
|
||||
SymbolRepresentation.ParseOptionTickerOSI("GOOG 151224P00752500"),
|
||||
SymbolRepresentation.ParseOptionTickerOSI("GOOG 151224P00755000")
|
||||
};
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2015, 12, 24);
|
||||
SetEndDate(2015, 12, 24);
|
||||
|
||||
var goog = AddEquity(UnderlyingTicker);
|
||||
|
||||
// expect GOOG equity
|
||||
_expectedData.Add(goog.Symbol);
|
||||
_expectedSecurities.Add(goog.Symbol);
|
||||
// expect user defined universe holding GOOG equity
|
||||
_expectedUniverses.Add(UserDefinedUniverse.CreateSymbol(SecurityType.Equity, Market.USA));
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
// verify expectations
|
||||
if (SubscriptionManager.Subscriptions.Count(x => x.Symbol == OptionChainSymbol)
|
||||
!= (_expectUniverseSubscription ? 1 : 0))
|
||||
{
|
||||
Log($"SubscriptionManager.Subscriptions: {string.Join(" -- ", SubscriptionManager.Subscriptions)}");
|
||||
throw new RegressionTestException($"Unexpected {OptionChainSymbol} subscription presence");
|
||||
}
|
||||
if (Time != _universeSubscriptionTime && !slice.ContainsKey(Underlying))
|
||||
{
|
||||
// TODO : In fact, we're unable to properly detect whether or not we auto-added or it was manually added
|
||||
// this is because when we auto-add the underlying we don't mark it as an internal security like we do with other auto adds
|
||||
// so there's currently no good way to remove the underlying equity without invoking RemoveSecurity(underlying) manually
|
||||
// from the algorithm, otherwise we may remove it incorrectly. Now, we could track MORE state, but it would likely be a duplication
|
||||
// of the internal flag's purpose, so kicking this issue for now with a big fat note here about it :) to be considerd for any future
|
||||
// refactorings of how we manage subscription/security data and track various aspects about the security (thinking a flags enum with
|
||||
// things like manually added, auto added, internal, and any other boolean state we need to track against a single security)
|
||||
throw new RegressionTestException("The underlying equity data should NEVER be removed in this algorithm because it was manually added");
|
||||
}
|
||||
if (_expectedSecurities.AreDifferent(Securities.Total.Select(x => x.Symbol).ToHashSet()))
|
||||
{
|
||||
var expected = string.Join(Environment.NewLine, _expectedSecurities.OrderBy(s => s.ToString()));
|
||||
var actual = string.Join(Environment.NewLine, Securities.Keys.OrderBy(s => s.ToString()));
|
||||
throw new RegressionTestException($"{Time}:: Detected differences in expected and actual securities{Environment.NewLine}Expected:{Environment.NewLine}{expected}{Environment.NewLine}Actual:{Environment.NewLine}{actual}");
|
||||
}
|
||||
if (_expectedUniverses.AreDifferent(UniverseManager.Keys.ToHashSet()))
|
||||
{
|
||||
var expected = string.Join(Environment.NewLine, _expectedUniverses.OrderBy(s => s.ToString()));
|
||||
var actual = string.Join(Environment.NewLine, UniverseManager.Keys.OrderBy(s => s.ToString()));
|
||||
throw new RegressionTestException($"{Time}:: Detected differences in expected and actual universes{Environment.NewLine}Expected:{Environment.NewLine}{expected}{Environment.NewLine}Actual:{Environment.NewLine}{actual}");
|
||||
}
|
||||
if (Time != _universeSubscriptionTime && _expectedData.AreDifferent(slice.Keys.ToHashSet()))
|
||||
{
|
||||
var expected = string.Join(Environment.NewLine, _expectedData.OrderBy(s => s.ToString()));
|
||||
var actual = string.Join(Environment.NewLine, slice.Keys.OrderBy(s => s.ToString()));
|
||||
throw new RegressionTestException($"{Time}:: Detected differences in expected and actual slice data keys{Environment.NewLine}Expected:{Environment.NewLine}{expected}{Environment.NewLine}Actual:{Environment.NewLine}{actual}");
|
||||
}
|
||||
|
||||
// 10AM add GOOG option chain
|
||||
if (Time.TimeOfDay.Hours == 10 && Time.TimeOfDay.Minutes == 0 && !_expectUniverseSubscription)
|
||||
{
|
||||
if (Securities.ContainsKey(OptionChainSymbol))
|
||||
{
|
||||
throw new RegressionTestException("The option chain security should not have been added yet");
|
||||
}
|
||||
|
||||
var googOptionChain = AddOption(UnderlyingTicker);
|
||||
googOptionChain.SetFilter(u =>
|
||||
{
|
||||
// we added the universe at 10, the universe selection data should not be from before
|
||||
if (u.LocalTime.Hour < 10)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected selection time {u.LocalTime}");
|
||||
}
|
||||
// find first put above market price
|
||||
return u.IncludeWeeklys()
|
||||
.Strikes(+1, +3)
|
||||
.Expiration(TimeSpan.Zero, TimeSpan.FromDays(1))
|
||||
.Contracts(c => c.Where(s => s.ID.OptionRight == OptionRight.Put));
|
||||
});
|
||||
|
||||
_expectedSecurities.Add(OptionChainSymbol);
|
||||
_expectedUniverses.Add(OptionChainSymbol);
|
||||
_expectUniverseSubscription = true;
|
||||
_universeSubscriptionTime = Time;
|
||||
}
|
||||
|
||||
// 11:30AM remove GOOG option chain
|
||||
if (Time.TimeOfDay.Hours == 11 && Time.TimeOfDay.Minutes == 30)
|
||||
{
|
||||
RemoveSecurity(OptionChainSymbol);
|
||||
// remove contracts from expected data
|
||||
_expectedData.RemoveWhere(s => _expectedContracts.Contains(s));
|
||||
// remove option chain universe from expected universes
|
||||
_expectedUniverses.Remove(OptionChainSymbol);
|
||||
// OptionChainSymbol universe subscription should not be present
|
||||
_expectUniverseSubscription = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
if (changes.AddedSecurities.Any())
|
||||
{
|
||||
foreach (var added in changes.AddedSecurities)
|
||||
{
|
||||
// any option security additions for this algorithm should match the expected contracts
|
||||
if (added.Symbol.SecurityType == SecurityType.Option)
|
||||
{
|
||||
var expectedContract = _expectedContracts[_expectedContractIndex];
|
||||
if (added.Symbol != expectedContract)
|
||||
{
|
||||
throw new RegressionTestException($"Expected option contract {expectedContract.Value} to be added but received {added.Symbol}");
|
||||
}
|
||||
|
||||
_expectedContractIndex++;
|
||||
|
||||
// purchase for regression statistics
|
||||
MarketOrder(added.Symbol, 1);
|
||||
}
|
||||
|
||||
_expectedData.Add(added.Symbol);
|
||||
_expectedSecurities.Add(added.Symbol);
|
||||
}
|
||||
}
|
||||
|
||||
// security removal happens exactly once in this algorithm when the option chain is removed
|
||||
// and all child subscriptions (option contracts) should be removed at the same time
|
||||
if (changes.RemovedSecurities.Any(x => x.Symbol.SecurityType == SecurityType.Option))
|
||||
{
|
||||
// receive removed event next timestep at 11:31AM
|
||||
if (Time.TimeOfDay.Hours != 11 || Time.TimeOfDay.Minutes != 31)
|
||||
{
|
||||
throw new RegressionTestException($"Expected option contracts to be removed at 11:31AM, instead removed at: {Time}");
|
||||
}
|
||||
|
||||
if (changes.RemovedSecurities
|
||||
.Where(x => x.Symbol.SecurityType == SecurityType.Option)
|
||||
.ToHashSet(s => s.Symbol)
|
||||
.AreDifferent(_expectedContracts.ToHashSet()))
|
||||
{
|
||||
throw new RegressionTestException("Expected removed securities to equal expected contracts added");
|
||||
}
|
||||
}
|
||||
|
||||
if (Securities.ContainsKey(Underlying))
|
||||
{
|
||||
Log($"{Time:o}:: PRICE:: {Securities[Underlying].Price} CHANGES:: {changes}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 3502;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "6"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "98784"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "$6.00"},
|
||||
{"Estimated Strategy Capacity", "$4000.00"},
|
||||
{"Lowest Capacity Asset", "GOOCV 305RBQ2BZGA4M|GOOCV VP83T1ZUHROL"},
|
||||
{"Portfolio Turnover", "2.58%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "f418de0673fc166487daf80991dfe3a0"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Orders;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm making sure the securities cache is reset correctly once it's removed from the algorithm
|
||||
/// </summary>
|
||||
public class AddRemoveSecurityCacheRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07); //Set Start Date
|
||||
SetEndDate(2013, 10, 11); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
|
||||
AddEquity("SPY", Resolution.Minute, extendedMarketHours: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="slice">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings("SPY", 1);
|
||||
}
|
||||
|
||||
if (Time.Day == 11)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!ActiveSecurities.ContainsKey("AIG"))
|
||||
{
|
||||
var aig = AddEquity("AIG", Resolution.Minute);
|
||||
|
||||
var ticket = MarketOrder("AIG", 1);
|
||||
|
||||
if (ticket.Status != OrderStatus.Invalid || aig.HasData || aig.Price != 0)
|
||||
{
|
||||
throw new RegressionTestException("Expected order to always be invalid because there is no data yet!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveSecurity("AIG");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 15042;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "19"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "271.720%"},
|
||||
{"Drawdown", "2.500%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "101753.84"},
|
||||
{"Net Profit", "1.754%"},
|
||||
{"Sharpe Ratio", "11.954"},
|
||||
{"Sortino Ratio", "29.606"},
|
||||
{"Probabilistic Sharpe Ratio", "73.973%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.616"},
|
||||
{"Beta", "0.81"},
|
||||
{"Annual Standard Deviation", "0.185"},
|
||||
{"Annual Variance", "0.034"},
|
||||
{"Information Ratio", "3.961"},
|
||||
{"Tracking Error", "0.061"},
|
||||
{"Treynor Ratio", "2.737"},
|
||||
{"Total Fees", "$21.45"},
|
||||
{"Estimated Strategy Capacity", "$830000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "20.49%"},
|
||||
{"Drawdown Recovery", "2"},
|
||||
{"OrderListHash", "6ebe462373e2ecc22de8eb2fe114d704"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Data;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This algorithm demonstrates the runtime addition and removal of securities from your algorithm.
|
||||
/// With LEAN it is possible to add and remove securities after the initialization.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="assets" />
|
||||
/// <meta name="tag" content="regression test" />
|
||||
public class AddRemoveSecurityRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private DateTime lastAction;
|
||||
|
||||
private Symbol _spy = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
|
||||
private Symbol _aig = QuantConnect.Symbol.Create("AIG", SecurityType.Equity, Market.USA);
|
||||
private Symbol _bac = QuantConnect.Symbol.Create("BAC", SecurityType.Equity, Market.USA);
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07); //Set Start Date
|
||||
SetEndDate(2013, 10, 11); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
AddSecurity(SecurityType.Equity, "SPY");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (lastAction.Date == Time.Date) return;
|
||||
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings(_spy, 0.5);
|
||||
lastAction = Time;
|
||||
}
|
||||
if (Time.DayOfWeek == DayOfWeek.Tuesday)
|
||||
{
|
||||
AddSecurity(SecurityType.Equity, "AIG");
|
||||
AddSecurity(SecurityType.Equity, "BAC");
|
||||
lastAction = Time;
|
||||
}
|
||||
else if (Time.DayOfWeek == DayOfWeek.Wednesday)
|
||||
{
|
||||
SetHoldings(_aig, .25);
|
||||
SetHoldings(_bac, .25);
|
||||
lastAction = Time;
|
||||
}
|
||||
else if (Time.DayOfWeek == DayOfWeek.Thursday)
|
||||
{
|
||||
RemoveSecurity(_aig);
|
||||
RemoveSecurity(_bac);
|
||||
lastAction = Time;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Order events are triggered on order status changes. There are many order events including non-fill messages.
|
||||
/// </summary>
|
||||
/// <param name="orderEvent">OrderEvent object with details about the order status</param>
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
if (orderEvent.Status == OrderStatus.Submitted)
|
||||
{
|
||||
Debug(Time + ": Submitted: " + Transactions.GetOrderById(orderEvent.OrderId));
|
||||
}
|
||||
if (orderEvent.Status.IsFill())
|
||||
{
|
||||
Debug(Time + ": Filled: " + Transactions.GetOrderById(orderEvent.OrderId));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 7065;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "5"},
|
||||
{"Average Win", "0.46%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "296.356%"},
|
||||
{"Drawdown", "1.400%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "101776.32"},
|
||||
{"Net Profit", "1.776%"},
|
||||
{"Sharpe Ratio", "12.966"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "80.179%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.678"},
|
||||
{"Beta", "0.707"},
|
||||
{"Annual Standard Deviation", "0.16"},
|
||||
{"Annual Variance", "0.026"},
|
||||
{"Information Ratio", "1.378"},
|
||||
{"Tracking Error", "0.072"},
|
||||
{"Treynor Ratio", "2.935"},
|
||||
{"Total Fees", "$28.30"},
|
||||
{"Estimated Strategy Capacity", "$4700000.00"},
|
||||
{"Lowest Capacity Asset", "AIG R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "29.88%"},
|
||||
{"Drawdown Recovery", "2"},
|
||||
{"OrderListHash", "f04b3521256c7d6740966bc3df34e7b1"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Test algorithm using <see cref="QCAlgorithm.AddRiskManagement(IRiskManagementModel)"/>
|
||||
/// </summary>
|
||||
public class AddRiskManagementAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
UniverseSettings.Resolution = Resolution.Minute;
|
||||
|
||||
SetStartDate(2013, 10, 07); //Set Start Date
|
||||
SetEndDate(2013, 10, 11); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel(QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA)));
|
||||
SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, null));
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
AddRiskManagement(new MaximumDrawdownPercentPortfolio(0.02m));
|
||||
AddRiskManagement(new MaximumUnrealizedProfitPercentPerSecurity(0.01m));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 3943;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "3"},
|
||||
{"Average Win", "1.02%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "296.066%"},
|
||||
{"Drawdown", "2.200%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "101775.37"},
|
||||
{"Net Profit", "1.775%"},
|
||||
{"Sharpe Ratio", "9.34"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "68.153%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.106"},
|
||||
{"Beta", "1.021"},
|
||||
{"Annual Standard Deviation", "0.227"},
|
||||
{"Annual Variance", "0.052"},
|
||||
{"Information Ratio", "25.083"},
|
||||
{"Tracking Error", "0.006"},
|
||||
{"Treynor Ratio", "2.079"},
|
||||
{"Total Fees", "$10.33"},
|
||||
{"Estimated Strategy Capacity", "$38000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "59.74%"},
|
||||
{"Drawdown Recovery", "3"},
|
||||
{"OrderListHash", "5d7657ec9954875eca633bed711085d3"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm reproducing issue where underlying option contract would be removed with the first call
|
||||
/// too RemoveOptionContract
|
||||
/// </summary>
|
||||
public class AddTwoAndRemoveOneOptionContractRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _contract1;
|
||||
private Symbol _contract2;
|
||||
private bool _hasRemoved;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2014, 06, 06);
|
||||
SetEndDate(2014, 06, 06);
|
||||
|
||||
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
|
||||
UniverseSettings.MinimumTimeInUniverse = TimeSpan.Zero;
|
||||
|
||||
var aapl = QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA);
|
||||
|
||||
var contracts = OptionChain(aapl)
|
||||
.OrderBy(x => x.ID.StrikePrice)
|
||||
.Where(optionContract => optionContract.ID.OptionRight == OptionRight.Call
|
||||
&& optionContract.ID.OptionStyle == OptionStyle.American)
|
||||
.Take(2)
|
||||
.ToList();
|
||||
|
||||
_contract1 = contracts[0];
|
||||
_contract2 = contracts[1];
|
||||
AddOptionContract(_contract1);
|
||||
AddOptionContract(_contract2);
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (slice.HasData)
|
||||
{
|
||||
if (!_hasRemoved)
|
||||
{
|
||||
RemoveOptionContract(_contract1);
|
||||
_hasRemoved = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var subscriptions =
|
||||
SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs("AAPL");
|
||||
if (subscriptions.Count == 0)
|
||||
{
|
||||
throw new RegressionTestException("No configuration for underlying was found!");
|
||||
}
|
||||
|
||||
if (!Portfolio.Invested &&
|
||||
// This security will be liquidated due to impending split, let's not trade it again after the contract is removed.
|
||||
// Trying to trade it will make the security to be re-added
|
||||
Securities[_contract2].IsTradable)
|
||||
{
|
||||
Buy(_contract2, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_hasRemoved)
|
||||
{
|
||||
throw new RegressionTestException("Expect a single call to OnData where we removed the option and underlying");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 1579;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 1;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "99238"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "$2.00"},
|
||||
{"Estimated Strategy Capacity", "$6200000.00"},
|
||||
{"Lowest Capacity Asset", "AAPL VXBK4QA5IWKM|AAPL R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "90.27%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "a332b93ff5e2dfe89258c450a64c7125"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Test algorithm using <see cref="QCAlgorithm.AddUniverseSelection(IUniverseSelectionModel)"/>
|
||||
/// </summary>
|
||||
public class AddUniverseSelectionModelAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
// Set requested data resolution
|
||||
UniverseSettings.Resolution = Resolution.Daily;
|
||||
|
||||
SetStartDate(2013, 10, 08); //Set Start Date
|
||||
SetEndDate(2013, 10, 11); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
|
||||
// set algorithm framework models
|
||||
SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, null));
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel(QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA)));
|
||||
AddUniverseSelection(new ManualUniverseSelectionModel(QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA)));
|
||||
AddUniverseSelection(new ManualUniverseSelectionModel(
|
||||
QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA), // duplicate will be ignored
|
||||
QuantConnect.Symbol.Create("FB", SecurityType.Equity, Market.USA)));
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (UniverseManager.Count != 3)
|
||||
{
|
||||
throw new RegressionTestException("Unexpected universe count");
|
||||
}
|
||||
if (UniverseManager.ActiveSecurities.Count != 3
|
||||
|| UniverseManager.ActiveSecurities.Keys.All(symbol => symbol.Value != "SPY")
|
||||
|| UniverseManager.ActiveSecurities.Keys.All(symbol => symbol.Value != "AAPL")
|
||||
|| UniverseManager.ActiveSecurities.Keys.All(symbol => symbol.Value != "FB"))
|
||||
{
|
||||
throw new RegressionTestException("Unexpected active securities");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 50;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "6"},
|
||||
{"Average Win", "0.01%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "1296.838%"},
|
||||
{"Drawdown", "0.400%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "102684.23"},
|
||||
{"Net Profit", "2.684%"},
|
||||
{"Sharpe Ratio", "34.319"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-5.738"},
|
||||
{"Beta", "1.381"},
|
||||
{"Annual Standard Deviation", "0.246"},
|
||||
{"Annual Variance", "0.06"},
|
||||
{"Information Ratio", "-26.937"},
|
||||
{"Tracking Error", "0.068"},
|
||||
{"Treynor Ratio", "6.106"},
|
||||
{"Total Fees", "$18.61"},
|
||||
{"Estimated Strategy Capacity", "$980000000.00"},
|
||||
{"Lowest Capacity Asset", "FB V6OIPNZEM8V9"},
|
||||
{"Portfolio Turnover", "25.56%"},
|
||||
{"Drawdown Recovery", "1"},
|
||||
{"OrderListHash", "5ee20c8556d706ab0a63ae41b6579c62"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Test algorithm using <see cref="QCAlgorithm.AddUniverseSelection(IUniverseSelectionModel)"/>
|
||||
/// </summary>
|
||||
public class AddUniverseSelectionModelCoarseAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
// Set requested data resolution
|
||||
UniverseSettings.Resolution = Resolution.Daily;
|
||||
|
||||
// Order margin value has to have a minimum of 0.5% of Portfolio value, allows filtering out small trades and reduce fees.
|
||||
// Commented so regression algorithm is more sensitive
|
||||
//Settings.MinimumOrderMarginPortfolioPercentage = 0.005m;
|
||||
|
||||
SetStartDate(2014, 03, 24);
|
||||
SetEndDate(2014, 04, 07);
|
||||
SetCash(100000);
|
||||
|
||||
// set algorithm framework models
|
||||
SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, null));
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
SetUniverseSelection(new CoarseFundamentalUniverseSelectionModel(
|
||||
enumerable => enumerable
|
||||
.Select(fundamental => fundamental.Symbol)
|
||||
.Where(symbol => symbol.Value == "AAPL")));
|
||||
AddUniverseSelection(new CoarseFundamentalUniverseSelectionModel(
|
||||
enumerable => enumerable
|
||||
.Select(fundamental => fundamental.Symbol)
|
||||
.Where(symbol => symbol.Value == "SPY")));
|
||||
AddUniverseSelection(new CoarseFundamentalUniverseSelectionModel(
|
||||
enumerable => enumerable
|
||||
.Select(fundamental => fundamental.Symbol)
|
||||
.Where(symbol => symbol.Value == "FB")));
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (UniverseManager.Count != 3)
|
||||
{
|
||||
throw new RegressionTestException("Unexpected universe count");
|
||||
}
|
||||
if (UniverseManager.ActiveSecurities.Count != 3
|
||||
|| UniverseManager.ActiveSecurities.Keys.All(symbol => symbol.Value != "SPY")
|
||||
|| UniverseManager.ActiveSecurities.Keys.All(symbol => symbol.Value != "AAPL")
|
||||
|| UniverseManager.ActiveSecurities.Keys.All(symbol => symbol.Value != "FB"))
|
||||
{
|
||||
throw new RegressionTestException("Unexpected active securities");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 234015;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "21"},
|
||||
{"Average Win", "0.01%"},
|
||||
{"Average Loss", "-0.01%"},
|
||||
{"Compounding Annual Return", "-77.566%"},
|
||||
{"Drawdown", "6.000%"},
|
||||
{"Expectancy", "-0.811"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "94042.73"},
|
||||
{"Net Profit", "-5.957%"},
|
||||
{"Sharpe Ratio", "-3.345"},
|
||||
{"Sortino Ratio", "-3.766"},
|
||||
{"Probabilistic Sharpe Ratio", "4.444%"},
|
||||
{"Loss Rate", "89%"},
|
||||
{"Win Rate", "11%"},
|
||||
{"Profit-Loss Ratio", "0.70"},
|
||||
{"Alpha", "-0.519"},
|
||||
{"Beta", "1.491"},
|
||||
{"Annual Standard Deviation", "0.2"},
|
||||
{"Annual Variance", "0.04"},
|
||||
{"Information Ratio", "-3.878"},
|
||||
{"Tracking Error", "0.147"},
|
||||
{"Treynor Ratio", "-0.449"},
|
||||
{"Total Fees", "$29.11"},
|
||||
{"Estimated Strategy Capacity", "$680000000.00"},
|
||||
{"Lowest Capacity Asset", "AAPL R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "7.48%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "2c814c55e7d7c56482411c065b861b33"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Auxiliary;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm to test volume adjusted behavior
|
||||
/// </summary>
|
||||
public class AdjustedVolumeRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _aapl;
|
||||
private const string Ticker = "AAPL";
|
||||
private CorporateFactorProvider _factorFile;
|
||||
private readonly IEnumerator<decimal> _expectedAdjustedVolume = new List<decimal> { 6164842, 3044047, 3680347, 3468303, 2169943, 2652523,
|
||||
1499707, 1518215, 1655219, 1510487 }.GetEnumerator();
|
||||
private readonly IEnumerator<decimal> _expectedAdjustedAskSize = new List<decimal> { 215600, 5600, 25200, 8400, 5600, 5600, 2800,
|
||||
8400, 14000, 2800 }.GetEnumerator();
|
||||
private readonly IEnumerator<decimal> _expectedAdjustedBidSize = new List<decimal> { 2800, 11200, 2800, 2800, 2800, 5600, 11200,
|
||||
8400, 30800, 2800 }.GetEnumerator();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2014, 6, 5); //Set Start Date
|
||||
SetEndDate(2014, 6, 5); //Set End Date
|
||||
|
||||
UniverseSettings.DataNormalizationMode = DataNormalizationMode.SplitAdjusted;
|
||||
_aapl = AddEquity(Ticker, Resolution.Minute).Symbol;
|
||||
|
||||
var dataProvider =
|
||||
Composer.Instance.GetExportedValueByTypeName<IDataProvider>(Config.Get("data-provider",
|
||||
"DefaultDataProvider"));
|
||||
|
||||
var mapFileProvider = new LocalDiskMapFileProvider();
|
||||
mapFileProvider.Initialize(dataProvider);
|
||||
var factorFileProvider = new LocalDiskFactorFileProvider();
|
||||
factorFileProvider.Initialize(mapFileProvider, dataProvider);
|
||||
|
||||
|
||||
_factorFile = factorFileProvider.Get(_aapl) as CorporateFactorProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings(_aapl, 1);
|
||||
}
|
||||
|
||||
if (slice.Splits.ContainsKey(_aapl))
|
||||
{
|
||||
Log(slice.Splits[_aapl].ToString());
|
||||
}
|
||||
|
||||
if (slice.Bars.ContainsKey(_aapl))
|
||||
{
|
||||
var aaplData = slice.Bars[_aapl];
|
||||
|
||||
// Assert our volume matches what we expect
|
||||
if (_expectedAdjustedVolume.MoveNext() && _expectedAdjustedVolume.Current != aaplData.Volume)
|
||||
{
|
||||
// Our values don't match lets try and give a reason why
|
||||
var dayFactor = _factorFile.GetPriceScale(aaplData.Time, DataNormalizationMode.SplitAdjusted);
|
||||
var probableAdjustedVolume = aaplData.Volume / dayFactor;
|
||||
|
||||
if (_expectedAdjustedVolume.Current == probableAdjustedVolume)
|
||||
{
|
||||
throw new ArgumentException($"Volume was incorrect; but manually adjusted value is correct." +
|
||||
$" Adjustment by multiplying volume by {1 / dayFactor} is not occurring.");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Volume was incorrect; even when adjusted manually by" +
|
||||
$" multiplying volume by {1 / dayFactor}. Data may have changed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (slice.QuoteBars.ContainsKey(_aapl))
|
||||
{
|
||||
var aaplQuoteData = slice.QuoteBars[_aapl];
|
||||
|
||||
// Assert our askSize matches what we expect
|
||||
if (_expectedAdjustedAskSize.MoveNext() && _expectedAdjustedAskSize.Current != aaplQuoteData.LastAskSize)
|
||||
{
|
||||
// Our values don't match lets try and give a reason why
|
||||
var dayFactor = _factorFile.GetPriceScale(aaplQuoteData.Time, DataNormalizationMode.SplitAdjusted);
|
||||
var probableAdjustedAskSize = aaplQuoteData.LastAskSize / dayFactor;
|
||||
|
||||
if (_expectedAdjustedAskSize.Current == probableAdjustedAskSize)
|
||||
{
|
||||
throw new ArgumentException($"Ask size was incorrect; but manually adjusted value is correct." +
|
||||
$" Adjustment by multiplying size by {1 / dayFactor} is not occurring.");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Ask size was incorrect; even when adjusted manually by" +
|
||||
$" multiplying size by {1 / dayFactor}. Data may have changed.");
|
||||
}
|
||||
}
|
||||
|
||||
// Assert our bidSize matches what we expect
|
||||
if (_expectedAdjustedBidSize.MoveNext() && _expectedAdjustedBidSize.Current != aaplQuoteData.LastBidSize)
|
||||
{
|
||||
// Our values don't match lets try and give a reason why
|
||||
var dayFactor = _factorFile.GetPriceScale(aaplQuoteData.Time, DataNormalizationMode.SplitAdjusted);
|
||||
var probableAdjustedBidSize = aaplQuoteData.LastBidSize / dayFactor;
|
||||
|
||||
if (_expectedAdjustedBidSize.Current == probableAdjustedBidSize)
|
||||
{
|
||||
throw new ArgumentException($"Bid size was incorrect; but manually adjusted value is correct." +
|
||||
$" Adjustment by multiplying size by {1 / dayFactor} is not occurring.");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Bid size was incorrect; even when adjusted manually by" +
|
||||
$" multiplying size by {1 / dayFactor}. Data may have changed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 795;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100146.57"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "$21.60"},
|
||||
{"Estimated Strategy Capacity", "$42000000.00"},
|
||||
{"Lowest Capacity Asset", "AAPL R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "99.56%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "60f03c8c589a4f814dc4e8945df23207"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm asserting the correct values for the deployment target and algorithm mode.
|
||||
/// </summary>
|
||||
public class AlgorithmModeAndDeploymentTargetAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07);
|
||||
SetEndDate(2013, 10, 07);
|
||||
SetCash(100000);
|
||||
|
||||
Debug($"Algorithm Mode: {AlgorithmMode}. Is Live Mode: {LiveMode}. Deployment Target: {DeploymentTarget}.");
|
||||
|
||||
if (AlgorithmMode != AlgorithmMode.Backtesting)
|
||||
{
|
||||
throw new RegressionTestException($"Algorithm mode is not backtesting. Actual: {AlgorithmMode}");
|
||||
}
|
||||
|
||||
if (LiveMode)
|
||||
{
|
||||
throw new RegressionTestException("Algorithm should not be live");
|
||||
}
|
||||
|
||||
if (DeploymentTarget != DeploymentTarget.LocalPlatform)
|
||||
{
|
||||
throw new RegressionTestException($"Algorithm deployment target is not local. Actual{DeploymentTarget}");
|
||||
}
|
||||
|
||||
// For a live deployment these checks should pass:
|
||||
//if (AlgorithmMode != AlgorithmMode.Live) throw new RegressionTestException("Algorithm mode is not live");
|
||||
//if (!LiveMode) throw new RegressionTestException("Algorithm should be live");
|
||||
|
||||
// For a cloud deployment these checks should pass:
|
||||
//if (DeploymentTarget != DeploymentTarget.CloudPlatform) throw new RegressionTestException("Algorithm deployment target is not cloud");
|
||||
|
||||
Quit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Portfolio Turnover", "0%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Brokerages;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Shortable;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.IO;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests filtering in coarse selection by shortable quantity
|
||||
/// </summary>
|
||||
public class AllShortableSymbolsCoarseSelectionRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private static readonly DateTime _20140325 = new DateTime(2014, 3, 25);
|
||||
private static readonly DateTime _20140326 = new DateTime(2014, 3, 26);
|
||||
private static readonly DateTime _20140327 = new DateTime(2014, 3, 27);
|
||||
private static readonly DateTime _20140328 = new DateTime(2014, 3, 28);
|
||||
private static readonly DateTime _20140329 = new DateTime(2014, 3, 29);
|
||||
|
||||
private static readonly Symbol _aapl = QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA);
|
||||
private static readonly Symbol _bac = QuantConnect.Symbol.Create("BAC", SecurityType.Equity, Market.USA);
|
||||
private static readonly Symbol _gme = QuantConnect.Symbol.Create("GME", SecurityType.Equity, Market.USA);
|
||||
private static readonly Symbol _goog = QuantConnect.Symbol.Create("GOOG", SecurityType.Equity, Market.USA);
|
||||
private static readonly Symbol _qqq = QuantConnect.Symbol.Create("QQQ", SecurityType.Equity, Market.USA);
|
||||
private static readonly Symbol _spy = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
|
||||
private DateTime _lastTradeDate;
|
||||
|
||||
private static readonly Dictionary<DateTime, bool> _coarseSelected = new Dictionary<DateTime, bool>
|
||||
{
|
||||
{ _20140325, false },
|
||||
{ _20140326, false },
|
||||
{ _20140327, false },
|
||||
{ _20140328, false },
|
||||
};
|
||||
|
||||
private static readonly Dictionary<DateTime, Symbol[]> _expectedSymbols = new Dictionary<DateTime, Symbol[]>
|
||||
{
|
||||
{ _20140325, new[]
|
||||
{
|
||||
_bac,
|
||||
_qqq,
|
||||
_spy
|
||||
}
|
||||
},
|
||||
{ _20140326, new[]
|
||||
{
|
||||
_spy
|
||||
}
|
||||
},
|
||||
{ _20140327, new[]
|
||||
{
|
||||
_aapl,
|
||||
_bac,
|
||||
_gme,
|
||||
_qqq,
|
||||
_spy,
|
||||
}
|
||||
},
|
||||
{ _20140328, new[]
|
||||
{
|
||||
_goog
|
||||
}
|
||||
},
|
||||
{ _20140329, new Symbol[0] }
|
||||
};
|
||||
|
||||
private Security _security;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2014, 3, 25);
|
||||
SetEndDate(2014, 3, 29);
|
||||
SetCash(10000000);
|
||||
_security = AddEquity(_spy);
|
||||
_security.SetShortableProvider(new RegressionTestShortableProvider());
|
||||
|
||||
AddUniverse(CoarseSelection);
|
||||
UniverseSettings.Resolution = Resolution.Daily;
|
||||
|
||||
SetBrokerageModel(new AllShortableSymbolsRegressionAlgorithmBrokerageModel());
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (Time.Date == _lastTradeDate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var (symbol, security) in ActiveSecurities.Where(kvp => !kvp.Value.Invested).OrderBy(kvp => kvp.Key))
|
||||
{
|
||||
var shortableQuantity = security.ShortableProvider.ShortableQuantity(symbol, Time);
|
||||
if (shortableQuantity == null)
|
||||
{
|
||||
throw new RegressionTestException($"Expected {symbol} to be shortable on {Time:yyyy-MM-dd}");
|
||||
}
|
||||
|
||||
// Buy at least once into all Symbols. Since daily data will always use
|
||||
// MOO orders, it makes the testing of liquidating buying into Symbols difficult.
|
||||
MarketOrder(symbol, -(decimal)shortableQuantity);
|
||||
_lastTradeDate = Time.Date;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<Symbol> CoarseSelection(IEnumerable<CoarseFundamental> coarse)
|
||||
{
|
||||
var shortableSymbols = (_security.ShortableProvider as dynamic).AllShortableSymbols(Time);
|
||||
var selectedSymbols = coarse
|
||||
.Select(x => x.Symbol)
|
||||
.Where(s => shortableSymbols.ContainsKey(s) && shortableSymbols[s] >= 500)
|
||||
.OrderBy(s => s)
|
||||
.ToList();
|
||||
|
||||
var expectedMissing = 0;
|
||||
if (Time.Date == _20140327)
|
||||
{
|
||||
var gme = QuantConnect.Symbol.Create("GME", SecurityType.Equity, Market.USA);
|
||||
if (!shortableSymbols.ContainsKey(gme))
|
||||
{
|
||||
throw new RegressionTestException("Expected unmapped GME in shortable symbols list on 2014-03-27");
|
||||
}
|
||||
if (!coarse.Select(x => x.Symbol.Value).Contains("GME"))
|
||||
{
|
||||
throw new RegressionTestException("Expected mapped GME in coarse symbols on 2014-03-27");
|
||||
}
|
||||
|
||||
expectedMissing = 1;
|
||||
}
|
||||
|
||||
var missing = _expectedSymbols[Time.Date].Except(selectedSymbols).ToList();
|
||||
if (missing.Count != expectedMissing)
|
||||
{
|
||||
throw new RegressionTestException($"Expected Symbols selected on {Time.Date:yyyy-MM-dd} to match expected Symbols, but the following Symbols were missing: {string.Join(", ", missing.Select(s => s.ToString()))}");
|
||||
}
|
||||
|
||||
_coarseSelected[Time.Date] = true;
|
||||
return selectedSymbols;
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_coarseSelected.Values.All(x => x))
|
||||
{
|
||||
throw new AggregateException($"Expected coarse selection on all dates, but didn't run on: {string.Join(", ", _coarseSelected.Where(kvp => !kvp.Value).Select(kvp => kvp.Key.ToStringInvariant("yyyy-MM-dd")))}");
|
||||
}
|
||||
}
|
||||
|
||||
private class AllShortableSymbolsRegressionAlgorithmBrokerageModel : DefaultBrokerageModel
|
||||
{
|
||||
public AllShortableSymbolsRegressionAlgorithmBrokerageModel() : base()
|
||||
{
|
||||
}
|
||||
public override IShortableProvider GetShortableProvider(Security security)
|
||||
{
|
||||
return new RegressionTestShortableProvider();
|
||||
}
|
||||
}
|
||||
|
||||
private class RegressionTestShortableProvider : LocalDiskShortableProvider
|
||||
{
|
||||
public RegressionTestShortableProvider() : base("testbrokerage")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all shortable Symbols, including the quantity shortable as a Dictionary.
|
||||
/// </summary>
|
||||
/// <param name="localTime">The algorithm's local time</param>
|
||||
/// <returns>Symbol/quantity shortable as a Dictionary. Returns null if no entry data exists for this date or brokerage</returns>
|
||||
public Dictionary<Symbol, long> AllShortableSymbols(DateTime localTime)
|
||||
{
|
||||
var shortableDataDirectory = Path.Combine(Globals.DataFolder, SecurityType.Equity.SecurityTypeToLower(), Market.USA, "shortable", Brokerage);
|
||||
var allSymbols = new Dictionary<Symbol, long>();
|
||||
|
||||
// Check backwards up to one week to see if we can source a previous file.
|
||||
// If not, then we return a list of all Symbols with quantity set to zero.
|
||||
var i = 0;
|
||||
while (i <= 7)
|
||||
{
|
||||
var shortableListFile = Path.Combine(shortableDataDirectory, "dates", $"{localTime.AddDays(-i):yyyyMMdd}.csv");
|
||||
|
||||
foreach (var line in DataProvider.ReadLines(shortableListFile))
|
||||
{
|
||||
var csv = line.Split(',');
|
||||
var ticker = csv[0];
|
||||
|
||||
var symbol = new Symbol(
|
||||
SecurityIdentifier.GenerateEquity(ticker, QuantConnect.Market.USA,
|
||||
mappingResolveDate: localTime), ticker);
|
||||
var quantity = Parse.Long(csv[1]);
|
||||
|
||||
allSymbols[symbol] = quantity;
|
||||
}
|
||||
|
||||
if (allSymbols.Count > 0)
|
||||
{
|
||||
return allSymbols;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// Return our empty dictionary if we did not find a file to extract
|
||||
return allSymbols;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 36573;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "8"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "11.027%"},
|
||||
{"Drawdown", "0.000%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "10000000"},
|
||||
{"End Equity", "10011469.88"},
|
||||
{"Net Profit", "0.115%"},
|
||||
{"Sharpe Ratio", "11.963"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.07"},
|
||||
{"Beta", "-0.077"},
|
||||
{"Annual Standard Deviation", "0.008"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "3.876"},
|
||||
{"Tracking Error", "0.105"},
|
||||
{"Treynor Ratio", "-1.215"},
|
||||
{"Total Fees", "$282.50"},
|
||||
{"Estimated Strategy Capacity", "$61000000000.00"},
|
||||
{"Lowest Capacity Asset", "NB R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "3.62%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "ce85d312f2e4e97c605d13dda0aab8fd"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using Accord.Math;
|
||||
using Accord.Statistics;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Consolidators;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// Energy prices, especially Oil and Natural Gas, are in general fairly correlated,
|
||||
/// meaning they typically move in the same direction as an overall trend.This Alpha
|
||||
/// uses this idea and implements an Alpha Model that takes Natural Gas ETF price
|
||||
/// movements as a leading indicator for Crude Oil ETF price movements.We take the
|
||||
/// Natural Gas/Crude Oil ETF pair with the highest historical price correlation and
|
||||
/// then create insights for Crude Oil depending on whether or not the Natural Gas ETF price change
|
||||
/// is above/below a certain threshold that we set (arbitrarily).
|
||||
///
|
||||
/// This alpha is part of the Benchmark Alpha Series created by QuantConnect which are open
|
||||
/// sourced so the community and client funds can see an example of an alpha.
|
||||
///</summary>
|
||||
public class GasAndCrudeOilEnergyCorrelationAlpha : QCAlgorithm
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2018, 1, 1);
|
||||
SetCash(100000);
|
||||
|
||||
// Set zero transaction fees
|
||||
SetSecurityInitializer(security => security.FeeModel = new ConstantFeeModel(0));
|
||||
|
||||
Func<string, Symbol> ToSymbol = x => QuantConnect.Symbol.Create(x, SecurityType.Equity, Market.USA);
|
||||
var naturalGas = new[] { "UNG", "BOIL", "FCG" }.Select(ToSymbol).ToArray();
|
||||
var crudeOil = new[] { "USO", "UCO", "DBO" }.Select(ToSymbol).ToArray();
|
||||
|
||||
// Manually curated universe
|
||||
UniverseSettings.Resolution = Resolution.Minute;
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel(naturalGas.Concat(crudeOil)));
|
||||
|
||||
// Use PairsAlphaModel to establish insights
|
||||
SetAlpha(new PairsAlphaModel(naturalGas, crudeOil, 90, Resolution.Minute));
|
||||
|
||||
// Equally weigh securities in portfolio, based on insights
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
|
||||
// Set Custom Execution Model
|
||||
SetExecution(new CustomExecutionModel());
|
||||
|
||||
// Set Null Risk Management Model
|
||||
SetRiskManagement(new NullRiskManagementModel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This Alpha model assumes that the ETF for natural gas is a good leading-indicator
|
||||
/// of the price of the crude oil ETF.The model will take in arguments for a threshold
|
||||
/// at which the model triggers an insight, the length of the look-back period for evaluating
|
||||
/// rate-of-change of UNG prices, and the duration of the insight
|
||||
/// </summary>
|
||||
private class PairsAlphaModel : AlphaModel
|
||||
{
|
||||
private readonly Symbol[] _leading;
|
||||
private readonly Symbol[] _following;
|
||||
private readonly int _historyDays;
|
||||
private readonly int _lookback;
|
||||
private readonly decimal _differenceTrigger = 0.75m;
|
||||
private readonly Resolution _resolution;
|
||||
private readonly TimeSpan _predictionInterval;
|
||||
private readonly Dictionary<Symbol, SymbolData> _symbolDataBySymbol;
|
||||
private Tuple<SymbolData, SymbolData> _pair;
|
||||
|
||||
private DateTime _nextUpdate;
|
||||
|
||||
public PairsAlphaModel(
|
||||
Symbol[] naturalGas,
|
||||
Symbol[] crudeOil,
|
||||
int historyDays = 90,
|
||||
Resolution resolution = Resolution.Hour,
|
||||
int lookback = 5,
|
||||
decimal differenceTrigger = 0.75m)
|
||||
{
|
||||
_leading = naturalGas;
|
||||
_following = crudeOil;
|
||||
_historyDays = historyDays;
|
||||
_resolution = resolution;
|
||||
_lookback = lookback;
|
||||
_differenceTrigger = differenceTrigger;
|
||||
_symbolDataBySymbol = new Dictionary<Symbol, SymbolData>();
|
||||
_predictionInterval = resolution.ToTimeSpan().Multiply(lookback);
|
||||
}
|
||||
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
if (_nextUpdate == DateTime.MinValue || algorithm.Time > _nextUpdate)
|
||||
{
|
||||
CorrelationPairsSelection();
|
||||
_nextUpdate = algorithm.Time.AddDays(30);
|
||||
}
|
||||
|
||||
var magnitude = (double)Math.Round(_pair.Item1.Return / 100, 6);
|
||||
|
||||
if (_pair.Item1.Return > _differenceTrigger)
|
||||
{
|
||||
yield return Insight.Price(_pair.Item2.Symbol, _predictionInterval, InsightDirection.Up, magnitude);
|
||||
}
|
||||
if (_pair.Item1.Return < -_differenceTrigger)
|
||||
{
|
||||
yield return Insight.Price(_pair.Item2.Symbol, _predictionInterval, InsightDirection.Down, magnitude);
|
||||
}
|
||||
}
|
||||
|
||||
public void CorrelationPairsSelection()
|
||||
{
|
||||
var maxCorrelation = -1.0;
|
||||
var matrix = new double[_historyDays, _following.Length + 1];
|
||||
|
||||
// Get returns for each oil ETF
|
||||
for (var j = 0; j < _following.Length; j++)
|
||||
{
|
||||
SymbolData symbolData2;
|
||||
if (_symbolDataBySymbol.TryGetValue(_following[j], out symbolData2))
|
||||
{
|
||||
var dailyReturn2 = symbolData2.DailyReturnArray;
|
||||
for (var i = 0; i < _historyDays; i++)
|
||||
{
|
||||
matrix[i, j + 1] = symbolData2.DailyReturnArray[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns for each natural gas ETF
|
||||
for (var j = 0; j < _leading.Length; j++)
|
||||
{
|
||||
SymbolData symbolData1;
|
||||
if (_symbolDataBySymbol.TryGetValue(_leading[j], out symbolData1))
|
||||
{
|
||||
for (var i = 0; i < _historyDays; i++)
|
||||
{
|
||||
matrix[i, 0] = symbolData1.DailyReturnArray[i];
|
||||
}
|
||||
|
||||
var column = matrix.Correlation().GetColumn(0);
|
||||
var correlation = column.RemoveAt(0).Max();
|
||||
|
||||
// Calculate the pair with highest historical correlation
|
||||
if (correlation > maxCorrelation)
|
||||
{
|
||||
var maxIndex = column.IndexOf(correlation) - 1;
|
||||
if (maxIndex < 0) continue;
|
||||
var symbolData2 = _symbolDataBySymbol[_following[maxIndex]];
|
||||
_pair = Tuple.Create(symbolData1, symbolData2);
|
||||
maxCorrelation = correlation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
foreach (var removed in changes.RemovedSecurities)
|
||||
{
|
||||
if (_symbolDataBySymbol.ContainsKey(removed.Symbol))
|
||||
{
|
||||
_symbolDataBySymbol[removed.Symbol].RemoveConsolidators(algorithm);
|
||||
_symbolDataBySymbol.Remove(removed.Symbol);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize data for added securities
|
||||
var symbols = changes.AddedSecurities.Select(x => x.Symbol);
|
||||
var dailyHistory = algorithm.History(symbols, _historyDays + 1, Resolution.Daily);
|
||||
if (symbols.Count() > 0 && dailyHistory.Count() == 0)
|
||||
{
|
||||
algorithm.Debug($"{algorithm.Time} :: No daily data");
|
||||
}
|
||||
|
||||
dailyHistory.PushThrough(bar =>
|
||||
{
|
||||
SymbolData symbolData;
|
||||
if (!_symbolDataBySymbol.TryGetValue(bar.Symbol, out symbolData))
|
||||
{
|
||||
symbolData = new SymbolData(algorithm, bar.Symbol, _historyDays, _lookback, _resolution);
|
||||
_symbolDataBySymbol.Add(bar.Symbol, symbolData);
|
||||
}
|
||||
// Update daily rate of change indicator
|
||||
symbolData.UpdateDailyRateOfChange(bar);
|
||||
});
|
||||
|
||||
algorithm.History(symbols, _lookback, _resolution).PushThrough(bar =>
|
||||
{
|
||||
// Update rate of change indicator with given resolution
|
||||
if (_symbolDataBySymbol.ContainsKey(bar.Symbol))
|
||||
{
|
||||
_symbolDataBySymbol[bar.Symbol].UpdateRateOfChange(bar);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains data specific to a symbol required by this model
|
||||
/// </summary>
|
||||
private class SymbolData
|
||||
{
|
||||
private readonly RateOfChangePercent _dailyReturn;
|
||||
private readonly IDataConsolidator _dailyConsolidator;
|
||||
private readonly RollingWindow<IndicatorDataPoint> _dailyReturnHistory;
|
||||
private readonly IDataConsolidator _consolidator;
|
||||
|
||||
public Symbol Symbol { get; }
|
||||
|
||||
public RateOfChangePercent Return { get; }
|
||||
|
||||
public double[] DailyReturnArray => _dailyReturnHistory
|
||||
.OrderBy(x => x.EndTime)
|
||||
.Select(x => (double)x.Value).ToArray();
|
||||
|
||||
public SymbolData(QCAlgorithm algorithm, Symbol symbol, int dailyLookback, int lookback, Resolution resolution)
|
||||
{
|
||||
Symbol = symbol;
|
||||
|
||||
_dailyReturn = new RateOfChangePercent($"{symbol}.DailyROCP(1)", 1);
|
||||
_dailyConsolidator = algorithm.ResolveConsolidator(symbol, Resolution.Daily);
|
||||
_dailyReturnHistory = new RollingWindow<IndicatorDataPoint>(dailyLookback);
|
||||
_dailyReturn.Updated += (s, e) => _dailyReturnHistory.Add(e);
|
||||
algorithm.RegisterIndicator(symbol, _dailyReturn, _dailyConsolidator);
|
||||
|
||||
Return = new RateOfChangePercent($"{symbol}.ROCP({lookback})", lookback);
|
||||
_consolidator = algorithm.ResolveConsolidator(symbol, resolution);
|
||||
algorithm.RegisterIndicator(symbol, Return, _consolidator);
|
||||
}
|
||||
|
||||
public void RemoveConsolidators(QCAlgorithm algorithm)
|
||||
{
|
||||
algorithm.SubscriptionManager.RemoveConsolidator(Symbol, _consolidator);
|
||||
algorithm.SubscriptionManager.RemoveConsolidator(Symbol, _dailyConsolidator);
|
||||
}
|
||||
|
||||
public void UpdateRateOfChange(BaseData data)
|
||||
{
|
||||
Return.Update(data.EndTime, data.Value);
|
||||
}
|
||||
|
||||
internal void UpdateDailyRateOfChange(BaseData data)
|
||||
{
|
||||
_dailyReturn.Update(data.EndTime, data.Value);
|
||||
}
|
||||
|
||||
public override string ToString() => Return.ToDetailedString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides an implementation of IExecutionModel that immediately submits market orders to achieve the desired portfolio targets
|
||||
/// </summary>
|
||||
private class CustomExecutionModel : ExecutionModel
|
||||
{
|
||||
private readonly PortfolioTargetCollection _targetsCollection = new PortfolioTargetCollection();
|
||||
private Symbol _previousSymbol;
|
||||
|
||||
/// <summary>
|
||||
/// Immediately submits orders for the specified portfolio targets.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="targets">The portfolio targets to be ordered</param>
|
||||
public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
|
||||
{
|
||||
_targetsCollection.AddRange(targets);
|
||||
|
||||
foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm))
|
||||
{
|
||||
var openQuantity = algorithm.Transactions.GetOpenOrders(target.Symbol)
|
||||
.Sum(x => x.Quantity);
|
||||
var existing = algorithm.Securities[target.Symbol].Holdings.Quantity + openQuantity;
|
||||
var quantity = target.Quantity - existing;
|
||||
|
||||
// Liquidate positions in Crude Oil ETF that is no longer part of the highest-correlation pair
|
||||
if (_previousSymbol != null && target.Symbol != _previousSymbol)
|
||||
{
|
||||
algorithm.Liquidate(_previousSymbol);
|
||||
}
|
||||
if (quantity != 0)
|
||||
{
|
||||
algorithm.MarketOrder(target.Symbol, quantity);
|
||||
_previousSymbol = target.Symbol;
|
||||
}
|
||||
}
|
||||
_targetsCollection.ClearFulfilled(algorithm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// Equity indices exhibit mean reversion in daily returns. The Internal Bar Strength indicator (IBS),
|
||||
/// which relates the closing price of a security to its daily range can be used to identify overbought
|
||||
/// and oversold securities.
|
||||
///
|
||||
/// This alpha ranks 33 global equity ETFs on its IBS value the previous day and predicts for the following day
|
||||
/// that the ETF with the highest IBS value will decrease in price, and the ETF with the lowest IBS value
|
||||
/// will increase in price.
|
||||
///
|
||||
/// Source: Kakushadze, Zura, and Juan Andrés Serur. “4. Exchange-Traded Funds (ETFs).” 151 Trading Strategies, Palgrave Macmillan, 2018, pp. 90–91.
|
||||
///
|
||||
/// This alpha is part of the Benchmark Alpha Series created by QuantConnect which are open sourced so the community and client funds can see an example of an alpha.
|
||||
///</summary>
|
||||
public class GlobalEquityMeanReversionIBSAlpha : QCAlgorithm
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2018, 1, 1);
|
||||
SetCash(100000);
|
||||
|
||||
// Set zero transaction fees
|
||||
SetSecurityInitializer(security => security.FeeModel = new ConstantFeeModel(0));
|
||||
|
||||
// Global Equity ETF tickers
|
||||
var symbols = new[] {
|
||||
"ECH", "EEM", "EFA", "EPHE", "EPP", "EWA", "EWC", "EWG",
|
||||
"EWH", "EWI", "EWJ", "EWL", "EWM", "EWM", "EWO", "EWP",
|
||||
"EWQ", "EWS", "EWT", "EWU", "EWY", "EWZ", "EZA", "FXI",
|
||||
"GXG", "IDX", "ILF", "EWM", "QQQ", "RSX", "SPY", "THD"}
|
||||
.Select(x => QuantConnect.Symbol.Create(x, SecurityType.Equity, Market.USA));
|
||||
|
||||
// Manually curated universe
|
||||
UniverseSettings.Resolution = Resolution.Daily;
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel(symbols));
|
||||
|
||||
// Use MeanReversionIBSAlphaModel to establish insights
|
||||
SetAlpha(new MeanReversionIBSAlphaModel());
|
||||
|
||||
// Equally weigh securities in portfolio, based on insights
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
|
||||
// Set Immediate Execution Model
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
// Set Null Risk Management Model
|
||||
SetRiskManagement(new NullRiskManagementModel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses ranking of Internal Bar Strength (IBS) to create direction prediction for insights
|
||||
/// </summary>
|
||||
private class MeanReversionIBSAlphaModel : AlphaModel
|
||||
{
|
||||
private readonly int _numberOfStocks;
|
||||
private readonly TimeSpan _predictionInterval;
|
||||
|
||||
public MeanReversionIBSAlphaModel(
|
||||
int lookback = 1,
|
||||
int numberOfStocks = 2,
|
||||
Resolution resolution = Resolution.Daily)
|
||||
{
|
||||
_numberOfStocks = numberOfStocks;
|
||||
_predictionInterval = resolution.ToTimeSpan().Multiply(lookback);
|
||||
}
|
||||
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
var symbolsIBS = new Dictionary<Symbol, decimal>();
|
||||
var returns = new Dictionary<Symbol, decimal>();
|
||||
|
||||
foreach (var kvp in algorithm.ActiveSecurities)
|
||||
{
|
||||
var security = kvp.Value;
|
||||
if (security.HasData)
|
||||
{
|
||||
var high = security.High;
|
||||
var low = security.Low;
|
||||
var hilo = high - low;
|
||||
|
||||
// Do not consider symbol with zero open and avoid division by zero
|
||||
if (security.Open * hilo != 0)
|
||||
{
|
||||
// Internal bar strength (IBS)
|
||||
symbolsIBS.Add(security.Symbol, (security.Close - low) / hilo);
|
||||
returns.Add(security.Symbol, security.Close / security.Open - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var insights = new List<Insight>();
|
||||
|
||||
// Number of stocks cannot be higher than half of symbolsIBS length
|
||||
var numberOfStocks = Math.Min((int)(symbolsIBS.Count / 2.0), _numberOfStocks);
|
||||
if (numberOfStocks == 0)
|
||||
{
|
||||
return insights;
|
||||
}
|
||||
|
||||
// Rank securities with the highest IBS value
|
||||
var ordered = from entry in symbolsIBS
|
||||
orderby Math.Round(entry.Value, 6) descending, entry.Key
|
||||
select entry;
|
||||
var highIBS = ordered.Take(numberOfStocks); // Get highest IBS
|
||||
var lowIBS = ordered.Reverse().Take(numberOfStocks); // Get lowest IBS
|
||||
|
||||
// Emit "down" insight for the securities with the highest IBS value
|
||||
foreach (var kvp in highIBS)
|
||||
{
|
||||
insights.Add(Insight.Price(kvp.Key, _predictionInterval, InsightDirection.Down, Math.Abs((double)returns[kvp.Key])));
|
||||
}
|
||||
|
||||
// Emit "up" insight for the securities with the highest IBS value
|
||||
foreach (var kvp in lowIBS)
|
||||
{
|
||||
insights.Add(Insight.Price(kvp.Key, _predictionInterval, InsightDirection.Up, Math.Abs((double)returns[kvp.Key])));
|
||||
}
|
||||
|
||||
return insights;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Consolidators;
|
||||
using QuantConnect.Data.Fundamental;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// This alpha picks stocks according to Joel Greenblatt's Magic Formula.
|
||||
/// First, each stock is ranked depending on the relative value of the ratio EV/EBITDA. For example, a stock
|
||||
/// that has the lowest EV/EBITDA ratio in the security universe receives a score of one while a stock that has
|
||||
/// the tenth lowest EV/EBITDA score would be assigned 10 points.
|
||||
///
|
||||
/// Then, each stock is ranked and given a score for the second valuation ratio, Return on Capital (ROC).
|
||||
/// Similarly, a stock that has the highest ROC value in the universe gets one score point.
|
||||
/// The stocks that receive the lowest combined score are chosen for insights.
|
||||
///
|
||||
/// Source: Greenblatt, J. (2010) The Little Book That Beats the Market
|
||||
///
|
||||
/// This alpha is part of the Benchmark Alpha Series created by QuantConnect which are open
|
||||
/// sourced so the community and client funds can see an example of an alpha.
|
||||
///</summary>
|
||||
public class GreenblattMagicFormulaAlpha : QCAlgorithm
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2018, 1, 1);
|
||||
SetCash(100000);
|
||||
|
||||
// Set zero transaction fees
|
||||
SetSecurityInitializer(security => security.FeeModel = new ConstantFeeModel(0));
|
||||
|
||||
// Select stocks using MagicFormulaUniverseSelectionModel
|
||||
SetUniverseSelection(new GreenBlattMagicFormulaUniverseSelectionModel());
|
||||
|
||||
// Use RateOfChangeAlphaModel to establish insights
|
||||
SetAlpha(new RateOfChangeAlphaModel());
|
||||
|
||||
// Equally weigh securities in portfolio, based on insights
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
|
||||
// Set Immediate Execution Model
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
// Set Null Risk Management Model
|
||||
SetRiskManagement(new NullRiskManagementModel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses Rate of Change (ROC) to create magnitude prediction for insights.
|
||||
/// </summary>
|
||||
private class RateOfChangeAlphaModel : AlphaModel
|
||||
{
|
||||
private readonly int _lookback;
|
||||
private readonly Resolution _resolution;
|
||||
private readonly TimeSpan _predictionInterval;
|
||||
private readonly Dictionary<Symbol, SymbolData> _symbolDataBySymbol;
|
||||
|
||||
public RateOfChangeAlphaModel(
|
||||
int lookback = 1,
|
||||
Resolution resolution = Resolution.Daily)
|
||||
{
|
||||
_lookback = lookback;
|
||||
_resolution = resolution;
|
||||
_predictionInterval = resolution.ToTimeSpan().Multiply(lookback);
|
||||
_symbolDataBySymbol = new Dictionary<Symbol, SymbolData>();
|
||||
}
|
||||
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
var insights = new List<Insight>();
|
||||
|
||||
foreach (var kvp in _symbolDataBySymbol)
|
||||
{
|
||||
var symbolData = kvp.Value;
|
||||
if (symbolData.CanEmit)
|
||||
{
|
||||
var magnitude = Convert.ToDouble(Math.Abs(symbolData.Return));
|
||||
insights.Add(Insight.Price(kvp.Key, _predictionInterval, InsightDirection.Up, magnitude));
|
||||
}
|
||||
}
|
||||
|
||||
return insights;
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
// Clean up data for removed securities
|
||||
foreach (var removed in changes.RemovedSecurities)
|
||||
{
|
||||
SymbolData symbolData;
|
||||
if (_symbolDataBySymbol.TryGetValue(removed.Symbol, out symbolData))
|
||||
{
|
||||
symbolData.RemoveConsolidators(algorithm);
|
||||
_symbolDataBySymbol.Remove(removed.Symbol);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize data for added securities
|
||||
var symbols = changes.AddedSecurities.Select(x => x.Symbol);
|
||||
var history = algorithm.History(symbols, _lookback, _resolution);
|
||||
if (symbols.Count() == 0 && history.Count() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
history.PushThrough(bar =>
|
||||
{
|
||||
SymbolData symbolData;
|
||||
if (!_symbolDataBySymbol.TryGetValue(bar.Symbol, out symbolData))
|
||||
{
|
||||
symbolData = new SymbolData(algorithm, bar.Symbol, _lookback, _resolution);
|
||||
_symbolDataBySymbol[bar.Symbol] = symbolData;
|
||||
}
|
||||
symbolData.WarmUpIndicators(bar);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains data specific to a symbol required by this model
|
||||
/// </summary>
|
||||
private class SymbolData
|
||||
{
|
||||
private readonly Symbol _symbol;
|
||||
private readonly IDataConsolidator _consolidator;
|
||||
private long _previous = 0;
|
||||
|
||||
public RateOfChange Return { get; }
|
||||
|
||||
public bool CanEmit
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_previous == Return.Samples)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_previous = Return.Samples;
|
||||
return Return.IsReady;
|
||||
}
|
||||
}
|
||||
|
||||
public SymbolData(QCAlgorithm algorithm, Symbol symbol, int lookback, Resolution resolution)
|
||||
{
|
||||
_symbol = symbol;
|
||||
Return = new RateOfChange($"{symbol}.ROC({lookback})", lookback);
|
||||
_consolidator = algorithm.ResolveConsolidator(symbol, resolution);
|
||||
algorithm.RegisterIndicator(symbol, Return, _consolidator);
|
||||
}
|
||||
|
||||
internal void RemoveConsolidators(QCAlgorithm algorithm)
|
||||
{
|
||||
algorithm.SubscriptionManager.RemoveConsolidator(_symbol, _consolidator);
|
||||
}
|
||||
|
||||
internal void WarmUpIndicators(BaseData bar)
|
||||
{
|
||||
Return.Update(bar.EndTime, bar.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines a universe according to Joel Greenblatt's Magic Formula, as a universe selection model for the framework algorithm.
|
||||
/// From the universe QC500, stocks are ranked using the valuation ratios, Enterprise Value to EBITDA(EV/EBITDA) and Return on Assets(ROA).
|
||||
/// </summary>
|
||||
private class GreenBlattMagicFormulaUniverseSelectionModel : FundamentalUniverseSelectionModel
|
||||
{
|
||||
private const int _numberOfSymbolsCoarse = 500;
|
||||
private const int _numberOfSymbolsFine = 20;
|
||||
private const int _numberOfSymbolsInPortfolio = 10;
|
||||
private int _lastMonth = -1;
|
||||
private Dictionary<Symbol, double> _dollarVolumeBySymbol;
|
||||
|
||||
public GreenBlattMagicFormulaUniverseSelectionModel() : base(true)
|
||||
{
|
||||
_dollarVolumeBySymbol = new ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs coarse selection for constituents.
|
||||
/// The stocks must have fundamental data
|
||||
/// The stock must have positive previous-day close price
|
||||
/// The stock must have positive volume on the previous trading day
|
||||
/// </summary>
|
||||
public override IEnumerable<Symbol> SelectCoarse(QCAlgorithm algorithm, IEnumerable<CoarseFundamental> coarse)
|
||||
{
|
||||
if (algorithm.Time.Month == _lastMonth)
|
||||
{
|
||||
return algorithm.Universe.Unchanged;
|
||||
}
|
||||
_lastMonth = algorithm.Time.Month;
|
||||
|
||||
_dollarVolumeBySymbol = (
|
||||
from cf in coarse
|
||||
where cf.HasFundamentalData
|
||||
orderby cf.DollarVolume descending
|
||||
select new { cf.Symbol, cf.DollarVolume }
|
||||
)
|
||||
.Take(_numberOfSymbolsCoarse)
|
||||
.ToDictionary(x => x.Symbol, x => x.DollarVolume);
|
||||
|
||||
return _dollarVolumeBySymbol.Keys;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// QC500: Performs fine selection for the coarse selection constituents
|
||||
/// The company's headquarter must in the U.S.
|
||||
/// The stock must be traded on either the NYSE or NASDAQ
|
||||
/// At least half a year since its initial public offering
|
||||
/// The stock's market cap must be greater than 500 million
|
||||
///
|
||||
/// Magic Formula: Rank stocks by Enterprise Value to EBITDA(EV/EBITDA)
|
||||
/// Rank subset of previously ranked stocks(EV/EBITDA), using the valuation ratio Return on Assets(ROA)
|
||||
/// </summary>
|
||||
public override IEnumerable<Symbol> SelectFine(QCAlgorithm algorithm, IEnumerable<FineFundamental> fine)
|
||||
{
|
||||
var filteredFine =
|
||||
from x in fine
|
||||
where x.CompanyReference.CountryId == "USA"
|
||||
where x.CompanyReference.PrimaryExchangeID == "NYS" || x.CompanyReference.PrimaryExchangeID == "NAS"
|
||||
where (algorithm.Time - x.SecurityReference.IPODate).TotalDays > 180
|
||||
where x.EarningReports.BasicAverageShares.ThreeMonths * x.EarningReports.BasicEPS.TwelveMonths * x.ValuationRatios.PERatio > 5e8
|
||||
select x;
|
||||
|
||||
double count = filteredFine.Count();
|
||||
if (count == 0)
|
||||
{
|
||||
return Enumerable.Empty<Symbol>();
|
||||
}
|
||||
|
||||
var percent = _numberOfSymbolsFine / count;
|
||||
|
||||
// Select stocks with top dollar volume in every single sector
|
||||
var myDict = (
|
||||
from x in filteredFine
|
||||
group x by x.CompanyReference.IndustryTemplateCode into g
|
||||
let y = (
|
||||
from item in g
|
||||
orderby _dollarVolumeBySymbol[item.Symbol] descending
|
||||
select item
|
||||
)
|
||||
let c = (int)Math.Ceiling(y.Count() * percent)
|
||||
select new { g.Key, Value = y.Take(c) }
|
||||
)
|
||||
.ToDictionary(x => x.Key, x => x.Value);
|
||||
|
||||
// Stocks in QC500 universe
|
||||
var topFine = myDict.Values.SelectMany(x => x);
|
||||
|
||||
// Magic Formula:
|
||||
// Rank stocks by Enterprise Value to EBITDA (EV/EBITDA)
|
||||
// Rank subset of previously ranked stocks (EV/EBITDA), using the valuation ratio Return on Assets (ROA)
|
||||
return topFine
|
||||
// Sort stocks in the security universe of QC500 based on Enterprise Value to EBITDA valuation ratio
|
||||
.OrderByDescending(x => x.ValuationRatios.EVToEBITDA)
|
||||
.Take(_numberOfSymbolsFine)
|
||||
// sort subset of stocks that have been sorted by Enterprise Value to EBITDA, based on the valuation ratio Return on Assets (ROA)
|
||||
.OrderByDescending(x => x.ValuationRatios.ForwardROA)
|
||||
.Take(_numberOfSymbolsInPortfolio)
|
||||
.Select(x => x.Symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// Reversal strategy that goes long when price crosses below SMA and Short when price crosses above SMA.
|
||||
/// The trading strategy is implemented only between 10AM - 3PM (NY time). Research suggests this is due to
|
||||
/// institutional trades during market hours which need hedging with the USD. Source paper:
|
||||
/// LeBaron, Zhao: Intraday Foreign Exchange Reversals
|
||||
/// http://people.brandeis.edu/~blebaron/wps/fxnyc.pdf
|
||||
/// http://www.fma.org/Reno/Papers/ForeignExchangeReversalsinNewYorkTime.pdf
|
||||
///
|
||||
/// This alpha is part of the Benchmark Alpha Series created by QuantConnect which are open sourced so the community and client funds can see an example of an alpha.
|
||||
///</summary>
|
||||
public class IntradayReversalCurrencyMarketsAlpha : QCAlgorithm
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2015, 1, 1);
|
||||
SetCash(100000);
|
||||
|
||||
// Set zero transaction fees
|
||||
SetSecurityInitializer(security => security.FeeModel = new ConstantFeeModel(0));
|
||||
|
||||
// Select resolution
|
||||
var resolution = Resolution.Hour;
|
||||
|
||||
// Reversion on the USD.
|
||||
var symbols = new[] { QuantConnect.Symbol.Create("EURUSD", SecurityType.Forex, Market.Oanda) };
|
||||
|
||||
// Set requested data resolution
|
||||
UniverseSettings.Resolution = resolution;
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel(symbols));
|
||||
|
||||
// Use IntradayReversalAlphaModel to establish insights
|
||||
SetAlpha(new IntradayReversalAlphaModel(5, resolution));
|
||||
|
||||
// Equally weigh securities in portfolio, based on insights
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
|
||||
// Set Immediate Execution Model
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
// Set Null Risk Management Model
|
||||
SetRiskManagement(new NullRiskManagementModel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alpha model that uses a Price/SMA Crossover to create insights on Hourly Frequency.
|
||||
/// Frequency: Hourly data with 5-hour simple moving average.
|
||||
/// Strategy:
|
||||
/// Reversal strategy that goes Long when price crosses below SMA and Short when price crosses above SMA.
|
||||
/// The trading strategy is implemented only between 10AM - 3PM (NY time)
|
||||
/// </summary>
|
||||
private class IntradayReversalAlphaModel : AlphaModel
|
||||
{
|
||||
private readonly int _periodSma;
|
||||
private readonly Resolution _resolution;
|
||||
private readonly Dictionary<Symbol, SymbolData> _cache;
|
||||
|
||||
public IntradayReversalAlphaModel(
|
||||
int periodSma = 5,
|
||||
Resolution resolution = Resolution.Hour)
|
||||
{
|
||||
_periodSma = periodSma;
|
||||
_resolution = resolution;
|
||||
_cache = new Dictionary<Symbol, SymbolData>();
|
||||
Name = "IntradayReversalAlphaModel";
|
||||
}
|
||||
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
// Set the time to close all positions at 3PM
|
||||
var timeToClose = algorithm.Time.Date.Add(new TimeSpan(0, 15, 1, 0));
|
||||
|
||||
var insights = new List<Insight>();
|
||||
|
||||
foreach (var kvp in algorithm.ActiveSecurities)
|
||||
{
|
||||
var symbol = kvp.Key;
|
||||
|
||||
SymbolData symbolData;
|
||||
|
||||
if (ShouldEmitInsight(algorithm, symbol) &&
|
||||
_cache.TryGetValue(symbol, out symbolData))
|
||||
{
|
||||
var price = kvp.Value.Price;
|
||||
|
||||
var direction = symbolData.IsUptrend(price)
|
||||
? InsightDirection.Up
|
||||
: InsightDirection.Down;
|
||||
|
||||
// Ignore signal for same direction as previous signal (when no crossover)
|
||||
if (direction == symbolData.PreviousDirection)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Save the current Insight Direction to check when the crossover happens
|
||||
symbolData.PreviousDirection = direction;
|
||||
|
||||
// Generate insight
|
||||
insights.Add(Insight.Price(symbol, timeToClose, direction));
|
||||
}
|
||||
}
|
||||
|
||||
return insights;
|
||||
}
|
||||
|
||||
private bool ShouldEmitInsight(QCAlgorithm algorithm, Symbol symbol)
|
||||
{
|
||||
var timeOfDay = algorithm.Time.TimeOfDay;
|
||||
|
||||
return algorithm.Securities[symbol].HasData &&
|
||||
timeOfDay >= TimeSpan.FromHours(10) &&
|
||||
timeOfDay <= TimeSpan.FromHours(15);
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
foreach (var symbol in changes.AddedSecurities.Select(x => x.Symbol))
|
||||
{
|
||||
if (_cache.ContainsKey(symbol)) continue;
|
||||
_cache.Add(symbol, new SymbolData(algorithm, symbol, _periodSma, _resolution));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains data specific to a symbol required by this model
|
||||
/// </summary>
|
||||
private class SymbolData
|
||||
{
|
||||
private readonly SimpleMovingAverage _priceSMA;
|
||||
|
||||
public InsightDirection PreviousDirection { get; set; }
|
||||
|
||||
public SymbolData(QCAlgorithm algorithm, Symbol symbol, int periodSma, Resolution resolution)
|
||||
{
|
||||
PreviousDirection = InsightDirection.Flat;
|
||||
_priceSMA = algorithm.SMA(symbol, periodSma, resolution);
|
||||
}
|
||||
|
||||
public bool IsUptrend(decimal price)
|
||||
{
|
||||
return _priceSMA.IsReady && price < Math.Round(_priceSMA * 1.001m, 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// This alpha aims to capture the mean-reversion effect of ETFs during lunch-break by ranking 20 ETFs
|
||||
/// on their return between the close of the previous day to 12:00 the day after and predicting mean-reversion
|
||||
/// in price during lunch-break.
|
||||
///
|
||||
/// Source: Lunina, V. (June 2011). The Intraday Dynamics of Stock Returns and Trading Activity: Evidence from OMXS 30 (Master's Essay, Lund University).
|
||||
/// Retrieved from http://lup.lub.lu.se/luur/download?func=downloadFile&recordOId=1973850&fileOId=1973852
|
||||
///
|
||||
/// This alpha is part of the Benchmark Alpha Series created by QuantConnect which are open sourced so the community and client funds can see an example of an alpha.
|
||||
///</summary>
|
||||
public class MeanReversionLunchBreakAlpha : QCAlgorithm
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2018, 1, 1);
|
||||
SetCash(100000);
|
||||
|
||||
// Set zero transaction fees
|
||||
SetSecurityInitializer(security => security.FeeModel = new ConstantFeeModel(0));
|
||||
|
||||
// Use Hourly Data For Simplicity
|
||||
UniverseSettings.Resolution = Resolution.Hour;
|
||||
SetUniverseSelection(new CoarseFundamentalUniverseSelectionModel(CoarseSelectionFunction));
|
||||
|
||||
// Use MeanReversionLunchBreakAlphaModel to establish insights
|
||||
SetAlpha(new MeanReversionLunchBreakAlphaModel());
|
||||
|
||||
// Equally weigh securities in portfolio, based on insights
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
|
||||
// Set Immediate Execution Model
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
// Set Null Risk Management Model
|
||||
SetRiskManagement(new NullRiskManagementModel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sort the data by daily dollar volume and take the top '20' ETFs
|
||||
/// </summary>
|
||||
private IEnumerable<Symbol> CoarseSelectionFunction(IEnumerable<CoarseFundamental> coarse)
|
||||
{
|
||||
return (from cf in coarse
|
||||
where !cf.HasFundamentalData
|
||||
orderby cf.DollarVolume descending
|
||||
select cf.Symbol).Take(20);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses the price return between the close of previous day to 12:00 the day after to
|
||||
/// predict mean-reversion of stock price during lunch break and creates direction prediction
|
||||
/// for insights accordingly.
|
||||
/// </summary>
|
||||
private class MeanReversionLunchBreakAlphaModel : AlphaModel
|
||||
{
|
||||
private const Resolution _resolution = Resolution.Hour;
|
||||
private readonly TimeSpan _predictionInterval;
|
||||
private readonly Dictionary<Symbol, SymbolData> _symbolDataBySymbol;
|
||||
|
||||
public MeanReversionLunchBreakAlphaModel(int lookback = 1)
|
||||
{
|
||||
_predictionInterval = _resolution.ToTimeSpan().Multiply(lookback);
|
||||
_symbolDataBySymbol = new Dictionary<Symbol, SymbolData>();
|
||||
}
|
||||
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
foreach (var kvp in _symbolDataBySymbol)
|
||||
{
|
||||
if (data.Bars.ContainsKey(kvp.Key))
|
||||
{
|
||||
var bar = data.Bars.GetValue(kvp.Key);
|
||||
kvp.Value.Update(bar.EndTime, bar.Close);
|
||||
}
|
||||
}
|
||||
|
||||
return algorithm.Time.Hour == 12
|
||||
? _symbolDataBySymbol.Select(kvp => kvp.Value.Insight)
|
||||
: Enumerable.Empty<Insight>();
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
foreach (var security in changes.RemovedSecurities)
|
||||
{
|
||||
if (_symbolDataBySymbol.ContainsKey(security.Symbol))
|
||||
{
|
||||
_symbolDataBySymbol.Remove(security.Symbol);
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve price history for all securities in the security universe
|
||||
// and update the indicators in the SymbolData object
|
||||
var symbols = changes.AddedSecurities.Select(x => x.Symbol);
|
||||
var history = algorithm.History(symbols, 1, _resolution);
|
||||
if (symbols.Count() > 0 && history.Count() == 0)
|
||||
{
|
||||
algorithm.Debug($"No data on {algorithm.Time}");
|
||||
}
|
||||
|
||||
history.PushThrough(bar =>
|
||||
{
|
||||
SymbolData symbolData;
|
||||
if (!_symbolDataBySymbol.TryGetValue(bar.Symbol, out symbolData))
|
||||
{
|
||||
symbolData = new SymbolData(bar.Symbol, _predictionInterval);
|
||||
}
|
||||
symbolData.Update(bar.EndTime, bar.Price);
|
||||
_symbolDataBySymbol[bar.Symbol] = symbolData;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains data specific to a symbol required by this model
|
||||
/// </summary>
|
||||
private class SymbolData
|
||||
{
|
||||
// Mean value of returns for magnitude prediction
|
||||
private readonly SimpleMovingAverage _meanOfPriceChange = new RateOfChangePercent(1).SMA(3);
|
||||
// Price change from close price the previous day
|
||||
private readonly RateOfChangePercent _priceChange = new RateOfChangePercent(3);
|
||||
|
||||
private readonly Symbol _symbol;
|
||||
private readonly TimeSpan _period;
|
||||
|
||||
public Insight Insight
|
||||
{
|
||||
get
|
||||
{
|
||||
// Emit "down" insight for the securities that increased in value and
|
||||
// emit "up" insight for securities that have decreased in value
|
||||
var direction = _priceChange > 0 ? InsightDirection.Down : InsightDirection.Up;
|
||||
var magnitude = Convert.ToDouble(Math.Abs(_meanOfPriceChange));
|
||||
return Insight.Price(_symbol, _period, direction, magnitude);
|
||||
}
|
||||
}
|
||||
|
||||
public SymbolData(Symbol symbol, TimeSpan period)
|
||||
{
|
||||
_symbol = symbol;
|
||||
_period = period;
|
||||
}
|
||||
|
||||
public bool Update(DateTime time, decimal value)
|
||||
{
|
||||
return _meanOfPriceChange.Update(time, value) &
|
||||
_priceChange.Update(time, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp.Alphas
|
||||
{
|
||||
///<summary>
|
||||
/// Alpha Benchmark Strategy capitalizing on ETF rebalancing causing momentum during trending markets.
|
||||
/// Strategy by Prof. Shum, reposted by Ernie Chan.
|
||||
/// Source: http://epchan.blogspot.com/2012/10/a-leveraged-etfs-strategy.html
|
||||
///</summary>
|
||||
/// <meta name="tag" content="alphastream" />
|
||||
/// <meta name="tag" content="algorithm framework" />
|
||||
/// <meta name="tag" content="etf" />
|
||||
public class RebalancingLeveragedETFAlpha : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private readonly List<ETFGroup> Groups = new List<ETFGroup>();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2017, 6, 1);
|
||||
SetEndDate(2018, 8, 1);
|
||||
SetCash(100000);
|
||||
|
||||
var underlying = new List<string> { "SPY", "QLD", "DIA", "IJR", "MDY", "IWM", "QQQ", "IYE", "EEM", "IYW", "EFA", "GAZB", "SLV", "IEF", "IYM", "IYF", "IYH", "IYR", "IYC", "IBB", "FEZ", "USO", "TLT" };
|
||||
var ultraLong = new List<string> { "SSO", "UGL", "DDM", "SAA", "MZZ", "UWM", "QLD", "DIG", "EET", "ROM", "EFO", "BOIL", "AGQ", "UST", "UYM", "UYG", "RXL", "URE", "UCC", "BIB", "ULE", "UCO", "UBT" };
|
||||
var ultraShort = new List<string> { "SDS", "GLL", "DXD", "SDD", "MVV", "TWM", "QID", "DUG", "EEV", "REW", "EFU", "KOLD", "ZSL", "PST", "SMN", "SKF", "RXD", "SRS", "SCC", "BIS", "EPV", "SCO", "TBT" };
|
||||
|
||||
for (var i = 0; i < underlying.Count; i++)
|
||||
{
|
||||
Groups.Add(new ETFGroup(AddEquity(underlying[i]).Symbol, AddEquity(ultraLong[i]).Symbol, AddEquity(ultraShort[i]).Symbol));
|
||||
}
|
||||
|
||||
// Manually curated universe
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel());
|
||||
|
||||
// Select the demonstration alpha model
|
||||
SetAlpha(new RebalancingLeveragedETFAlphaModel(Groups));
|
||||
|
||||
// Select our default model types
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
|
||||
// Equally weigh securities in portfolio, based on insights
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
|
||||
// Set Immediate Execution Model
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
// Set Null Risk Management Model
|
||||
SetRiskManagement(new NullRiskManagementModel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 0;
|
||||
|
||||
/// </summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2465"},
|
||||
{"Average Win", "0.26%"},
|
||||
{"Average Loss", "-0.24%"},
|
||||
{"Compounding Annual Return", "7.848%"},
|
||||
{"Drawdown", "17.500%"},
|
||||
{"Expectancy", "0.035"},
|
||||
{"Net Profit", "9.233%"},
|
||||
{"Sharpe Ratio", "0.492"},
|
||||
{"Loss Rate", "50%"},
|
||||
{"Win Rate", "50%"},
|
||||
{"Profit-Loss Ratio", "1.06"},
|
||||
{"Alpha", "0.585"},
|
||||
{"Beta", "-24.639"},
|
||||
{"Annual Standard Deviation", "0.19"},
|
||||
{"Annual Variance", "0.036"},
|
||||
{"Information Ratio", "0.387"},
|
||||
{"Tracking Error", "0.19"},
|
||||
{"Treynor Ratio", "-0.004"},
|
||||
{"Total Fees", "$9029.33"}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the underlying ETF has experienced a return >= 1% since the previous day's close up to the current time at 14:15,
|
||||
/// then buy it's ultra ETF right away, and exit at the close. If the return is <= -1%, sell it's ultra-short ETF.
|
||||
/// </summary>
|
||||
class RebalancingLeveragedETFAlphaModel : AlphaModel
|
||||
{
|
||||
private DateTime _date;
|
||||
private readonly List<ETFGroup> _etfGroups;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new leveraged ETF rebalancing alpha
|
||||
/// </summary>
|
||||
public RebalancingLeveragedETFAlphaModel(List<ETFGroup> etfGroups)
|
||||
{
|
||||
_etfGroups = etfGroups;
|
||||
_date = DateTime.MinValue;
|
||||
Name = "RebalancingLeveragedETFAlphaModel";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan to see if the returns are greater than 1% at 2.15pm to emit an insight.
|
||||
/// </summary>
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
// Initialize:
|
||||
var insights = new List<Insight>();
|
||||
var magnitude = 0.0005;
|
||||
|
||||
// Paper suggests leveraged ETF's rebalance from 2.15pm - to close
|
||||
// giving an insight period of 105 minutes.
|
||||
var period = TimeSpan.FromMinutes(105);
|
||||
|
||||
if (algorithm.Time.Date != _date)
|
||||
{
|
||||
_date = algorithm.Time.Date;
|
||||
|
||||
// Save yesterday's price and reset the signal.
|
||||
foreach (var group in _etfGroups)
|
||||
{
|
||||
var history = algorithm.History(group.Underlying, 1, Resolution.Daily);
|
||||
group.YesterdayClose = history.Select(x => x.Close).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the returns are > 1% at 14.15
|
||||
if (algorithm.Time.Hour == 14 && algorithm.Time.Minute == 15)
|
||||
{
|
||||
foreach (var group in _etfGroups)
|
||||
{
|
||||
if (group.YesterdayClose == 0) continue;
|
||||
var returns = (algorithm.Portfolio[group.Underlying].Price - group.YesterdayClose) / group.YesterdayClose;
|
||||
|
||||
if (returns > 0.01m)
|
||||
{
|
||||
insights.Add(Insight.Price(group.UltraLong, period, InsightDirection.Up, magnitude));
|
||||
}
|
||||
else if (returns < -0.01m)
|
||||
{
|
||||
insights.Add(Insight.Price(group.UltraShort, period, InsightDirection.Down, magnitude));
|
||||
}
|
||||
}
|
||||
}
|
||||
return insights;
|
||||
}
|
||||
}
|
||||
|
||||
class ETFGroup
|
||||
{
|
||||
public Symbol Underlying;
|
||||
public Symbol UltraLong;
|
||||
public Symbol UltraShort;
|
||||
public decimal YesterdayClose;
|
||||
|
||||
/// <summary>
|
||||
/// Group the underlying ETF and it's ultra ETFs
|
||||
/// </summary>
|
||||
/// <param name="underlying">The underlying indexETF</param>
|
||||
/// <param name="ultraLong">The long-leveraged version of underlying ETF</param>
|
||||
/// <param name="ultraShort">The short-leveraged version of the underlying ETF</param>
|
||||
public ETFGroup(Symbol underlying, Symbol ultraLong, Symbol ultraShort)
|
||||
{
|
||||
Underlying = underlying;
|
||||
UltraLong = ultraLong;
|
||||
UltraShort = ultraShort;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// A number of companies publicly trade two different classes of shares
|
||||
/// in US equity markets. If both assets trade with reasonable volume, then
|
||||
/// the underlying driving forces of each should be similar or the same. Given
|
||||
/// this, we can create a relatively dollar-neutral long/short portfolio using
|
||||
/// the dual share classes. Theoretically, any deviation of this portfolio from
|
||||
/// its mean-value should be corrected, and so the motivating idea is based on
|
||||
/// mean-reversion. Using a Simple Moving Average indicator, we can
|
||||
/// compare the value of this portfolio against its SMA and generate insights
|
||||
/// to buy the under-valued symbol and sell the over-valued symbol.
|
||||
///
|
||||
/// This alpha is part of the Benchmark Alpha Series created by QuantConnect which are open sourced so the community and client funds can see an example of an alpha.
|
||||
/// </summary>
|
||||
public class ShareClassMeanReversionAlpha : QCAlgorithm
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2019, 1, 1);
|
||||
SetCash(100000);
|
||||
|
||||
// Set zero transaction fees
|
||||
SetSecurityInitializer(security => security.FeeModel = new ConstantFeeModel(0));
|
||||
|
||||
SetWarmUp(20);
|
||||
|
||||
// Setup Universe settings and tickers to be used
|
||||
var symbols = new[] { "VIA", "VIAB" }
|
||||
.Select(x => QuantConnect.Symbol.Create(x, SecurityType.Equity, Market.USA));
|
||||
|
||||
// Set requested data resolution
|
||||
UniverseSettings.Resolution = Resolution.Minute;
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel(symbols));
|
||||
|
||||
// Use ShareClassMeanReversionAlphaModel to establish insights
|
||||
SetAlpha(new ShareClassMeanReversionAlphaModel(symbols));
|
||||
|
||||
// Equally weigh securities in portfolio, based on insights
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
|
||||
// Set Immediate Execution Model
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
// Set Null Risk Management Model
|
||||
SetRiskManagement(new NullRiskManagementModel());
|
||||
}
|
||||
|
||||
private class ShareClassMeanReversionAlphaModel : AlphaModel
|
||||
{
|
||||
private const double _insightMagnitude = 0.001;
|
||||
private readonly Symbol _longSymbol;
|
||||
private readonly Symbol _shortSymbol;
|
||||
private readonly TimeSpan _insightPeriod;
|
||||
private readonly SimpleMovingAverage _sma;
|
||||
private readonly RollingWindow<decimal> _positionWindow;
|
||||
private decimal _alpha;
|
||||
private decimal _beta;
|
||||
private bool _invested;
|
||||
|
||||
public ShareClassMeanReversionAlphaModel(
|
||||
IEnumerable<Symbol> symbols,
|
||||
Resolution resolution = Resolution.Minute)
|
||||
{
|
||||
if (symbols.Count() != 2)
|
||||
{
|
||||
throw new ArgumentException("ShareClassMeanReversionAlphaModel: symbols parameter must contain 2 elements");
|
||||
}
|
||||
_longSymbol = symbols.ToArray()[0];
|
||||
_shortSymbol = symbols.ToArray()[1];
|
||||
_insightPeriod = resolution.ToTimeSpan().Multiply(5);
|
||||
_sma = new SimpleMovingAverage(2);
|
||||
_positionWindow = new RollingWindow<decimal>(2);
|
||||
}
|
||||
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
// Check to see if either ticker will return a NoneBar, and skip the data slice if so
|
||||
if (data.Bars.Count < 2)
|
||||
{
|
||||
return Enumerable.Empty<Insight>();
|
||||
}
|
||||
|
||||
// If Alpha and Beta haven't been calculated yet, then do so
|
||||
if (_alpha == 0 || _beta == 0)
|
||||
{
|
||||
CalculateAlphaBeta(algorithm);
|
||||
}
|
||||
|
||||
// Update indicator and Rolling Window for each data slice passed into Update() method
|
||||
if (!UpdateIndicators(data))
|
||||
{
|
||||
return Enumerable.Empty<Insight>();
|
||||
}
|
||||
|
||||
// Check to see if the portfolio is invested. If no, then perform value comparisons and emit insights accordingly
|
||||
if (!_invested)
|
||||
{
|
||||
//Reset invested boolean
|
||||
_invested = true;
|
||||
|
||||
if (_positionWindow[0] > _sma)
|
||||
{
|
||||
return Insight.Group(new[]
|
||||
{
|
||||
Insight.Price(_longSymbol, _insightPeriod, InsightDirection.Down, _insightMagnitude),
|
||||
Insight.Price(_shortSymbol, _insightPeriod, InsightDirection.Up, _insightMagnitude),
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
return Insight.Group(new[]
|
||||
{
|
||||
Insight.Price(_longSymbol, _insightPeriod, InsightDirection.Up, _insightMagnitude),
|
||||
Insight.Price(_shortSymbol, _insightPeriod, InsightDirection.Down, _insightMagnitude),
|
||||
});
|
||||
}
|
||||
}
|
||||
// If the portfolio is invested and crossed back over the SMA, then emit flat insights
|
||||
else if (_invested && CrossedMean())
|
||||
{
|
||||
_invested = false;
|
||||
}
|
||||
|
||||
return Enumerable.Empty<Insight>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate Alpha and Beta, the initial number of shares for each security needed to achieve a 50/50 weighting
|
||||
/// </summary>
|
||||
/// <param name="algorithm"></param>
|
||||
private void CalculateAlphaBeta(QCAlgorithm algorithm)
|
||||
{
|
||||
_alpha = algorithm.CalculateOrderQuantity(_longSymbol, 0.5);
|
||||
_beta = algorithm.CalculateOrderQuantity(_shortSymbol, 0.5);
|
||||
algorithm.Log($"{algorithm.Time} :: Alpha: {_alpha} Beta: {_beta}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate position value and update the SMA indicator and Rolling Window
|
||||
/// </summary>
|
||||
private bool UpdateIndicators(Slice data)
|
||||
{
|
||||
var positionValue = (_alpha * data[_longSymbol].Close) - (_beta * data[_shortSymbol].Close);
|
||||
_sma.Update(data[_longSymbol].EndTime, positionValue);
|
||||
_positionWindow.Add(positionValue);
|
||||
return _sma.IsReady && _positionWindow.IsReady;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check to see if the position value has crossed the SMA and then return a boolean value
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool CrossedMean()
|
||||
{
|
||||
return (_positionWindow[0] >= _sma && _positionWindow[1] < _sma)
|
||||
|| (_positionWindow[1] >= _sma && _positionWindow[0] < _sma);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// Identify "pumped" penny stocks and predict that the price of a "Pumped" penny stock reverts to mean
|
||||
///
|
||||
/// This alpha is part of the Benchmark Alpha Series created by QuantConnect which are open sourced so the community and client funds can see an example of an alpha.
|
||||
///</summary>
|
||||
public class SykesShortMicroCapAlpha : QCAlgorithm
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2018, 1, 1);
|
||||
SetCash(100000);
|
||||
|
||||
// Set zero transaction fees
|
||||
SetSecurityInitializer(security => security.FeeModel = new ConstantFeeModel(0));
|
||||
|
||||
// Select stocks using PennyStockUniverseSelectionModel
|
||||
UniverseSettings.Resolution = Resolution.Daily;
|
||||
SetUniverseSelection(new PennyStockUniverseSelectionModel());
|
||||
|
||||
// Use SykesShortMicroCapAlphaModel to establish insights
|
||||
SetAlpha(new SykesShortMicroCapAlphaModel());
|
||||
|
||||
// Equally weigh securities in portfolio, based on insights
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
|
||||
// Set Immediate Execution Model
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
// Set Null Risk Management Model
|
||||
SetRiskManagement(new NullRiskManagementModel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs coarse selection for constituents.
|
||||
/// The stocks must have fundamental data
|
||||
/// The stock must have positive previous-day close price
|
||||
/// The stock must have volume between $1000000 and $10000 on the previous trading day
|
||||
/// The stock must cost less than $5'''
|
||||
/// </summary>
|
||||
private class PennyStockUniverseSelectionModel : FundamentalUniverseSelectionModel
|
||||
{
|
||||
private const int _numberOfSymbolsCoarse = 500;
|
||||
private int _lastMonth = -1;
|
||||
|
||||
public PennyStockUniverseSelectionModel() : base(false)
|
||||
{
|
||||
}
|
||||
|
||||
public override IEnumerable<Symbol> SelectCoarse(QCAlgorithm algorithm, IEnumerable<CoarseFundamental> coarse)
|
||||
{
|
||||
var month = algorithm.Time.Month;
|
||||
if (month == _lastMonth)
|
||||
{
|
||||
return algorithm.Universe.Unchanged;
|
||||
}
|
||||
_lastMonth = month;
|
||||
|
||||
return (from cf in coarse
|
||||
where cf.HasFundamentalData
|
||||
where cf.Volume < 1000000
|
||||
where cf.Volume > 10000
|
||||
where cf.Price < 5
|
||||
orderby cf.DollarVolume descending
|
||||
select cf.Symbol).Take(_numberOfSymbolsCoarse);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses ranking of intraday percentage difference between open price and close price to create magnitude and direction prediction for insights
|
||||
/// </summary>
|
||||
private class SykesShortMicroCapAlphaModel : AlphaModel
|
||||
{
|
||||
private readonly int _numberOfStocks;
|
||||
private readonly TimeSpan _predictionInterval;
|
||||
|
||||
public SykesShortMicroCapAlphaModel(
|
||||
int lookback = 1,
|
||||
int numberOfStocks = 10,
|
||||
Resolution resolution = Resolution.Daily)
|
||||
{
|
||||
_numberOfStocks = numberOfStocks;
|
||||
_predictionInterval = resolution.ToTimeSpan().Multiply(lookback);
|
||||
}
|
||||
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
return (
|
||||
from entry in algorithm.ActiveSecurities
|
||||
let security = entry.Value
|
||||
where security.HasData && security.Open > 0
|
||||
// Rank penny stocks on one day price change
|
||||
let Magnitude = security.Close / security.Open - 1
|
||||
orderby Math.Round(Magnitude, 6), security.Symbol descending
|
||||
select Insight.Price(security.Symbol, _predictionInterval, InsightDirection.Down, Math.Abs((double)Magnitude)))
|
||||
// Retrieve list of _numberOfStocks "pumped" penny stocks
|
||||
.Take(_numberOfStocks);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// In a perfect market, you could buy 100 EUR worth of USD, sell 100 EUR worth of GBP,
|
||||
/// and then use the GBP to buy USD and wind up with the same amount in USD as you received when
|
||||
/// you bought them with EUR. This relationship is expressed by the Triangle Exchange Rate, which is
|
||||
///
|
||||
/// Triangle Exchange Rate = (A/B) * (B/C) * (C/A)
|
||||
///
|
||||
/// where (A/B) is the exchange rate of A-to-B. In a perfect market, TER = 1, and so when
|
||||
/// there is a mispricing in the market, then TER will not be 1 and there exists an arbitrage opportunity.
|
||||
///
|
||||
/// This alpha is part of the Benchmark Alpha Series created by QuantConnect which are open sourced so the community and client funds can see an example of an alpha.
|
||||
/// </summary>
|
||||
public class TriangleExchangeRateArbitrageAlpha : QCAlgorithm
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2019, 2, 1);
|
||||
SetCash(100000);
|
||||
|
||||
// Set zero transaction fees
|
||||
SetSecurityInitializer(security => security.FeeModel = new ConstantFeeModel(0));
|
||||
|
||||
// Select trio of currencies to trade where
|
||||
// Currency A = USD
|
||||
// Currency B = EUR
|
||||
// Currency C = GBP
|
||||
var symbols = new[] { "EURUSD", "EURGBP", "GBPUSD" }
|
||||
.Select(x => QuantConnect.Symbol.Create(x, SecurityType.Forex, Market.Oanda));
|
||||
|
||||
// Set requested data resolution
|
||||
UniverseSettings.Resolution = Resolution.Minute;
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel(symbols));
|
||||
|
||||
// Use ForexTriangleArbitrageAlphaModel to establish insights
|
||||
SetAlpha(new ForexTriangleArbitrageAlphaModel(symbols, Resolution.Minute));
|
||||
|
||||
// Equally weigh securities in portfolio, based on insights
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
|
||||
// Set Immediate Execution Model
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
// Set Null Risk Management Model
|
||||
SetRiskManagement(new NullRiskManagementModel());
|
||||
}
|
||||
|
||||
private class ForexTriangleArbitrageAlphaModel : AlphaModel
|
||||
{
|
||||
private readonly Symbol[] _symbols;
|
||||
private readonly TimeSpan _insightPeriod;
|
||||
|
||||
public ForexTriangleArbitrageAlphaModel(
|
||||
IEnumerable<Symbol> symbols,
|
||||
Resolution resolution = Resolution.Minute)
|
||||
{
|
||||
_symbols = symbols.ToArray();
|
||||
_insightPeriod = resolution.ToTimeSpan().Multiply(5);
|
||||
}
|
||||
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
// Check to make sure all currency symbols are present
|
||||
if (data.QuoteBars.Count < 3)
|
||||
{
|
||||
return Enumerable.Empty<Insight>();
|
||||
}
|
||||
|
||||
// Extract QuoteBars for all three Forex securities
|
||||
var barA = data[_symbols[0]];
|
||||
var barB = data[_symbols[1]];
|
||||
var barC = data[_symbols[2]];
|
||||
|
||||
// Calculate the triangle exchange rate
|
||||
// Bid(Currency A -> Currency B) * Bid(Currency B -> Currency C) * Bid(Currency C -> Currency A)
|
||||
// If exchange rates are priced perfectly, then this yield 1.If it is different than 1, then an arbitrage opportunity exists
|
||||
var triangleRate = barA.Ask.Close / barB.Bid.Close / barC.Ask.Close;
|
||||
|
||||
// If the triangle rate is significantly different than 1, then emit insights
|
||||
if (triangleRate > 1.0005m)
|
||||
{
|
||||
return Insight.Group(new[]
|
||||
{
|
||||
Insight.Price(_symbols[0], _insightPeriod, InsightDirection.Up, 0.0001),
|
||||
Insight.Price(_symbols[1], _insightPeriod, InsightDirection.Down, 0.0001),
|
||||
Insight.Price(_symbols[2], _insightPeriod, InsightDirection.Up, 0.0001)
|
||||
});
|
||||
}
|
||||
|
||||
return Enumerable.Empty<Insight>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// Leveraged ETFs (LETF) promise a fixed leverage ratio with respect to an underlying asset or an index.
|
||||
/// A Triple-Leveraged ETF allows speculators to amplify their exposure to the daily returns of an underlying index by a factor of 3.
|
||||
///
|
||||
/// Increased volatility generally decreases the value of a LETF over an extended period of time as daily compounding is amplified.
|
||||
///
|
||||
/// This alpha emits short-biased insight to capitalize on volatility decay for each listed pair of TL-ETFs, by rebalancing the
|
||||
/// ETFs with equal weights each day.
|
||||
///
|
||||
/// This alpha is part of the Benchmark Alpha Series created by QuantConnect which are open sourced so the community and client funds can see an example of an alpha.
|
||||
/// </summary>
|
||||
public class TripleLeveragedETFPairVolatilityDecayAlpha : QCAlgorithm
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2018, 1, 1);
|
||||
|
||||
SetCash(100000);
|
||||
|
||||
// Set zero transaction fees
|
||||
SetSecurityInitializer(security => security.FeeModel = new ConstantFeeModel(0));
|
||||
|
||||
// 3X ETF pair tickers
|
||||
var ultraLong = QuantConnect.Symbol.Create("UGLD", SecurityType.Equity, Market.USA);
|
||||
var ultraShort = QuantConnect.Symbol.Create("DGLD", SecurityType.Equity, Market.USA);
|
||||
|
||||
// Manually curated universe
|
||||
UniverseSettings.Resolution = Resolution.Daily;
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel(new[] { ultraLong, ultraShort }));
|
||||
|
||||
// Select the demonstration alpha model
|
||||
SetAlpha(new RebalancingTripleLeveragedETFAlphaModel(ultraLong, ultraShort));
|
||||
|
||||
// Equally weigh securities in portfolio, based on insights
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
|
||||
// Set Immediate Execution Model
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
// Set Null Risk Management Model
|
||||
SetRiskManagement(new NullRiskManagementModel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rebalance a pair of 3x leveraged ETFs and predict that the value of both ETFs in each pair will decrease.
|
||||
/// </summary>
|
||||
private class RebalancingTripleLeveragedETFAlphaModel : AlphaModel
|
||||
{
|
||||
private const double _magnitude = 0.001;
|
||||
private readonly Symbol _ultraLong;
|
||||
private readonly Symbol _ultraShort;
|
||||
private readonly TimeSpan _period;
|
||||
|
||||
public RebalancingTripleLeveragedETFAlphaModel(Symbol ultraLong, Symbol ultraShort)
|
||||
{
|
||||
// Giving an insight period 1 days.
|
||||
_period = QuantConnect.Time.OneDay;
|
||||
|
||||
_ultraLong = ultraLong;
|
||||
_ultraShort = ultraShort;
|
||||
|
||||
Name = "RebalancingTripleLeveragedETFAlphaModel";
|
||||
}
|
||||
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
return Insight.Group(new[]
|
||||
{
|
||||
Insight.Price(_ultraLong, _period, InsightDirection.Down, _magnitude),
|
||||
Insight.Price(_ultraShort, _period, InsightDirection.Down, _magnitude)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Brokerages;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Consolidators;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Orders.Fees;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a demonstration algorithm. It trades UVXY.
|
||||
/// Dual Thrust alpha model is used to produce insights.
|
||||
/// Those input parameters have been chosen that gave acceptable results on a series
|
||||
/// of random backtests run for the period from Oct, 2016 till Feb, 2019.
|
||||
/// </summary>
|
||||
class VIXDualThrustAlpha : QCAlgorithm
|
||||
{
|
||||
// -- STRATEGY INPUT PARAMETERS --
|
||||
private decimal _k1 = 0.63m;
|
||||
private decimal _k2 = 0.63m;
|
||||
private int _rangePeriod = 20;
|
||||
private int _consolidatorBars = 30;
|
||||
|
||||
// -- INITIALIZE --
|
||||
public override void Initialize()
|
||||
{
|
||||
// Settings
|
||||
SetStartDate(2016, 10, 01);
|
||||
SetSecurityInitializer(s => s.SetFeeModel(new ConstantFeeModel(0m)));
|
||||
SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin);
|
||||
|
||||
// Universe Selection
|
||||
UniverseSettings.Resolution = Resolution.Minute; // it's minute by default, but lets leave this param here
|
||||
var symbols = new[] { QuantConnect.Symbol.Create("UVXY", SecurityType.Equity, Market.USA) };
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel(symbols));
|
||||
|
||||
// Warming up
|
||||
var resolutionInTimeSpan = UniverseSettings.Resolution.ToTimeSpan();
|
||||
var warmUpTimeSpan = resolutionInTimeSpan.Multiply(_consolidatorBars).Multiply(_rangePeriod);
|
||||
SetWarmUp(warmUpTimeSpan);
|
||||
|
||||
// Alpha Model
|
||||
SetAlpha(new DualThrustAlphaModel(_k1, _k2, _rangePeriod, UniverseSettings.Resolution, _consolidatorBars));
|
||||
|
||||
// Portfolio Construction
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
|
||||
// Execution
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
// Risk Management
|
||||
SetRiskManagement(new MaximumDrawdownPercentPerSecurity(0.03m));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alpha model that uses dual-thrust strategy to create insights
|
||||
/// https://medium.com/@FMZ_Quant/dual-thrust-trading-strategy-2cc74101a626
|
||||
/// or here:
|
||||
/// https://www.quantconnect.com/tutorials/strategy-library/dual-thrust-trading-algorithm
|
||||
/// </summary>
|
||||
public class DualThrustAlphaModel : AlphaModel
|
||||
{
|
||||
private readonly decimal _k1;
|
||||
private readonly decimal _k2;
|
||||
private readonly TimeSpan _consolidatorTimeSpan;
|
||||
private readonly int _rangePeriod;
|
||||
private readonly Dictionary<Symbol, SymbolData> _symbolDataBySymbol;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the class
|
||||
/// </summary>
|
||||
/// <param name="k1">Coefficient for upper band</param>
|
||||
/// <param name="k2">Coefficient for lower band</param>
|
||||
/// <param name="rangePeriod">Amount of last bars to calculate the range</param>
|
||||
/// <param name="resolution">The resolution of data sent into the EMA indicators</param>
|
||||
/// <param name="barsToConsolidate">If we want alpha o work on trade bars whose length is
|
||||
/// different from the standard resolution - 1m 1h etc. - we need to pass this parameters along
|
||||
/// with proper data resolution</param>
|
||||
public DualThrustAlphaModel(
|
||||
decimal k1,
|
||||
decimal k2,
|
||||
int rangePeriod,
|
||||
Resolution resolution = Resolution.Daily,
|
||||
int barsToConsolidate = 1
|
||||
)
|
||||
{
|
||||
// coefficient that used to determine upper and lower borders of a breakout channel
|
||||
_k1 = k1;
|
||||
_k2 = k2;
|
||||
|
||||
// period the range is calculated over
|
||||
_rangePeriod = rangePeriod;
|
||||
|
||||
// initialize with empty dict.
|
||||
_symbolDataBySymbol = new Dictionary<Symbol, SymbolData>();
|
||||
|
||||
// time for bars we make the calculations on
|
||||
_consolidatorTimeSpan = resolution.ToTimeSpan().Multiply(barsToConsolidate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates this alpha model with the latest data from the algorithm.
|
||||
/// This is called each time the algorithm receives data for subscribed securities
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="data">The new data available</param>
|
||||
/// <returns>The new insights generated</returns>
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
var insights = new List<Insight>();
|
||||
|
||||
// in 5 days after emission an insight is to be considered expired
|
||||
int insightCloseAddDays = 5;
|
||||
|
||||
foreach (var symbolData in _symbolDataBySymbol.Values)
|
||||
{
|
||||
var range = symbolData.Range;
|
||||
var symbol = symbolData.Symbol;
|
||||
var security = algorithm.Securities[symbol];
|
||||
|
||||
if (symbolData.IsReady)
|
||||
{
|
||||
// buying condition
|
||||
// - (1) price is above upper line
|
||||
// - (2) and we are not long. this is a first time we crossed the line lately
|
||||
if (security.Price > symbolData.UpperLine && !algorithm.Portfolio[symbol].IsLong)
|
||||
{
|
||||
DateTime insightCloseTimeUtc = algorithm.UtcTime.AddDays(insightCloseAddDays);
|
||||
insights.Add(Insight.Price(symbolData.Symbol, insightCloseTimeUtc, InsightDirection.Up));
|
||||
}
|
||||
|
||||
// selling condition
|
||||
// - (1) price is lower that lower line
|
||||
// - (2) and we are not short. this is a first time we crossed the line lately
|
||||
if (security.Price < symbolData.LowerLine && !algorithm.Portfolio[symbol].IsShort)
|
||||
{
|
||||
DateTime insightCloseTimeUtc = algorithm.UtcTime.AddDays(insightCloseAddDays);
|
||||
insights.Add(Insight.Price(symbolData.Symbol, insightCloseTimeUtc, InsightDirection.Down));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return insights;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired each time the we add/remove securities from the data feed
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
|
||||
/// <param name="changes">The security additions and removals from the algorithm</param>
|
||||
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
// added
|
||||
foreach (var added in changes.AddedSecurities)
|
||||
{
|
||||
SymbolData symbolData;
|
||||
if (!_symbolDataBySymbol.TryGetValue(added.Symbol, out symbolData))
|
||||
{
|
||||
// add symbol/symbolData pair to collection
|
||||
symbolData = new SymbolData(_rangePeriod, _consolidatorTimeSpan)
|
||||
{
|
||||
Symbol = added.Symbol,
|
||||
K1 = _k1,
|
||||
K2 = _k2
|
||||
};
|
||||
|
||||
_symbolDataBySymbol[added.Symbol] = symbolData;
|
||||
|
||||
//register consolidator
|
||||
algorithm.SubscriptionManager.AddConsolidator(added.Symbol, symbolData.GetConsolidator());
|
||||
}
|
||||
}
|
||||
|
||||
// removed
|
||||
foreach (var removed in changes.RemovedSecurities)
|
||||
{
|
||||
SymbolData symbolData;
|
||||
if (_symbolDataBySymbol.TryGetValue(removed.Symbol, out symbolData))
|
||||
{
|
||||
// unsubscribe consolidator from data updates
|
||||
algorithm.SubscriptionManager.RemoveConsolidator(removed.Symbol, symbolData.GetConsolidator());
|
||||
|
||||
// remove item from dictionary collection
|
||||
if (!_symbolDataBySymbol.Remove(removed.Symbol))
|
||||
{
|
||||
algorithm.Error("Unable to remove data from collection: DualThrustAlphaModel");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains data specific to a symbol required by this model
|
||||
/// </summary>
|
||||
private class SymbolData
|
||||
{
|
||||
// rolling to contain items over the looking back period
|
||||
private readonly RollingWindow<TradeBar> _rangeWindow;
|
||||
|
||||
// we calculate our logic on bars
|
||||
private readonly TradeBarConsolidator _consolidator;
|
||||
|
||||
// current range value
|
||||
public decimal Range { get; private set; }
|
||||
|
||||
// upper Line
|
||||
public decimal UpperLine { get; private set; }
|
||||
|
||||
// lower Line
|
||||
public decimal LowerLine { get; private set; }
|
||||
|
||||
// symbol value
|
||||
public Symbol Symbol { get; set; }
|
||||
|
||||
// k1
|
||||
public decimal K1 { private get; set; }
|
||||
|
||||
// k2
|
||||
public decimal K2 { private get; set; }
|
||||
|
||||
// data is ready when rolling window is ready
|
||||
public bool IsReady => _rangeWindow.IsReady;
|
||||
|
||||
/// <summary>
|
||||
/// Main constructor for the class
|
||||
/// </summary>
|
||||
/// <param name="rangePeriod">Range period</param>
|
||||
/// <param name="consolidatorResolution">Time length of consolidator</param>
|
||||
public SymbolData(int rangePeriod, TimeSpan consolidatorResolution)
|
||||
{
|
||||
_rangeWindow = new RollingWindow<TradeBar>(rangePeriod);
|
||||
_consolidator = new TradeBarConsolidator(consolidatorResolution);
|
||||
|
||||
// event fired at new consolidated trade bar
|
||||
_consolidator.DataConsolidated += (sender, consolidated) =>
|
||||
{
|
||||
// add new tradebar to
|
||||
_rangeWindow.Add(consolidated);
|
||||
|
||||
if (IsReady)
|
||||
{
|
||||
var hh = _rangeWindow.Select(x => x.High).Max();
|
||||
var hc = _rangeWindow.Select(x => x.Close).Max();
|
||||
var lc = _rangeWindow.Select(x => x.Close).Min();
|
||||
var ll = _rangeWindow.Select(x => x.Low).Min();
|
||||
|
||||
Range = Math.Max(hh - lc, hc - ll);
|
||||
|
||||
UpperLine = consolidated.Close + K1 * Range;
|
||||
LowerLine = consolidated.Close - K2 * Range;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the interior consolidator
|
||||
/// </summary>
|
||||
public TradeBarConsolidator GetConsolidator()
|
||||
{
|
||||
return _consolidator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Example algorithm using the asynchronous universe selection functionality
|
||||
/// </summary>
|
||||
public class AsynchronousUniverseRegressionAlgorithm : FundamentalRegressionAlgorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
UniverseSettings.Asynchronous = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm to test the behaviour of ARMA versus AR models at the same order of differencing.
|
||||
/// In particular, an ARIMA(1,1,1) and ARIMA(1,1,0) are instantiated while orders are placed if their difference
|
||||
/// is sufficiently large (which would be due to the inclusion of the MA(1) term).
|
||||
/// </summary>
|
||||
public class AutoRegressiveIntegratedMovingAverageRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private AutoRegressiveIntegratedMovingAverage _arima;
|
||||
private AutoRegressiveIntegratedMovingAverage _ar;
|
||||
private decimal _last;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 1, 07);
|
||||
SetEndDate(2013, 12, 11);
|
||||
|
||||
Settings.AutomaticIndicatorWarmUp = true;
|
||||
AddEquity("SPY", Resolution.Daily);
|
||||
_arima = ARIMA("SPY", 1, 1, 1, 50);
|
||||
_ar = ARIMA("SPY", 1, 1, 0, 50);
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (_arima.IsReady)
|
||||
{
|
||||
if (Math.Abs(_ar.Current.Value - _arima.Current.Value) > 1) // Difference due to MA(1) being included.
|
||||
{
|
||||
if (_arima.Current.Value > _last)
|
||||
{
|
||||
MarketOrder("SPY", 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
MarketOrder("SPY", -1);
|
||||
}
|
||||
}
|
||||
|
||||
_last = _arima.Current.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 1893;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 100;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "53"},
|
||||
{"Average Win", "0.00%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "0.076%"},
|
||||
{"Drawdown", "0.100%"},
|
||||
{"Expectancy", "2.933"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100070.90"},
|
||||
{"Net Profit", "0.071%"},
|
||||
{"Sharpe Ratio", "-9.164"},
|
||||
{"Sortino Ratio", "-9.852"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "27%"},
|
||||
{"Win Rate", "73%"},
|
||||
{"Profit-Loss Ratio", "4.41"},
|
||||
{"Alpha", "-0.008"},
|
||||
{"Beta", "0.008"},
|
||||
{"Annual Standard Deviation", "0.001"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-1.961"},
|
||||
{"Tracking Error", "0.092"},
|
||||
{"Treynor Ratio", "-0.911"},
|
||||
{"Total Fees", "$53.00"},
|
||||
{"Estimated Strategy Capacity", "$16000000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "0.02%"},
|
||||
{"Drawdown Recovery", "50"},
|
||||
{"OrderListHash", "685c37df6e4c49b75792c133be189094"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm which tests indicator warm up using different data types, related to GH issue 4205
|
||||
/// </summary>
|
||||
public class AutomaticIndicatorWarmupDataTypeRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _symbol;
|
||||
public override void Initialize()
|
||||
{
|
||||
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
|
||||
Settings.AutomaticIndicatorWarmUp = true;
|
||||
SetStartDate(2013, 10, 08);
|
||||
SetEndDate(2013, 10, 10);
|
||||
|
||||
var SP500 = QuantConnect.Symbol.Create(Futures.Indices.SP500EMini, SecurityType.Future, Market.CME);
|
||||
_symbol = FuturesChain(SP500).OrderBy(x => x.Symbol.ID.Date).First();
|
||||
|
||||
// Test case: custom IndicatorBase<QuoteBar> indicator using Future unsubscribed symbol
|
||||
var indicator1 = new CustomIndicator();
|
||||
AssertIndicatorState(indicator1, isReady: false);
|
||||
WarmUpIndicator(_symbol, indicator1);
|
||||
AssertIndicatorState(indicator1, isReady: true);
|
||||
|
||||
// Test case: SimpleMovingAverage<IndicatorDataPoint> using Future unsubscribed symbol (should use TradeBar)
|
||||
var sma1 = new SimpleMovingAverage(10);
|
||||
AssertIndicatorState(sma1, isReady: false);
|
||||
WarmUpIndicator(_symbol, sma1);
|
||||
AssertIndicatorState(sma1, isReady: true);
|
||||
|
||||
// Test case: SimpleMovingAverage<IndicatorDataPoint> using Equity unsubscribed symbol
|
||||
var spy = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
|
||||
var sma = new SimpleMovingAverage(10);
|
||||
AssertIndicatorState(sma, isReady: false);
|
||||
WarmUpIndicator(spy, sma);
|
||||
AssertIndicatorState(sma, isReady: true);
|
||||
|
||||
// We add the symbol
|
||||
AddFutureContract(_symbol);
|
||||
AddEquity("SPY");
|
||||
// force spy for use Raw data mode so that it matches the used when unsubscribed which uses the universe settings
|
||||
SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(spy).SetDataNormalizationMode(DataNormalizationMode.Raw);
|
||||
|
||||
// Test case: custom IndicatorBase<QuoteBar> indicator using Future subscribed symbol
|
||||
var indicator = new CustomIndicator();
|
||||
var consolidator = CreateConsolidator(TimeSpan.FromMinutes(2), typeof(QuoteBar));
|
||||
RegisterIndicator(_symbol, indicator, consolidator);
|
||||
|
||||
AssertIndicatorState(indicator, isReady: false);
|
||||
WarmUpIndicator(_symbol, indicator);
|
||||
AssertIndicatorState(indicator, isReady: true);
|
||||
|
||||
// Test case: SimpleMovingAverage<IndicatorDataPoint> using Future Subscribed symbol (should use TradeBar)
|
||||
var sma11 = new SimpleMovingAverage(10);
|
||||
AssertIndicatorState(sma11, isReady: false);
|
||||
WarmUpIndicator(_symbol, sma11);
|
||||
AssertIndicatorState(sma11, isReady: true);
|
||||
|
||||
if (!sma11.Current.Equals(sma1.Current))
|
||||
{
|
||||
throw new RegressionTestException("Expected SMAs warmed up before and after adding the Future to the algorithm to have the same current value. " +
|
||||
"The result of 'WarmUpIndicator' shouldn't change if the symbol is or isn't subscribed");
|
||||
}
|
||||
|
||||
// Test case: SimpleMovingAverage<IndicatorDataPoint> using Equity unsubscribed symbol
|
||||
var smaSpy = new SimpleMovingAverage(10);
|
||||
AssertIndicatorState(smaSpy, isReady: false);
|
||||
WarmUpIndicator(spy, smaSpy);
|
||||
AssertIndicatorState(smaSpy, isReady: true);
|
||||
|
||||
if (!smaSpy.Current.Equals(sma.Current))
|
||||
{
|
||||
throw new RegressionTestException("Expected SMAs warmed up before and after adding the Equity to the algorithm to have the same current value. " +
|
||||
"The result of 'WarmUpIndicator' shouldn't change if the symbol is or isn't subscribed");
|
||||
}
|
||||
}
|
||||
|
||||
private void AssertIndicatorState(IIndicator indicator, bool isReady)
|
||||
{
|
||||
if (indicator.IsReady != isReady)
|
||||
{
|
||||
throw new RegressionTestException($"Expected indicator state, expected {isReady} but was {indicator.IsReady}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings(_symbol, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
private class CustomIndicator : IndicatorBase<QuoteBar>, IIndicatorWarmUpPeriodProvider
|
||||
{
|
||||
private bool _isReady;
|
||||
public int WarmUpPeriod => 1;
|
||||
public override bool IsReady => _isReady;
|
||||
public CustomIndicator() : base("Pepe")
|
||||
{ }
|
||||
protected override decimal ComputeNextValue(QuoteBar input)
|
||||
{
|
||||
_isReady = true;
|
||||
return input.Ask.High;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 6426;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 85;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "733913.744%"},
|
||||
{"Drawdown", "15.900%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "106827.7"},
|
||||
{"Net Profit", "6.828%"},
|
||||
{"Sharpe Ratio", "203744786353.299"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "456382350698.622"},
|
||||
{"Beta", "9.229"},
|
||||
{"Annual Standard Deviation", "2.24"},
|
||||
{"Annual Variance", "5.017"},
|
||||
{"Information Ratio", "228504036840.953"},
|
||||
{"Tracking Error", "1.997"},
|
||||
{"Treynor Ratio", "49450701625.717"},
|
||||
{"Total Fees", "$23.65"},
|
||||
{"Estimated Strategy Capacity", "$200000000.00"},
|
||||
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
|
||||
{"Portfolio Turnover", "351.80%"},
|
||||
{"Drawdown Recovery", "1"},
|
||||
{"OrderListHash", "dfd9a280d3c6470b305c03e0b72c234e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm asserting the behavior of the AutomaticIndicatorWarmUp on option greeks
|
||||
/// </summary>
|
||||
public class AutomaticIndicatorWarmupOptionIndicatorsMirrorContractsRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2015, 12, 24);
|
||||
SetEndDate(2015, 12, 24);
|
||||
|
||||
Settings.AutomaticIndicatorWarmUp = true;
|
||||
|
||||
var underlying = "GOOG";
|
||||
var resolution = Resolution.Minute;
|
||||
|
||||
var expiration = new DateTime(2015, 12, 24);
|
||||
var strike = 650m;
|
||||
|
||||
var equity = AddEquity(underlying, resolution).Symbol;
|
||||
var option = QuantConnect.Symbol.CreateOption(underlying, Market.USA, OptionStyle.American, OptionRight.Put, strike, expiration);
|
||||
AddOptionContract(option, resolution);
|
||||
// add the call counter side of the mirrored pair
|
||||
var mirrorOption = QuantConnect.Symbol.CreateOption(underlying, Market.USA, OptionStyle.American, OptionRight.Call, strike, expiration);
|
||||
AddOptionContract(mirrorOption, resolution);
|
||||
|
||||
var impliedVolatility = IV(option, mirrorOption);
|
||||
var delta = D(option, mirrorOption, optionModel: OptionPricingModelType.BinomialCoxRossRubinstein, ivModel: OptionPricingModelType.BlackScholes);
|
||||
var gamma = G(option, mirrorOption, optionModel: OptionPricingModelType.ForwardTree, ivModel: OptionPricingModelType.BlackScholes);
|
||||
var vega = V(option, mirrorOption, optionModel: OptionPricingModelType.ForwardTree, ivModel: OptionPricingModelType.BlackScholes);
|
||||
var theta = T(option, mirrorOption, optionModel: OptionPricingModelType.ForwardTree, ivModel: OptionPricingModelType.BlackScholes);
|
||||
var rho = R(option, mirrorOption, optionModel: OptionPricingModelType.ForwardTree, ivModel: OptionPricingModelType.BlackScholes);
|
||||
|
||||
if (impliedVolatility == 0m || delta == 0m || gamma == 0m || vega == 0m || theta == 0m || rho == 0m)
|
||||
{
|
||||
throw new RegressionTestException("Expected IV/greeks calculated");
|
||||
}
|
||||
if (!impliedVolatility.IsReady || !delta.IsReady || !gamma.IsReady || !vega.IsReady || !theta.IsReady || !rho.IsReady)
|
||||
{
|
||||
throw new RegressionTestException("Expected IV/greeks to be ready");
|
||||
}
|
||||
|
||||
Quit($"Implied Volatility: {impliedVolatility}, Delta: {delta}, Gamma: {gamma}, Vega: {vega}, Theta: {theta}, Rho: {rho}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally => true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 18;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Portfolio Turnover", "0%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm which reproduces GH issue 3861, where in some cases 2 consolidators were added when
|
||||
/// using the automatic indicator warmup feature
|
||||
/// </summary>
|
||||
public class AutomaticIndicatorWarmupRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _spy;
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07);
|
||||
SetEndDate(2013, 10, 11);
|
||||
|
||||
Settings.AutomaticIndicatorWarmUp = true;
|
||||
|
||||
// Test case 1
|
||||
_spy = AddEquity("SPY").Symbol;
|
||||
var sma = SMA(_spy, 10);
|
||||
if (!sma.IsReady)
|
||||
{
|
||||
throw new RegressionTestException("Expected SMA to be warmed up");
|
||||
}
|
||||
|
||||
// Test case 2
|
||||
var indicator = new CustomIndicator(10);
|
||||
RegisterIndicator(_spy, indicator, Resolution.Minute, (Func<IBaseData, decimal>) null);
|
||||
|
||||
if (indicator.IsReady)
|
||||
{
|
||||
throw new RegressionTestException("Expected CustomIndicator Not to be warmed up");
|
||||
}
|
||||
WarmUpIndicator(_spy, indicator);
|
||||
if (!indicator.IsReady)
|
||||
{
|
||||
throw new RegressionTestException("Expected CustomIndicator to be warmed up");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="slice">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
var subscription = SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(_spy).First(config => config.TickType == TickType.Trade);
|
||||
|
||||
// we expect 1 consolidator per indicator
|
||||
if (subscription.Consolidators.Count != 2)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected consolidator count for subscription: {subscription.Consolidators.Count}");
|
||||
}
|
||||
SetHoldings(_spy, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private class CustomIndicator : SimpleMovingAverage
|
||||
{
|
||||
private IndicatorDataPoint _previous;
|
||||
public CustomIndicator(int period) : base(period)
|
||||
{
|
||||
}
|
||||
protected override decimal ComputeNextValue(IReadOnlyWindow<IndicatorDataPoint> window, IndicatorDataPoint input)
|
||||
{
|
||||
if (_previous != null && input.EndTime == _previous.EndTime)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected indicator double data point call: {_previous}");
|
||||
}
|
||||
_previous = input;
|
||||
return base.ComputeNextValue(window, input);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 3943;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 40;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "271.453%"},
|
||||
{"Drawdown", "2.200%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "101691.92"},
|
||||
{"Net Profit", "1.692%"},
|
||||
{"Sharpe Ratio", "8.854"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "67.459%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.005"},
|
||||
{"Beta", "0.996"},
|
||||
{"Annual Standard Deviation", "0.222"},
|
||||
{"Annual Variance", "0.049"},
|
||||
{"Information Ratio", "-14.565"},
|
||||
{"Tracking Error", "0.001"},
|
||||
{"Treynor Ratio", "1.97"},
|
||||
{"Total Fees", "$3.44"},
|
||||
{"Estimated Strategy Capacity", "$56000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "19.93%"},
|
||||
{"Drawdown Recovery", "3"},
|
||||
{"OrderListHash", "3da9fa60bf95b9ed148b95e02e0cfc9e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm asserting that security are automatically seeded by default
|
||||
/// </summary>
|
||||
public abstract class AutomaticSeedBaseRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
protected virtual bool ShouldHaveTradeData { get; }
|
||||
protected virtual bool ShouldHaveQuoteData { get; }
|
||||
protected virtual bool ShouldHaveOpenInterestData { get; }
|
||||
protected virtual List<string> SecuritiesToIgnoreForChecking => Enumerable.Empty<string>().ToList();
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
var gotTrades = false;
|
||||
var gotQuotes = false;
|
||||
var gotOpenInterest = false;
|
||||
|
||||
var securitiesToCheck = changes.AddedSecurities.Where(x => (!x.Symbol.IsCanonical() || x.Symbol.SecurityType == SecurityType.Future) && !SecuritiesToIgnoreForChecking.Contains(x.Symbol.Value)).ToList();
|
||||
|
||||
foreach (var addedSecurity in securitiesToCheck)
|
||||
{
|
||||
if (addedSecurity.Price == 0)
|
||||
{
|
||||
throw new RegressionTestException("Security was not seeded");
|
||||
}
|
||||
|
||||
if (!addedSecurity.HasData)
|
||||
{
|
||||
throw new RegressionTestException("Security does not have TradeBar or QuoteBar or OpenInterest data");
|
||||
}
|
||||
|
||||
gotTrades |= addedSecurity.Cache.GetData<TradeBar>() != null;
|
||||
gotQuotes |= addedSecurity.Cache.GetData<QuoteBar>() != null;
|
||||
gotOpenInterest |= addedSecurity.Cache.GetData<OpenInterest>() != null;
|
||||
}
|
||||
|
||||
if (securitiesToCheck.Count > 0)
|
||||
{
|
||||
if (ShouldHaveTradeData && !gotTrades)
|
||||
{
|
||||
throw new RegressionTestException("No contract had TradeBar data");
|
||||
}
|
||||
|
||||
if (ShouldHaveQuoteData && !gotQuotes)
|
||||
{
|
||||
throw new RegressionTestException("No contract had QuoteBar data");
|
||||
}
|
||||
|
||||
if (ShouldHaveOpenInterestData && !gotOpenInterest)
|
||||
{
|
||||
throw new RegressionTestException("No contract had OpenInterest data");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public abstract long DataPoints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public abstract int AlgorithmHistoryDataPoints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Portfolio Turnover", "0%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Data.Market;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Example algorithm using and asserting the behavior of auxiliary Data handlers
|
||||
/// </summary>
|
||||
public class AuxiliaryDataHandlersRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private bool _onSplits;
|
||||
private bool _onDividends;
|
||||
private bool _onDelistingsCalled;
|
||||
private bool _onSymbolChangedEvents;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2007, 05, 16);
|
||||
SetEndDate(2015, 1, 1);
|
||||
|
||||
UniverseSettings.Resolution = Resolution.Daily;
|
||||
|
||||
// will get delisted
|
||||
AddEquity("AAA.1");
|
||||
|
||||
// get's remapped
|
||||
AddEquity("SPWR");
|
||||
|
||||
// has a split & dividends
|
||||
AddEquity("AAPL");
|
||||
}
|
||||
|
||||
public override void OnDelistings(Delistings delistings)
|
||||
{
|
||||
if (!delistings.ContainsKey("AAA.1"))
|
||||
{
|
||||
throw new RegressionTestException("Unexpected OnDelistings call");
|
||||
}
|
||||
_onDelistingsCalled = true;
|
||||
}
|
||||
|
||||
public override void OnSymbolChangedEvents(SymbolChangedEvents symbolsChanged)
|
||||
{
|
||||
if (!symbolsChanged.ContainsKey("SPWR"))
|
||||
{
|
||||
throw new RegressionTestException("Unexpected OnSymbolChangedEvents call");
|
||||
}
|
||||
_onSymbolChangedEvents = true;
|
||||
}
|
||||
|
||||
public override void OnSplits(Splits splits)
|
||||
{
|
||||
if (!splits.ContainsKey("AAPL"))
|
||||
{
|
||||
throw new RegressionTestException("Unexpected OnSplits call");
|
||||
}
|
||||
_onSplits = true;
|
||||
}
|
||||
|
||||
public override void OnDividends(Dividends dividends)
|
||||
{
|
||||
if (!dividends.ContainsKey("AAPL"))
|
||||
{
|
||||
throw new RegressionTestException("Unexpected OnDividends call");
|
||||
}
|
||||
_onDividends = true;
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_onDelistingsCalled)
|
||||
{
|
||||
throw new RegressionTestException("OnDelistings was not called!");
|
||||
}
|
||||
if (!_onSymbolChangedEvents)
|
||||
{
|
||||
throw new RegressionTestException("OnSymbolChangedEvents was not called!");
|
||||
}
|
||||
if (!_onSplits)
|
||||
{
|
||||
throw new RegressionTestException("OnSplits was not called!");
|
||||
}
|
||||
if (!_onDividends)
|
||||
{
|
||||
throw new RegressionTestException("OnDividends was not called!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 15347;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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.332"},
|
||||
{"Tracking Error", "0.183"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Portfolio Turnover", "0%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm asserting that in backtesting, orders are submitted in the same time step even when asynchronous
|
||||
/// </summary>
|
||||
public class BacktestingAsynchronousOrdersRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _symbol;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07);
|
||||
SetEndDate(2013, 10, 08);
|
||||
SetCash(100000);
|
||||
|
||||
_symbol = AddEquity("SPY").Symbol;
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
var marketOrderTicket = MarketOrder(_symbol, 100, asynchronous: false);
|
||||
AssertMarketOrderStatus(marketOrderTicket);
|
||||
|
||||
var asyncMarketOrderTicket = MarketOrder(_symbol, -100, asynchronous: true);
|
||||
AssertMarketOrderStatus(asyncMarketOrderTicket);
|
||||
|
||||
var limitPrice = Securities[_symbol].Price * 0.95m;
|
||||
var limitOrderTicket = LimitOrder(_symbol, 100, limitPrice, asynchronous: false);
|
||||
AssertLimitOrderStatus(limitOrderTicket);
|
||||
|
||||
var asyncLimitOrderTicket = LimitOrder(_symbol, -100, limitPrice, asynchronous: true);
|
||||
AssertLimitOrderStatus(asyncLimitOrderTicket);
|
||||
}
|
||||
}
|
||||
|
||||
private static void AssertMarketOrderStatus(OrderTicket ticket)
|
||||
{
|
||||
// In backtesting the order should be submitted and filled right away.
|
||||
// Note that OrderSet event will not be fired if there is an error when processing the order submission,
|
||||
// but this is a happy case
|
||||
if (!ticket.OrderSet.WaitOne(0))
|
||||
{
|
||||
throw new RegressionTestException("Order was not submitted immediately in backtesting mode");
|
||||
}
|
||||
if (!ticket.OrderClosed.WaitOne(0))
|
||||
{
|
||||
throw new RegressionTestException("Order was not filled immediately in backtesting mode");
|
||||
}
|
||||
if (ticket.Status != OrderStatus.Filled)
|
||||
{
|
||||
throw new RegressionTestException($"Order status is not filled: {ticket.Status}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void AssertLimitOrderStatus(OrderTicket ticket)
|
||||
{
|
||||
// In backtesting the order should be submitted right away but not filled since price hasn't moved even when asynchronous
|
||||
// Note that OrderSet event will not be fired if there is an error when processing the order submission,
|
||||
// but this is a happy case
|
||||
if (!ticket.OrderSet.WaitOne(0))
|
||||
{
|
||||
throw new RegressionTestException("Asynchronous limit order was not submitted immediately in backtesting mode");
|
||||
}
|
||||
if (ticket.OrderClosed.WaitOne(0))
|
||||
{
|
||||
throw new RegressionTestException("Asynchronous limit order was filled immediately in backtesting mode when it shouldn't");
|
||||
}
|
||||
if (ticket.Status != OrderStatus.Submitted)
|
||||
{
|
||||
throw new RegressionTestException($"Order status is not submitted: {ticket.Status}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 1582;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "4"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100168.20"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "$3.00"},
|
||||
{"Estimated Strategy Capacity", "$22000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "21.72%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "65f010e904a929e5383f0920a3c5b797"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using QuantConnect.Orders.Fills;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Option;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This regression algorithm tests the order processing of the backtesting brokerage.
|
||||
/// We open an equity position that should fill in two parts, on two different bars.
|
||||
/// We open a long option position and let it expire so we can exercise the position.
|
||||
/// To check the orders we use OnOrderEvent and throw exceptions if verification fails.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="backtesting brokerage" />
|
||||
/// <meta name="tag" content="regression test" />
|
||||
/// <meta name="tag" content="options" />
|
||||
class BacktestingBrokerageRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Security _security;
|
||||
private Symbol _spy;
|
||||
private OrderTicket _equityBuy;
|
||||
private Option _option;
|
||||
private Symbol _optionSymbol;
|
||||
private OrderTicket _optionBuy;
|
||||
private bool _optionBought = false;
|
||||
private bool _equityBought = false;
|
||||
private decimal _optionStrikePrice;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the algorithm
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetCash(100000);
|
||||
SetStartDate(2015, 12, 24);
|
||||
SetEndDate(2015, 12, 28);
|
||||
|
||||
// Get our equity
|
||||
_security = AddEquity("SPY", Resolution.Hour);
|
||||
_security.SetFillModel(new PartialMarketFillModel(2));
|
||||
_spy = _security.Symbol;
|
||||
|
||||
// Get our option
|
||||
_option = AddOption("GOOG");
|
||||
_option.SetFilter(u => u.IncludeWeeklys()
|
||||
.Strikes(-2, +2)
|
||||
.Expiration(TimeSpan.Zero, TimeSpan.FromDays(10)));
|
||||
_optionSymbol = _option.Symbol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice data)
|
||||
{
|
||||
if (!_equityBought && data.ContainsKey(_spy))
|
||||
{
|
||||
//Buy our Equity.
|
||||
//Quantity is rounded down to an even number since it will be split in two equal halves
|
||||
var quantity = Math.Floor(CalculateOrderQuantity(_spy, .1m) / 2) * 2;
|
||||
_equityBuy = MarketOrder(_spy, quantity, asynchronous: true);
|
||||
_equityBought = true;
|
||||
}
|
||||
|
||||
if (!_optionBought)
|
||||
{
|
||||
// Buy our option
|
||||
OptionChain chain;
|
||||
if (data.OptionChains.TryGetValue(_optionSymbol, out chain))
|
||||
{
|
||||
// Find the second call strike under market price expiring today
|
||||
var contracts = (
|
||||
from optionContract in chain.OrderByDescending(x => x.Strike)
|
||||
where optionContract.Right == OptionRight.Call
|
||||
where optionContract.Expiry == Time.Date
|
||||
where optionContract.Strike < chain.Underlying.Price
|
||||
select optionContract
|
||||
).Take(2);
|
||||
|
||||
if (contracts.Any())
|
||||
{
|
||||
var optionToBuy = contracts.FirstOrDefault();
|
||||
_optionStrikePrice = optionToBuy.Strike;
|
||||
_optionBuy = MarketOrder(optionToBuy.Symbol, 1);
|
||||
_optionBought = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All order events get pushed through this function
|
||||
/// </summary>
|
||||
/// <param name="orderEvent">OrderEvent object that contains all the information about the event</param>
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
// Get the order from our transactions
|
||||
var order = Transactions.GetOrderById(orderEvent.OrderId);
|
||||
|
||||
// Based on the type verify the order
|
||||
switch (order.Type)
|
||||
{
|
||||
case OrderType.Market:
|
||||
VerifyMarketOrder(order, orderEvent);
|
||||
break;
|
||||
|
||||
case OrderType.OptionExercise:
|
||||
VerifyOptionExercise(order, orderEvent);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To verify Market orders is process correctly
|
||||
/// </summary>
|
||||
/// <param name="order">Order object to analyze</param>
|
||||
public void VerifyMarketOrder(Order order, OrderEvent orderEvent)
|
||||
{
|
||||
switch (order.Status)
|
||||
{
|
||||
case OrderStatus.Submitted:
|
||||
break;
|
||||
|
||||
// All PartiallyFilled orders should have a LastFillTime
|
||||
case OrderStatus.PartiallyFilled:
|
||||
if (order.LastFillTime == null)
|
||||
{
|
||||
throw new RegressionTestException("LastFillTime should not be null");
|
||||
}
|
||||
|
||||
if (order.Quantity / 2 != orderEvent.FillQuantity)
|
||||
{
|
||||
throw new RegressionTestException("Order size should be half");
|
||||
}
|
||||
break;
|
||||
|
||||
// All filled equity orders should have filled after creation because of our fill model!
|
||||
case OrderStatus.Filled:
|
||||
if (order.SecurityType == SecurityType.Equity && order.CreatedTime == order.LastFillTime)
|
||||
{
|
||||
throw new RegressionTestException("Order should not finish during the CreatedTime bar");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To verify OptionExercise orders is process correctly
|
||||
/// </summary>
|
||||
/// <param name="order">Order object to analyze</param>
|
||||
public void VerifyOptionExercise(Order order, OrderEvent orderEvent)
|
||||
{
|
||||
// If the option price isn't the same as the strike price, its incorrect
|
||||
if (order.Price != _optionStrikePrice)
|
||||
{
|
||||
throw new RegressionTestException("OptionExercise order price should be strike price!!");
|
||||
}
|
||||
|
||||
if (orderEvent.Quantity != -1)
|
||||
{
|
||||
throw new RegressionTestException("OrderEvent Quantity should be -1");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs after algorithm, used to check our portfolio and orders
|
||||
/// </summary>
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!Portfolio.ContainsKey(_optionBuy.Symbol) || !Portfolio.ContainsKey(_optionBuy.Symbol.Underlying) || !Portfolio.ContainsKey(_equityBuy.Symbol))
|
||||
{
|
||||
throw new RegressionTestException("Portfolio does not contain the Symbols we purchased");
|
||||
}
|
||||
|
||||
//Check option holding, should not be invested since it expired, profit should be -400
|
||||
var optionHolding = Portfolio[_optionBuy.Symbol];
|
||||
if (optionHolding.Invested || optionHolding.Profit != -400)
|
||||
{
|
||||
throw new RegressionTestException("Options holding does not match expected outcome");
|
||||
}
|
||||
|
||||
//Check the option underlying symbol since we should have bought it at exercise
|
||||
//Quantity should be 100, AveragePrice should be option strike price
|
||||
var optionExerciseHolding = Portfolio[_optionBuy.Symbol.Underlying];
|
||||
if (!optionExerciseHolding.Invested || optionExerciseHolding.Quantity != 100 || optionExerciseHolding.AveragePrice != _optionBuy.Symbol.ID.StrikePrice)
|
||||
{
|
||||
throw new RegressionTestException("Equity holding for exercised option does not match expected outcome");
|
||||
}
|
||||
|
||||
//Check equity holding, should be invested, profit should be
|
||||
//Quantity should be 52, AveragePrice should be ticket AverageFillPrice
|
||||
var equityHolding = Portfolio[_equityBuy.Symbol];
|
||||
if (!equityHolding.Invested || equityHolding.Quantity != 52 || equityHolding.AveragePrice != _equityBuy.AverageFillPrice)
|
||||
{
|
||||
throw new RegressionTestException("Equity holding does not match expected outcome");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PartialMarketFillModel that allows the user to set the number of fills and restricts
|
||||
/// the fill to only one per bar.
|
||||
/// </summary>
|
||||
private class PartialMarketFillModel : ImmediateFillModel
|
||||
{
|
||||
private readonly decimal _percent;
|
||||
private readonly Dictionary<long, decimal> _absoluteRemainingByOrderId = new Dictionary<long, decimal>();
|
||||
|
||||
/// <param name="numberOfFills"></param>
|
||||
public PartialMarketFillModel(int numberOfFills = 1)
|
||||
{
|
||||
_percent = 1m / numberOfFills;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs partial market fills once per time step
|
||||
/// </summary>
|
||||
/// <param name="asset">The security being ordered</param>
|
||||
/// <param name="order">The order</param>
|
||||
/// <returns>The order fill</returns>
|
||||
public override OrderEvent MarketFill(Security asset, MarketOrder order)
|
||||
{
|
||||
var currentUtcTime = asset.LocalTime.ConvertToUtc(asset.Exchange.TimeZone);
|
||||
|
||||
// Only fill once a time slice
|
||||
if (order.LastFillTime != null && currentUtcTime <= order.LastFillTime)
|
||||
{
|
||||
return new OrderEvent(order, currentUtcTime, OrderFee.Zero);
|
||||
}
|
||||
|
||||
decimal absoluteRemaining;
|
||||
if (!_absoluteRemainingByOrderId.TryGetValue(order.Id, out absoluteRemaining))
|
||||
{
|
||||
absoluteRemaining = order.AbsoluteQuantity;
|
||||
_absoluteRemainingByOrderId.Add(order.Id, order.AbsoluteQuantity);
|
||||
}
|
||||
|
||||
var fill = base.MarketFill(asset, order);
|
||||
var absoluteFillQuantity = (int)(Math.Min(absoluteRemaining, (int)(_percent * order.Quantity)));
|
||||
fill.FillQuantity = Math.Sign(order.Quantity) * absoluteFillQuantity;
|
||||
|
||||
if (absoluteRemaining == absoluteFillQuantity)
|
||||
{
|
||||
fill.Status = OrderStatus.Filled;
|
||||
_absoluteRemainingByOrderId.Remove(order.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
absoluteRemaining = absoluteRemaining - absoluteFillQuantity;
|
||||
_absoluteRemainingByOrderId[order.Id] = absoluteRemaining;
|
||||
fill.Status = OrderStatus.PartiallyFilled;
|
||||
}
|
||||
|
||||
return fill;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 27071;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "3"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.40%"},
|
||||
{"Compounding Annual Return", "119.386%"},
|
||||
{"Drawdown", "0.800%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "101082.06"},
|
||||
{"Net Profit", "1.082%"},
|
||||
{"Sharpe Ratio", "12.594"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "95.481%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.504"},
|
||||
{"Beta", "-6.672"},
|
||||
{"Annual Standard Deviation", "0.111"},
|
||||
{"Annual Variance", "0.012"},
|
||||
{"Information Ratio", "12.001"},
|
||||
{"Tracking Error", "0.127"},
|
||||
{"Treynor Ratio", "-0.209"},
|
||||
{"Total Fees", "$2.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"},
|
||||
{"Portfolio Turnover", "17.02%"},
|
||||
{"Drawdown Recovery", "4"},
|
||||
{"OrderListHash", "1be5073f2cf8802ffa163f7dab7d040e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract regression framework algorithm for multiple framework regression tests
|
||||
/// </summary>
|
||||
public abstract class BaseFrameworkRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2014, 6, 1);
|
||||
SetEndDate(2014, 6, 30);
|
||||
|
||||
UniverseSettings.Resolution = Resolution.Hour;
|
||||
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
|
||||
|
||||
var symbols = new[] { "AAPL", "AIG", "BAC", "SPY" }
|
||||
.Select(ticker => QuantConnect.Symbol.Create(ticker, SecurityType.Equity, Market.USA))
|
||||
.ToList();
|
||||
|
||||
// Manually add AAPL and AIG when the algorithm starts
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel(symbols.Take(2)));
|
||||
|
||||
// At midnight, add all securities every day except on the last data
|
||||
// With this procedure, the Alpha Model will experience multiple universe changes
|
||||
AddUniverseSelection(new ScheduledUniverseSelectionModel(
|
||||
DateRules.EveryDay(), TimeRules.Midnight,
|
||||
dt => dt < EndDate.AddDays(-1) ? symbols : Enumerable.Empty<Symbol>()));
|
||||
|
||||
SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromDays(31), 0.025, null));
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
SetRiskManagement(new NullRiskManagementModel());
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
// The base implementation checks for active insights
|
||||
var insightsCount = Insights.GetInsights(insight => insight.IsActive(UtcTime)).Count;
|
||||
if (insightsCount != 0)
|
||||
{
|
||||
throw new RegressionTestException($"The number of active insights should be 0. Actual: {insightsCount}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public virtual List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 764;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public virtual int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public abstract Dictionary<string, string> ExpectedStatistics { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Data;
|
||||
using Python.Runtime;
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
public class BasicPythonIntegrationTemplateAlgorithm : QCAlgorithm
|
||||
{
|
||||
// Create class field for numpy library
|
||||
private dynamic _numpy;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 7); // Set Start Date
|
||||
SetEndDate(2013, 10, 11); // Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
AddEquity("SPY", Resolution.Minute);
|
||||
|
||||
// Assign numpy library
|
||||
using (Py.GIL())
|
||||
{
|
||||
_numpy = Py.Import("numpy");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private decimal ComputeSin(decimal value)
|
||||
{
|
||||
// Calculate python sin(10)
|
||||
using (Py.GIL())
|
||||
{
|
||||
return (decimal)_numpy.sin(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// Slice object keyed by symbol containing the stock data
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings("SPY", 1);
|
||||
var sin = ComputeSin(10);
|
||||
|
||||
// Calculate C# sin(10)
|
||||
var sinOfTen = Math.Sin(10);
|
||||
Debug($"According to Python, the value of sin(10) is: {sin}");
|
||||
Debug($"According to C#, the value of sin(10) is: {sinOfTen}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Brokerages;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic algorithm using SetAccountCurrency
|
||||
/// </summary>
|
||||
public class BasicSetAccountCurrencyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _btcEur;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2018, 04, 04); //Set Start Date
|
||||
SetEndDate(2018, 04, 04); //Set End Date
|
||||
SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash);
|
||||
SetAccountCurrency();
|
||||
_btcEur = AddCrypto("BTCEUR").Symbol;
|
||||
}
|
||||
|
||||
public virtual void SetAccountCurrency()
|
||||
{
|
||||
//Before setting any cash or adding a Security call SetAccountCurrency
|
||||
SetAccountCurrency("EUR");
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings(_btcEur, 1);
|
||||
Debug("Purchased Stock");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 4319;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 15;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000.00"},
|
||||
{"End Equity", "92395.59"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "€298.35"},
|
||||
{"Estimated Strategy Capacity", "€85000.00"},
|
||||
{"Lowest Capacity Asset", "BTCEUR 2XR"},
|
||||
{"Portfolio Turnover", "107.64%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "6819dc936b86af6e4b89b6017b7d5284"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic algorithm using SetAccountCurrency with an amount
|
||||
/// </summary>
|
||||
public class BasicSetAccountCurrencyWithAmountAlgorithm : BasicSetAccountCurrencyAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
public override void SetAccountCurrency()
|
||||
{
|
||||
//Before setting any cash or adding a Security call SetAccountCurrency
|
||||
SetAccountCurrency("EUR", 200000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 4319;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 15;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "200000.00"},
|
||||
{"End Equity", "184791.19"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "€596.71"},
|
||||
{"Estimated Strategy Capacity", "€85000.00"},
|
||||
{"Lowest Capacity Asset", "BTCEUR 2XR"},
|
||||
{"Portfolio Turnover", "107.64%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "3d450fd418a0e845b3eaaac17fcd13fc"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic template algorithm simply initializes the date range and cash. This is a skeleton
|
||||
/// framework you can use for designing an algorithm.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="using quantconnect" />
|
||||
/// <meta name="tag" content="trading and orders" />
|
||||
public class BasicTemplateAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _spy = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07); //Set Start Date
|
||||
SetEndDate(2013, 10, 11); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
|
||||
// Find more symbols here: http://quantconnect.com/data
|
||||
// Forex, CFD, Equities Resolutions: Tick, Second, Minute, Hour, Daily.
|
||||
// Futures Resolution: Tick, Second, Minute
|
||||
// Options Resolution: Minute Only.
|
||||
AddEquity("SPY", Resolution.Minute);
|
||||
|
||||
// There are other assets with similar methods. See "Selecting Options" etc for more details.
|
||||
// AddFuture, AddForex, AddCfd, AddOption
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings(_spy, 1);
|
||||
Debug("Purchased Stock");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 3943;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "271.453%"},
|
||||
{"Drawdown", "2.200%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "101691.92"},
|
||||
{"Net Profit", "1.692%"},
|
||||
{"Sharpe Ratio", "8.854"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "67.459%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.005"},
|
||||
{"Beta", "0.996"},
|
||||
{"Annual Standard Deviation", "0.222"},
|
||||
{"Annual Variance", "0.049"},
|
||||
{"Information Ratio", "-14.565"},
|
||||
{"Tracking Error", "0.001"},
|
||||
{"Treynor Ratio", "1.97"},
|
||||
{"Total Fees", "$3.44"},
|
||||
{"Estimated Strategy Capacity", "$56000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "19.93%"},
|
||||
{"Drawdown Recovery", "3"},
|
||||
{"OrderListHash", "3da9fa60bf95b9ed148b95e02e0cfc9e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Brokerages;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic template algorithm for the Axos brokerage
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="using quantconnect" />
|
||||
/// <meta name="tag" content="trading and orders" />
|
||||
public class BasicTemplateAxosAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07);
|
||||
SetEndDate(2013, 10, 11);
|
||||
SetCash(100000);
|
||||
|
||||
SetBrokerageModel(BrokerageName.Axos);
|
||||
AddEquity("SPY", Resolution.Minute);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="slice">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
// will set 25% of our buying power with a market order
|
||||
SetHoldings("SPY", 0.25m);
|
||||
|
||||
Debug("Purchased SPY!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 3901;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "39.143%"},
|
||||
{"Drawdown", "0.500%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100423.24"},
|
||||
{"Net Profit", "0.423%"},
|
||||
{"Sharpe Ratio", "5.498"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "66.898%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0.055"},
|
||||
{"Annual Variance", "0.003"},
|
||||
{"Information Ratio", "5.634"},
|
||||
{"Tracking Error", "0.055"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$0.60"},
|
||||
{"Estimated Strategy Capacity", "$150000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "4.98%"},
|
||||
{"Drawdown Recovery", "3"},
|
||||
{"OrderListHash", "8774049eb5141a2b6956d9432426f837"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm demonstrating CFD asset types and requesting history.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="history" />
|
||||
/// <meta name="tag" content="cfd" />
|
||||
public class BasicTemplateCfdAlgorithm : QCAlgorithm
|
||||
{
|
||||
private Symbol _symbol;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetAccountCurrency("EUR");
|
||||
|
||||
SetStartDate(2019, 2, 20);
|
||||
SetEndDate(2019, 2, 21);
|
||||
SetCash("EUR", 100000);
|
||||
|
||||
_symbol = AddCfd("DE30EUR").Symbol;
|
||||
|
||||
// Historical Data
|
||||
var history = History(_symbol, 60, Resolution.Daily);
|
||||
Log($"Received {history.Count()} bars from CFD historical data call.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
// Access Data
|
||||
if (slice.QuoteBars.ContainsKey(_symbol))
|
||||
{
|
||||
var quoteBar = slice.QuoteBars[_symbol];
|
||||
Log($"{quoteBar.EndTime} :: {quoteBar.Close}");
|
||||
}
|
||||
|
||||
if (!Portfolio.Invested)
|
||||
SetHoldings(_symbol, 1);
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Debug($"{Time} {orderEvent.ToString()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Future;
|
||||
using Futures = QuantConnect.Securities.Futures;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic Continuous Futures Template Algorithm
|
||||
/// </summary>
|
||||
public class BasicTemplateContinuousFutureAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Future _continuousContract;
|
||||
private Security _currentContract;
|
||||
private SimpleMovingAverage _fast;
|
||||
private SimpleMovingAverage _slow;
|
||||
|
||||
// Minimum SMA gap required before acting on a cross; see the workaround note in OnData.
|
||||
private const decimal CrossThreshold = 0.001m;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 7, 1);
|
||||
SetEndDate(2014, 1, 1);
|
||||
|
||||
_continuousContract = AddFuture(Futures.Indices.SP500EMini,
|
||||
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
|
||||
dataMappingMode: DataMappingMode.LastTradingDay,
|
||||
contractDepthOffset: 0
|
||||
);
|
||||
|
||||
_fast = SMA(_continuousContract.Symbol, 4, Resolution.Daily);
|
||||
_slow = SMA(_continuousContract.Symbol, 10, Resolution.Daily);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
foreach (var changedEvent in slice.SymbolChangedEvents.Values)
|
||||
{
|
||||
Debug($"{Time} - SymbolChanged event: {changedEvent}");
|
||||
if (Time.TimeOfDay != TimeSpan.Zero)
|
||||
{
|
||||
throw new RegressionTestException($"{Time} unexpected symbol changed event {changedEvent}!");
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround so the C# and Python versions take the exact same trades on the limited
|
||||
// sample data in the repository (decimal vs double rounding can disagree at a cross).
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
if(_fast.Current.Value - _slow.Current.Value > CrossThreshold)
|
||||
{
|
||||
_currentContract = Securities[_continuousContract.Mapped];
|
||||
Buy(_currentContract.Symbol, 1);
|
||||
}
|
||||
}
|
||||
else if(_slow.Current.Value - _fast.Current.Value > CrossThreshold)
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
|
||||
// We check exchange hours because the contract mapping can call OnData outside of regular hours.
|
||||
if (_currentContract != null && _currentContract.Symbol != _continuousContract.Mapped && _continuousContract.Exchange.ExchangeOpen)
|
||||
{
|
||||
Log($"{Time} - rolling position from {_currentContract.Symbol} to {_continuousContract.Mapped}");
|
||||
|
||||
var currentPositionSize = _currentContract.Holdings.Quantity;
|
||||
Liquidate(_currentContract.Symbol);
|
||||
Buy(_continuousContract.Mapped, currentPositionSize);
|
||||
_currentContract = Securities[_continuousContract.Mapped];
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Debug($"{orderEvent}");
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
Debug($"{Time}-{changes}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 162575;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "9"},
|
||||
{"Average Win", "2.85%"},
|
||||
{"Average Loss", "-0.43%"},
|
||||
{"Compounding Annual Return", "11.019%"},
|
||||
{"Drawdown", "0.900%"},
|
||||
{"Expectancy", "2.818"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "105403.5"},
|
||||
{"Net Profit", "5.404%"},
|
||||
{"Sharpe Ratio", "1.531"},
|
||||
{"Sortino Ratio", "2.106"},
|
||||
{"Probabilistic Sharpe Ratio", "74.321%"},
|
||||
{"Loss Rate", "50%"},
|
||||
{"Win Rate", "50%"},
|
||||
{"Profit-Loss Ratio", "6.64"},
|
||||
{"Alpha", "0.067"},
|
||||
{"Beta", "0.009"},
|
||||
{"Annual Standard Deviation", "0.045"},
|
||||
{"Annual Variance", "0.002"},
|
||||
{"Information Ratio", "-1.606"},
|
||||
{"Tracking Error", "0.093"},
|
||||
{"Treynor Ratio", "7.237"},
|
||||
{"Total Fees", "$19.35"},
|
||||
{"Estimated Strategy Capacity", "$1000000000.00"},
|
||||
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
|
||||
{"Portfolio Turnover", "4.18%"},
|
||||
{"Drawdown Recovery", "19"},
|
||||
{"OrderListHash", "eb3bed9886f79a56c631225a6445adb2"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Future;
|
||||
using Futures = QuantConnect.Securities.Futures;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic Continuous Futures Template Algorithm with extended market hours
|
||||
/// </summary>
|
||||
public class BasicTemplateContinuousFutureWithExtendedMarketAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Future _continuousContract;
|
||||
private Security _currentContract;
|
||||
private SimpleMovingAverage _fast;
|
||||
private SimpleMovingAverage _slow;
|
||||
|
||||
// Minimum SMA gap required before acting on a cross; see the workaround note in OnData.
|
||||
private const decimal CrossThreshold = 0.001m;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 7, 1);
|
||||
SetEndDate(2014, 1, 1);
|
||||
|
||||
_continuousContract = AddFuture(Futures.Indices.SP500EMini,
|
||||
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
|
||||
dataMappingMode: DataMappingMode.LastTradingDay,
|
||||
contractDepthOffset: 0,
|
||||
extendedMarketHours: true
|
||||
);
|
||||
|
||||
_fast = SMA(_continuousContract.Symbol, 4, Resolution.Daily);
|
||||
_slow = SMA(_continuousContract.Symbol, 10, Resolution.Daily);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="slice">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
foreach (var changedEvent in slice.SymbolChangedEvents.Values)
|
||||
{
|
||||
Debug($"{Time} - SymbolChanged event: {changedEvent}");
|
||||
if (Time.TimeOfDay != TimeSpan.Zero)
|
||||
{
|
||||
throw new RegressionTestException($"{Time} unexpected symbol changed event {changedEvent}!");
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsMarketOpen(_continuousContract.Symbol))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// This is just to limit the amount of orders done in this regression test, since data in the repo is limited.
|
||||
// Also limit it to 3 orders so that the continuous contract rolls happens with an open position.
|
||||
if (Time < new DateTime(2013, 11, 12) && Transactions.OrdersCount < 3)
|
||||
{
|
||||
// Workaround so the C# and Python versions take the exact same trades on the limited
|
||||
// sample data in the repository (decimal vs double rounding can disagree at a cross).
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
if (_fast.Current.Value - _slow.Current.Value > CrossThreshold)
|
||||
{
|
||||
_currentContract = Securities[_continuousContract.Mapped];
|
||||
Buy(_currentContract.Symbol, 1);
|
||||
}
|
||||
}
|
||||
else if (_slow.Current.Value - _fast.Current.Value > CrossThreshold)
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
}
|
||||
|
||||
if (_currentContract != null && _currentContract.Symbol != _continuousContract.Mapped)
|
||||
{
|
||||
Log($"{Time} - rolling position from {_currentContract.Symbol} to {_continuousContract.Mapped}");
|
||||
|
||||
var currentPositionSize = _currentContract.Holdings.Quantity;
|
||||
Liquidate(_currentContract.Symbol);
|
||||
Buy(_continuousContract.Mapped, currentPositionSize);
|
||||
_currentContract = Securities[_continuousContract.Mapped];
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Debug($"{orderEvent}");
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
Debug($"{Time}-{changes}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 504530;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "3"},
|
||||
{"Average Win", "6.15%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "13.813%"},
|
||||
{"Drawdown", "1.400%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "106741.4"},
|
||||
{"Net Profit", "6.741%"},
|
||||
{"Sharpe Ratio", "2.003"},
|
||||
{"Sortino Ratio", "2.845"},
|
||||
{"Probabilistic Sharpe Ratio", "87.787%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.069"},
|
||||
{"Beta", "0.086"},
|
||||
{"Annual Standard Deviation", "0.044"},
|
||||
{"Annual Variance", "0.002"},
|
||||
{"Information Ratio", "-1.506"},
|
||||
{"Tracking Error", "0.086"},
|
||||
{"Treynor Ratio", "1.023"},
|
||||
{"Total Fees", "$6.45"},
|
||||
{"Estimated Strategy Capacity", "$3700000000.00"},
|
||||
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
|
||||
{"Portfolio Turnover", "1.37%"},
|
||||
{"Drawdown Recovery", "18"},
|
||||
{"OrderListHash", "764ab9f6ea662a60e41daedb9613b246"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Brokerages;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// The demonstration algorithm shows some of the most common order methods when working with Crypto assets.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="using quantconnect" />
|
||||
/// <meta name="tag" content="trading and orders" />
|
||||
public class BasicTemplateCryptoAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private ExponentialMovingAverage _fast;
|
||||
private ExponentialMovingAverage _slow;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2018, 4, 4); // Set Start Date
|
||||
SetEndDate(2018, 4, 4); // Set End Date
|
||||
|
||||
// Although typically real brokerages as GDAX only support a single account currency,
|
||||
// here we add both USD and EUR to demonstrate how to handle non-USD account currencies.
|
||||
// Set Strategy Cash (USD)
|
||||
SetCash(10000);
|
||||
|
||||
// Set Strategy Cash (EUR)
|
||||
// EUR/USD conversion rate will be updated dynamically
|
||||
SetCash("EUR", 10000);
|
||||
|
||||
// Add some coins as initial holdings
|
||||
// When connected to a real brokerage, the amount specified in SetCash
|
||||
// will be replaced with the amount in your actual account.
|
||||
SetCash("BTC", 1m);
|
||||
SetCash("ETH", 5m);
|
||||
|
||||
SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash);
|
||||
|
||||
// You can uncomment the following line when live trading with GDAX,
|
||||
// to ensure limit orders will only be posted to the order book and never executed as a taker (incurring fees).
|
||||
// Please note this statement has no effect in backtesting or paper trading.
|
||||
// DefaultOrderProperties = new GDAXOrderProperties { PostOnly = true };
|
||||
|
||||
// Find more symbols here: http://quantconnect.com/data
|
||||
AddCrypto("BTCUSD");
|
||||
AddCrypto("ETHUSD");
|
||||
AddCrypto("BTCEUR");
|
||||
var symbol = AddCrypto("LTCUSD").Symbol;
|
||||
|
||||
// create two moving averages
|
||||
_fast = EMA(symbol, 30, Resolution.Minute);
|
||||
_slow = EMA(symbol, 60, Resolution.Minute);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="slice">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (Portfolio.CashBook["EUR"].ConversionRate == 0
|
||||
|| Portfolio.CashBook["BTC"].ConversionRate == 0
|
||||
|| Portfolio.CashBook["ETH"].ConversionRate == 0
|
||||
|| Portfolio.CashBook["LTC"].ConversionRate == 0)
|
||||
{
|
||||
Log($"EUR conversion rate: {Portfolio.CashBook["EUR"].ConversionRate}");
|
||||
Log($"BTC conversion rate: {Portfolio.CashBook["BTC"].ConversionRate}");
|
||||
Log($"LTC conversion rate: {Portfolio.CashBook["LTC"].ConversionRate}");
|
||||
Log($"ETH conversion rate: {Portfolio.CashBook["ETH"].ConversionRate}");
|
||||
|
||||
throw new RegressionTestException("Conversion rate is 0");
|
||||
}
|
||||
if (Time.Hour == 1 && Time.Minute == 0)
|
||||
{
|
||||
// Sell all ETH holdings with a limit order at 1% above the current price
|
||||
var limitPrice = Math.Round(Securities["ETHUSD"].Price * 1.01m, 2);
|
||||
var quantity = Portfolio.CashBook["ETH"].Amount;
|
||||
LimitOrder("ETHUSD", -quantity, limitPrice);
|
||||
}
|
||||
else if (Time.Hour == 2 && Time.Minute == 0)
|
||||
{
|
||||
// Submit a buy limit order for BTC at 5% below the current price
|
||||
var usdTotal = Portfolio.CashBook["USD"].Amount;
|
||||
var limitPrice = Math.Round(Securities["BTCUSD"].Price * 0.95m, 2);
|
||||
// use only half of our total USD
|
||||
var quantity = usdTotal * 0.5m / limitPrice;
|
||||
LimitOrder("BTCUSD", quantity, limitPrice);
|
||||
}
|
||||
else if (Time.Hour == 2 && Time.Minute == 1)
|
||||
{
|
||||
// Get current USD available, subtracting amount reserved for buy open orders
|
||||
var usdTotal = Portfolio.CashBook["USD"].Amount;
|
||||
var usdReserved = Transactions.GetOpenOrders(x => x.Direction == OrderDirection.Buy && x.Type == OrderType.Limit)
|
||||
.Where(x => x.Symbol == "BTCUSD" || x.Symbol == "ETHUSD")
|
||||
.Sum(x => x.Quantity * ((LimitOrder) x).LimitPrice);
|
||||
var usdAvailable = usdTotal - usdReserved;
|
||||
|
||||
// Submit a marketable buy limit order for ETH at 1% above the current price
|
||||
var limitPrice = Math.Round(Securities["ETHUSD"].Price * 1.01m, 2);
|
||||
|
||||
// use all of our available USD
|
||||
var quantity = usdAvailable / limitPrice;
|
||||
|
||||
// this order will be rejected for insufficient funds
|
||||
LimitOrder("ETHUSD", quantity, limitPrice);
|
||||
|
||||
// use only half of our available USD
|
||||
quantity = usdAvailable * 0.5m / limitPrice;
|
||||
LimitOrder("ETHUSD", quantity, limitPrice);
|
||||
}
|
||||
else if (Time.Hour == 11 && Time.Minute == 0)
|
||||
{
|
||||
// Liquidate our BTC holdings (including the initial holding)
|
||||
SetHoldings("BTCUSD", 0m);
|
||||
}
|
||||
else if (Time.Hour == 12 && Time.Minute == 0)
|
||||
{
|
||||
// Submit a market buy order for 1 BTC using EUR
|
||||
Buy("BTCEUR", 1m);
|
||||
|
||||
// Submit a sell limit order at 10% above market price
|
||||
var limitPrice = Math.Round(Securities["BTCEUR"].Price * 1.1m, 2);
|
||||
LimitOrder("BTCEUR", -1, limitPrice);
|
||||
}
|
||||
else if (Time.Hour == 13 && Time.Minute == 0)
|
||||
{
|
||||
// Cancel the limit order if not filled
|
||||
Transactions.CancelOpenOrders("BTCEUR");
|
||||
}
|
||||
else if (Time.Hour > 13)
|
||||
{
|
||||
// To include any initial holdings, we read the LTC amount from the cashbook
|
||||
// instead of using Portfolio["LTCUSD"].Quantity
|
||||
|
||||
if (_fast > _slow)
|
||||
{
|
||||
if (Portfolio.CashBook["LTC"].Amount == 0)
|
||||
{
|
||||
Buy("LTCUSD", 10);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Portfolio.CashBook["LTC"].Amount > 0)
|
||||
{
|
||||
Liquidate("LTCUSD");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Debug(Time + " " + orderEvent);
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
Log($"{Time} - TotalPortfolioValue: {Portfolio.TotalPortfolioValue}");
|
||||
Log($"{Time} - CashBook: {Portfolio.CashBook}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 12965;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 35;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "12"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "31592.84"},
|
||||
{"End Equity", "30866.71"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "$85.34"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "BTCEUR 2XR"},
|
||||
{"Portfolio Turnover", "118.08%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "26b9a07ace86b6a0e0eb2ff8c168cee0"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Orders;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic template framework algorithm uses framework components to define the algorithm.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="using quantconnect" />
|
||||
/// <meta name="tag" content="trading and orders" />
|
||||
public class BasicTemplateFrameworkCryptoAlgorithm : QCAlgorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
// Set requested data resolution
|
||||
UniverseSettings.Resolution = Resolution.Minute;
|
||||
|
||||
SetStartDate(2016, 10, 7); //Set Start Date
|
||||
SetEndDate(2016, 10, 7); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
|
||||
// Find more symbols here: http://quantconnect.com/data
|
||||
// Forex, CFD, Equities Resolutions: Tick, Second, Minute, Hour, Daily.
|
||||
// Futures Resolution: Tick, Second, Minute
|
||||
// Options Resolution: Minute Only.
|
||||
|
||||
// set algorithm framework models
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel(QuantConnect.Symbol.Create("BTCUSD", SecurityType.Crypto, Market.GDAX)));
|
||||
SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, null));
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
SetRiskManagement(new NullRiskManagementModel());
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
if (orderEvent.Status.IsFill())
|
||||
{
|
||||
Debug($"Purchased Stock: {orderEvent.Symbol}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Brokerages;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Data.Market;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Securities.CryptoFuture;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Minute resolution regression algorithm trading Coin and USDT binance futures long and short asserting the behavior
|
||||
/// </summary>
|
||||
public class BasicTemplateCryptoFutureAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Dictionary<Symbol, int> _interestPerSymbol = new();
|
||||
private CryptoFuture _btcUsd;
|
||||
private CryptoFuture _adaUsdt;
|
||||
private ExponentialMovingAverage _fast;
|
||||
private ExponentialMovingAverage _slow;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2022, 12, 13); // Set Start Date
|
||||
SetEndDate(2022, 12, 13); // Set End Date
|
||||
|
||||
SetTimeZone(TimeZones.Utc);
|
||||
|
||||
try
|
||||
{
|
||||
SetBrokerageModel(BrokerageName.BinanceFutures, AccountType.Cash);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// expected, we don't allow cash account type
|
||||
}
|
||||
SetBrokerageModel(BrokerageName.BinanceFutures, AccountType.Margin);
|
||||
|
||||
_btcUsd = AddCryptoFuture("BTCUSD");
|
||||
_adaUsdt = AddCryptoFuture("ADAUSDT");
|
||||
|
||||
_fast = EMA(_btcUsd.Symbol, 30, Resolution.Minute);
|
||||
_slow = EMA(_btcUsd.Symbol, 60, Resolution.Minute);
|
||||
|
||||
_interestPerSymbol[_btcUsd.Symbol] = 0;
|
||||
_interestPerSymbol[_adaUsdt.Symbol] = 0;
|
||||
|
||||
// Default USD cash, set 1M but it wont be used
|
||||
SetCash(1000000);
|
||||
|
||||
// the amount of BTC we need to hold to trade 'BTCUSD'
|
||||
_btcUsd.BaseCurrency.SetAmount(0.005m);
|
||||
// the amount of USDT we need to hold to trade 'ADAUSDT'
|
||||
_adaUsdt.QuoteCurrency.SetAmount(200);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
var interestRates = slice.Get<MarginInterestRate>();
|
||||
foreach (var interestRate in interestRates)
|
||||
{
|
||||
_interestPerSymbol[interestRate.Key]++;
|
||||
|
||||
var cachedInterestRate = Securities[interestRate.Key].Cache.GetData<MarginInterestRate>();
|
||||
if (cachedInterestRate != interestRate.Value)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected cached margin interest rate for {interestRate.Key}!");
|
||||
}
|
||||
}
|
||||
|
||||
if (_fast > _slow)
|
||||
{
|
||||
if (!Portfolio.Invested && Transactions.OrdersCount == 0)
|
||||
{
|
||||
var ticket = Buy(_btcUsd.Symbol, 50);
|
||||
if (ticket.Status != OrderStatus.Invalid)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected valid order {ticket}, should fail due to margin not sufficient");
|
||||
}
|
||||
|
||||
Buy(_btcUsd.Symbol, 1);
|
||||
|
||||
var marginUsed = Portfolio.TotalMarginUsed;
|
||||
var btcUsdHoldings = _btcUsd.Holdings;
|
||||
|
||||
// Coin futures value is 100 USD
|
||||
var holdingsValueBtcUsd = 100;
|
||||
|
||||
if (Math.Abs(btcUsdHoldings.TotalSaleVolume - holdingsValueBtcUsd) > 1)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected TotalSaleVolume {btcUsdHoldings.TotalSaleVolume}");
|
||||
}
|
||||
if (Math.Abs(btcUsdHoldings.AbsoluteHoldingsCost - holdingsValueBtcUsd) > 1)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected holdings cost {btcUsdHoldings.HoldingsCost}");
|
||||
}
|
||||
if (_btcUsd.BuyingPowerModel.GetMaintenanceMargin(_btcUsd) != marginUsed)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected margin used {marginUsed}");
|
||||
}
|
||||
|
||||
Buy(_adaUsdt.Symbol, 1000);
|
||||
|
||||
marginUsed = Portfolio.TotalMarginUsed - marginUsed;
|
||||
var adaUsdtHoldings = _adaUsdt.Holdings;
|
||||
|
||||
// USDT/BUSD futures value is based on it's price
|
||||
var holdingsValueUsdt = _adaUsdt.Price * _adaUsdt.SymbolProperties.ContractMultiplier * 1000;
|
||||
|
||||
if (Math.Abs(adaUsdtHoldings.TotalSaleVolume - holdingsValueUsdt) > 1)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected TotalSaleVolume {adaUsdtHoldings.TotalSaleVolume}");
|
||||
}
|
||||
if (Math.Abs(adaUsdtHoldings.AbsoluteHoldingsCost - holdingsValueUsdt) > 1)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected holdings cost {adaUsdtHoldings.HoldingsCost}");
|
||||
}
|
||||
if (_adaUsdt.BuyingPowerModel.GetMaintenanceMargin(_adaUsdt) != marginUsed)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected margin used {marginUsed}");
|
||||
}
|
||||
|
||||
// position just opened should be just spread here
|
||||
var profit = Portfolio.TotalUnrealizedProfit;
|
||||
if ((5 - Math.Abs(profit)) < 0)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected TotalUnrealizedProfit {Portfolio.TotalUnrealizedProfit}");
|
||||
}
|
||||
|
||||
if (Portfolio.TotalProfit != 0)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected TotalProfit {Portfolio.TotalProfit}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// let's revert our position and double
|
||||
if (Time.Hour > 10 && Transactions.OrdersCount == 3)
|
||||
{
|
||||
Sell(_btcUsd.Symbol, 3);
|
||||
|
||||
var btcUsdHoldings = _btcUsd.Holdings;
|
||||
|
||||
if (Math.Abs(btcUsdHoldings.AbsoluteHoldingsCost - 100 * 2) > 1)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected holdings cost {btcUsdHoldings.HoldingsCost}");
|
||||
}
|
||||
|
||||
Sell(_adaUsdt.Symbol, 3000);
|
||||
|
||||
var adaUsdtHoldings = _adaUsdt.Holdings;
|
||||
|
||||
// USDT/BUSD futures value is based on it's price
|
||||
var holdingsValueUsdt = _adaUsdt.Price * _adaUsdt.SymbolProperties.ContractMultiplier * 2000;
|
||||
|
||||
if (Math.Abs(adaUsdtHoldings.AbsoluteHoldingsCost - holdingsValueUsdt) > 1)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected holdings cost {adaUsdtHoldings.HoldingsCost}");
|
||||
}
|
||||
|
||||
// position just opened should be just spread here
|
||||
var profit = Portfolio.TotalUnrealizedProfit;
|
||||
if ((5 - Math.Abs(profit)) < 0)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected TotalUnrealizedProfit {Portfolio.TotalUnrealizedProfit}");
|
||||
}
|
||||
// we barely did any difference on the previous trade
|
||||
if ((5 - Math.Abs(Portfolio.TotalProfit)) < 0)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected TotalProfit {Portfolio.TotalProfit}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (_interestPerSymbol[_adaUsdt.Symbol] != 1)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected interest rate count {_interestPerSymbol[_adaUsdt.Symbol]}");
|
||||
}
|
||||
|
||||
if (_interestPerSymbol[_btcUsd.Symbol] != 3)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected interest rate count {_interestPerSymbol[_btcUsd.Symbol]}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Debug(Time + " " + orderEvent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 7205;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "5"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "1000200.00"},
|
||||
{"End Equity", "1000278.02"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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.65"},
|
||||
{"Estimated Strategy Capacity", "$620000000.00"},
|
||||
{"Lowest Capacity Asset", "ADAUSDT 18R"},
|
||||
{"Portfolio Turnover", "0.16%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "dcc4f964b5549c753123848c32eaee41"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Brokerages;
|
||||
using QuantConnect.Data.Market;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Securities.CryptoFuture;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Hourly regression algorithm trading ADAUSDT binance futures long and short asserting the behavior
|
||||
/// </summary>
|
||||
public class BasicTemplateCryptoFutureHourlyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Dictionary<Symbol, int> _interestPerSymbol = new();
|
||||
private CryptoFuture _adaUsdt;
|
||||
private ExponentialMovingAverage _fast;
|
||||
private ExponentialMovingAverage _slow;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2022, 12, 13);
|
||||
SetEndDate(2022, 12, 13);
|
||||
|
||||
SetTimeZone(TimeZones.Utc);
|
||||
|
||||
try
|
||||
{
|
||||
SetBrokerageModel(BrokerageName.BinanceCoinFutures, AccountType.Cash);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// expected, we don't allow cash account type
|
||||
}
|
||||
SetBrokerageModel(BrokerageName.BinanceCoinFutures, AccountType.Margin);
|
||||
|
||||
_adaUsdt = AddCryptoFuture("ADAUSDT", Resolution.Hour);
|
||||
|
||||
_fast = EMA(_adaUsdt.Symbol, 3, Resolution.Hour);
|
||||
_slow = EMA(_adaUsdt.Symbol, 6, Resolution.Hour);
|
||||
|
||||
_interestPerSymbol[_adaUsdt.Symbol] = 0;
|
||||
|
||||
// Default USD cash, set 1M but it wont be used
|
||||
SetCash(1000000);
|
||||
|
||||
// the amount of USDT we need to hold to trade 'ADAUSDT'
|
||||
_adaUsdt.QuoteCurrency.SetAmount(200);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
var interestRates = slice.Get<MarginInterestRate>();
|
||||
foreach (var interestRate in interestRates)
|
||||
{
|
||||
_interestPerSymbol[interestRate.Key]++;
|
||||
|
||||
var cachedInterestRate = Securities[interestRate.Key].Cache.GetData<MarginInterestRate>();
|
||||
if (cachedInterestRate != interestRate.Value)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected cached margin interest rate for {interestRate.Key}!");
|
||||
}
|
||||
}
|
||||
|
||||
if (_fast > _slow)
|
||||
{
|
||||
if (!Portfolio.Invested && Transactions.OrdersCount == 0)
|
||||
{
|
||||
var ticket = Buy(_adaUsdt.Symbol, 100000);
|
||||
if (ticket.Status != OrderStatus.Invalid)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected valid order {ticket}, should fail due to margin not sufficient");
|
||||
}
|
||||
|
||||
Buy(_adaUsdt.Symbol, 1000);
|
||||
|
||||
var marginUsed = Portfolio.TotalMarginUsed;
|
||||
var adaUsdtHoldings = _adaUsdt.Holdings;
|
||||
|
||||
// USDT/BUSD futures value is based on it's price
|
||||
var holdingsValueUsdt = _adaUsdt.Price * _adaUsdt.SymbolProperties.ContractMultiplier * 1000;
|
||||
|
||||
if (Math.Abs(adaUsdtHoldings.TotalSaleVolume - holdingsValueUsdt) > 1)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected TotalSaleVolume {adaUsdtHoldings.TotalSaleVolume}");
|
||||
}
|
||||
if (Math.Abs(adaUsdtHoldings.AbsoluteHoldingsCost - holdingsValueUsdt) > 1)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected holdings cost {adaUsdtHoldings.HoldingsCost}");
|
||||
}
|
||||
if (_adaUsdt.BuyingPowerModel.GetMaintenanceMargin(_adaUsdt) != marginUsed)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected margin used {marginUsed}");
|
||||
}
|
||||
|
||||
// position just opened should be just spread here
|
||||
var profit = Portfolio.TotalUnrealizedProfit;
|
||||
if ((5 - Math.Abs(profit)) < 0)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected TotalUnrealizedProfit {Portfolio.TotalUnrealizedProfit}");
|
||||
}
|
||||
|
||||
if (Portfolio.TotalProfit != 0)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected TotalProfit {Portfolio.TotalProfit}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// let's revert our position and double
|
||||
if (Time.Hour > 10 && Transactions.OrdersCount == 2)
|
||||
{
|
||||
Sell(_adaUsdt.Symbol, 3000);
|
||||
|
||||
var adaUsdtHoldings = _adaUsdt.Holdings;
|
||||
|
||||
// USDT/BUSD futures value is based on it's price
|
||||
var holdingsValueUsdt = _adaUsdt.Price * _adaUsdt.SymbolProperties.ContractMultiplier * 2000;
|
||||
|
||||
if (Math.Abs(adaUsdtHoldings.AbsoluteHoldingsCost - holdingsValueUsdt) > 1)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected holdings cost {adaUsdtHoldings.HoldingsCost}");
|
||||
}
|
||||
|
||||
// position just opened should be just spread here
|
||||
var profit = Portfolio.TotalUnrealizedProfit;
|
||||
if ((5 - Math.Abs(profit)) < 0)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected TotalUnrealizedProfit {Portfolio.TotalUnrealizedProfit}");
|
||||
}
|
||||
// we barely did any difference on the previous trade
|
||||
if ((5 - Math.Abs(Portfolio.TotalProfit)) < 0)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected TotalProfit {Portfolio.TotalProfit}");
|
||||
}
|
||||
}
|
||||
|
||||
if (Time.Hour >= 22 && Transactions.OrdersCount == 3)
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (_interestPerSymbol[_adaUsdt.Symbol] != 1)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected interest rate count {_interestPerSymbol[_adaUsdt.Symbol]}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Debug(Time + " " + orderEvent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 50;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "3"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "1000200"},
|
||||
{"End Equity", "1000189.47"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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.61"},
|
||||
{"Estimated Strategy Capacity", "$460000000.00"},
|
||||
{"Lowest Capacity Asset", "ADAUSDT 18R"},
|
||||
{"Portfolio Turnover", "0.12%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "50a51d06d03a5355248a6bccef1ca521"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Demonstration of requesting daily resolution data for US Equities.
|
||||
/// This is a simple regression test algorithm using a skeleton algorithm and requesting daily data.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
public class BasicTemplateDailyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _spy = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 08); //Set Start Date
|
||||
SetEndDate(2013, 10, 17); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
// Find more symbols here: http://quantconnect.com/data
|
||||
AddEquity("SPY", Resolution.Daily);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="slice">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings(_spy, 1);
|
||||
Debug("Purchased Stock");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 72;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "424.375%"},
|
||||
{"Drawdown", "0.800%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "104486.22"},
|
||||
{"Net Profit", "4.486%"},
|
||||
{"Sharpe Ratio", "17.304"},
|
||||
{"Sortino Ratio", "35.217"},
|
||||
{"Probabilistic Sharpe Ratio", "96.710%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.249"},
|
||||
{"Beta", "1.015"},
|
||||
{"Annual Standard Deviation", "0.141"},
|
||||
{"Annual Variance", "0.02"},
|
||||
{"Information Ratio", "-19"},
|
||||
{"Tracking Error", "0.011"},
|
||||
{"Treynor Ratio", "2.403"},
|
||||
{"Total Fees", "$3.49"},
|
||||
{"Estimated Strategy Capacity", "$1200000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "10.01%"},
|
||||
{"Drawdown Recovery", "1"},
|
||||
{"OrderListHash", "70f21e930175a2ec9d465b21edc1b6d9"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Future;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This algorithm tests and demonstrates EUREX futures subscription and trading:
|
||||
/// - It tests contracts rollover by adding a continuous future and asserting that mapping happens at some point.
|
||||
/// - It tests basic trading by buying a contract and holding it until expiration.
|
||||
/// - It tests delisting and asserts the holdings are liquidated after that.
|
||||
/// </summary>
|
||||
public class BasicTemplateEurexFuturesAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Future _continuousContract;
|
||||
private Symbol _mappedSymbol;
|
||||
private Symbol _contractToTrade;
|
||||
private int _mappingsCount;
|
||||
private decimal _boughtQuantity;
|
||||
private decimal _liquidatedQuantity;
|
||||
private bool _delisted;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2024, 5, 30);
|
||||
SetEndDate(2024, 6, 23);
|
||||
|
||||
SetAccountCurrency(Currencies.EUR);
|
||||
SetCash(1000000);
|
||||
|
||||
_continuousContract = AddFuture(Futures.Indices.EuroStoxx50, Resolution.Minute,
|
||||
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
|
||||
dataMappingMode: DataMappingMode.FirstDayMonth,
|
||||
contractDepthOffset: 0);
|
||||
_continuousContract.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(180));
|
||||
_mappedSymbol = _continuousContract.Mapped;
|
||||
|
||||
var benchmark = AddIndex("SX5E");
|
||||
SetBenchmark(benchmark.Symbol);
|
||||
|
||||
var seeder = new FuncSecuritySeeder(GetLastKnownPrices);
|
||||
SetSecurityInitializer(security => seeder.SeedSecurity(security));
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
foreach (var changedEvent in slice.SymbolChangedEvents.Values)
|
||||
{
|
||||
if (++_mappingsCount > 1)
|
||||
{
|
||||
throw new RegressionTestException($"{Time} - Unexpected number of symbol changed events (mappings): {_mappingsCount}. " +
|
||||
$"Expected only 1.");
|
||||
}
|
||||
|
||||
Debug($"{Time} - SymbolChanged event: {changedEvent}");
|
||||
|
||||
if (changedEvent.OldSymbol != _mappedSymbol.ID.ToString())
|
||||
{
|
||||
throw new RegressionTestException($"{Time} - Unexpected symbol changed event old symbol: {changedEvent}");
|
||||
}
|
||||
|
||||
if (changedEvent.NewSymbol != _continuousContract.Mapped.ID.ToString())
|
||||
{
|
||||
throw new RegressionTestException($"{Time} - Unexpected symbol changed event new symbol: {changedEvent}");
|
||||
}
|
||||
|
||||
// Let's trade the previous mapped contract, so we can hold it until expiration for testing
|
||||
// (will be sooner than the new mapped contract)
|
||||
_contractToTrade = _mappedSymbol;
|
||||
_mappedSymbol = _continuousContract.Mapped;
|
||||
}
|
||||
|
||||
// Let's trade after the mapping is done
|
||||
if (_contractToTrade != null && _boughtQuantity == 0 && Securities[_contractToTrade].Exchange.ExchangeOpen)
|
||||
{
|
||||
Buy(_contractToTrade, 1);
|
||||
}
|
||||
|
||||
if (_contractToTrade != null && slice.Delistings.TryGetValue(_contractToTrade, out var delisting))
|
||||
{
|
||||
if (delisting.Type == DelistingType.Delisted)
|
||||
{
|
||||
_delisted = true;
|
||||
|
||||
if (Portfolio.Invested)
|
||||
{
|
||||
throw new RegressionTestException($"{Time} - Portfolio should not be invested after the traded contract is delisted.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
if (orderEvent.Symbol != _contractToTrade)
|
||||
{
|
||||
throw new RegressionTestException($"{Time} - Unexpected order event symbol: {orderEvent.Symbol}. Expected {_contractToTrade}");
|
||||
}
|
||||
|
||||
if (orderEvent.Direction == OrderDirection.Buy)
|
||||
{
|
||||
if (orderEvent.Status == OrderStatus.Filled)
|
||||
{
|
||||
if (_boughtQuantity != 0 && _liquidatedQuantity != 0)
|
||||
{
|
||||
throw new RegressionTestException($"{Time} - Unexpected buy order event status: {orderEvent.Status}");
|
||||
}
|
||||
_boughtQuantity = orderEvent.Quantity;
|
||||
}
|
||||
}
|
||||
else if (orderEvent.Direction == OrderDirection.Sell)
|
||||
{
|
||||
if (orderEvent.Status == OrderStatus.Filled)
|
||||
{
|
||||
if (_boughtQuantity <= 0 && _liquidatedQuantity != 0)
|
||||
{
|
||||
throw new RegressionTestException($"{Time} - Unexpected sell order event status: {orderEvent.Status}");
|
||||
}
|
||||
_liquidatedQuantity = orderEvent.Quantity;
|
||||
|
||||
if (_liquidatedQuantity != -_boughtQuantity)
|
||||
{
|
||||
throw new RegressionTestException($"{Time} - Unexpected liquidated quantity: {_liquidatedQuantity}. Expected: {-_boughtQuantity}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
foreach (var addedSecurity in changes.AddedSecurities)
|
||||
{
|
||||
if (addedSecurity.Symbol.SecurityType == SecurityType.Future && addedSecurity.Symbol.IsCanonical())
|
||||
{
|
||||
_mappedSymbol = _continuousContract.Mapped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (_mappingsCount == 0)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected number of symbol changed events (mappings): {_mappingsCount}. Expected 1.");
|
||||
}
|
||||
|
||||
if (!_delisted)
|
||||
{
|
||||
throw new RegressionTestException("Contract was not delisted");
|
||||
}
|
||||
|
||||
// Make sure we traded and that the position was liquidated on delisting
|
||||
if (_boughtQuantity <= 0 || _liquidatedQuantity >= 0)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected sold quantity: {_boughtQuantity} and liquidated quantity: {_liquidatedQuantity}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 94326;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.11%"},
|
||||
{"Compounding Annual Return", "-1.667%"},
|
||||
{"Drawdown", "0.100%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "998849.48"},
|
||||
{"Net Profit", "-0.115%"},
|
||||
{"Sharpe Ratio", "-34.455"},
|
||||
{"Sortino Ratio", "-57.336"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0.002"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-6.176"},
|
||||
{"Tracking Error", "0.002"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "€1.02"},
|
||||
{"Estimated Strategy Capacity", "€2300000000.00"},
|
||||
{"Lowest Capacity Asset", "FESX YJHOAMPYKRS5"},
|
||||
{"Portfolio Turnover", "0.40%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "ac9acc478ba1afe53993cdbb92f8ec6e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Skeleton algorithm demonstrating filling forward data through gaps and inconsistent data. By default LEAN fills the previous bar forward
|
||||
/// so you get regular bars.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
public class BasicTemplateFillForwardAlgorithm : QCAlgorithm
|
||||
{
|
||||
private Symbol _asur = QuantConnect.Symbol.Create("ASUR", SecurityType.Equity, Market.USA);
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 01); //Set Start Date
|
||||
SetEndDate(2013, 11, 30); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
// Find more symbols here: http://quantconnect.com/data
|
||||
AddSecurity(SecurityType.Equity, "ASUR", Resolution.Second);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="slice">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings(_asur, 1);
|
||||
Debug("Purchased Stock");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Data;
|
||||
using System;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm demonstrating FOREX asset types and requesting history on them in bulk. As FOREX uses
|
||||
/// QuoteBars you should request slices or
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="history and warm up" />
|
||||
/// <meta name="tag" content="history" />
|
||||
/// <meta name="tag" content="forex" />
|
||||
public class BasicTemplateForexAlgorithm : QCAlgorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2014, 5, 7); //Set Start Date
|
||||
SetEndDate(2014, 5, 15); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
// Find more symbols here: http://quantconnect.com/data
|
||||
AddForex("EURUSD");
|
||||
AddForex("NZDUSD");
|
||||
|
||||
var dailyHistory = History(5, Resolution.Daily);
|
||||
var hourHistory = History(5, Resolution.Hour);
|
||||
var minuteHistory = History(5, Resolution.Minute);
|
||||
var secondHistory = History(5, Resolution.Second);
|
||||
|
||||
// Log values from history request of second-resolution data
|
||||
foreach (var data in secondHistory)
|
||||
{
|
||||
foreach (var key in data.Keys)
|
||||
{
|
||||
Log(key.Value + ": " + data.Time + " > " + data[key].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings("EURUSD", .5);
|
||||
SetHoldings("NZDUSD", .5);
|
||||
Log(string.Join(", ", slice.Values));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic template framework algorithm uses framework components to define the algorithm.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="using quantconnect" />
|
||||
/// <meta name="tag" content="trading and orders" />
|
||||
public class BasicTemplateFrameworkAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
// Set requested data resolution
|
||||
UniverseSettings.Resolution = Resolution.Minute;
|
||||
|
||||
SetStartDate(2013, 10, 07); //Set Start Date
|
||||
SetEndDate(2013, 10, 11); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
|
||||
// Find more symbols here: http://quantconnect.com/data
|
||||
// Forex, CFD, Equities Resolutions: Tick, Second, Minute, Hour, Daily.
|
||||
// Futures Resolution: Tick, Second, Minute
|
||||
// Options Resolution: Minute Only.
|
||||
|
||||
// set algorithm framework models
|
||||
SetUniverseSelection(new ManualUniverseSelectionModel(QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA)));
|
||||
SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, null));
|
||||
|
||||
// We can define who often the EWPCM will rebalance if no new insight is submitted using:
|
||||
// Resolution Enum:
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel(Resolution.Daily));
|
||||
// TimeSpan
|
||||
// SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel(TimeSpan.FromDays(2)));
|
||||
// A Func<DateTime, DateTime>. In this case, we can use the pre-defined func at Expiry helper class
|
||||
// SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel(Expiry.EndOfWeek));
|
||||
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
SetRiskManagement(new MaximumDrawdownPercentPerSecurity(0.01m));
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
if (orderEvent.Status.IsFill())
|
||||
{
|
||||
Debug($"Purchased Stock: {orderEvent.Symbol}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public virtual List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 3943;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "3"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-1.01%"},
|
||||
{"Compounding Annual Return", "261.134%"},
|
||||
{"Drawdown", "2.200%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "101655.30"},
|
||||
{"Net Profit", "1.655%"},
|
||||
{"Sharpe Ratio", "8.472"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "66.693%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.091"},
|
||||
{"Beta", "1.006"},
|
||||
{"Annual Standard Deviation", "0.224"},
|
||||
{"Annual Variance", "0.05"},
|
||||
{"Information Ratio", "-33.445"},
|
||||
{"Tracking Error", "0.002"},
|
||||
{"Treynor Ratio", "1.885"},
|
||||
{"Total Fees", "$10.32"},
|
||||
{"Estimated Strategy Capacity", "$27000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "59.86%"},
|
||||
{"Drawdown Recovery", "3"},
|
||||
{"OrderListHash", "f209ed42701b0419858e0100595b40c0"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm demonstrating FutureOption asset types and requesting history.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="history" />
|
||||
/// <meta name="tag" content="future option" />
|
||||
public class BasicTemplateFutureOptionAlgorithm : QCAlgorithm
|
||||
{
|
||||
private Symbol _symbol;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2022, 1, 1);
|
||||
SetEndDate(2022, 2, 1);
|
||||
SetCash(100000);
|
||||
|
||||
var gold_futures = AddFuture(Futures.Metals.Gold, Resolution.Minute);
|
||||
gold_futures.SetFilter(0, 180);
|
||||
_symbol = gold_futures.Symbol;
|
||||
AddFutureOption(_symbol, universe => universe.Strikes(-5, +5)
|
||||
.CallsOnly()
|
||||
.BackMonth()
|
||||
.OnlyApplyFilterAtMarketOpen());
|
||||
|
||||
// Historical Data
|
||||
var history = History(_symbol, 60, Resolution.Daily);
|
||||
Log($"Received {history.Count()} bars from {_symbol} FutureOption historical data call.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
// Access Data
|
||||
foreach(var kvp in slice.OptionChains)
|
||||
{
|
||||
var underlyingFutureContract = kvp.Key.Underlying;
|
||||
var chain = kvp.Value;
|
||||
|
||||
if (chain.Count() == 0) continue;
|
||||
|
||||
foreach(var contract in chain)
|
||||
{
|
||||
Log($@"Canonical Symbol: {kvp.Key};
|
||||
Contract: {contract};
|
||||
Right: {contract.Right};
|
||||
Expiry: {contract.Expiry};
|
||||
Bid price: {contract.BidPrice};
|
||||
Ask price: {contract.AskPrice};
|
||||
Implied Volatility: {contract.ImpliedVolatility}");
|
||||
}
|
||||
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
var atmStrike = chain.OrderBy(x => Math.Abs(chain.Underlying.Price - x.Strike)).First().Strike;
|
||||
var selectedContract = chain.Where(x => x.Strike == atmStrike).OrderByDescending(x => x.Expiry).First();
|
||||
MarketOrder(selectedContract.Symbol, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Debug($"{Time} {orderEvent.ToString()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Future;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Example algorithm for trading continuous future
|
||||
/// </summary>
|
||||
public class BasicTemplateFutureRolloverAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Dictionary<Symbol, SymbolData> _symbolDataBySymbol = new();
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 8);
|
||||
SetEndDate(2013, 12, 10);
|
||||
SetCash(1000000);
|
||||
|
||||
var futures = new List<string> {
|
||||
Futures.Indices.SP500EMini
|
||||
};
|
||||
|
||||
foreach (var future in futures)
|
||||
{
|
||||
// Requesting data
|
||||
var continuousContract = AddFuture(future,
|
||||
resolution: Resolution.Daily,
|
||||
extendedMarketHours: true,
|
||||
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
|
||||
dataMappingMode: DataMappingMode.OpenInterest,
|
||||
contractDepthOffset: 0
|
||||
);
|
||||
|
||||
var symbolData = new SymbolData(this, continuousContract);
|
||||
_symbolDataBySymbol.Add(continuousContract.Symbol, symbolData);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="slice">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
foreach (var kvp in _symbolDataBySymbol)
|
||||
{
|
||||
var symbol = kvp.Key;
|
||||
var symbolData = kvp.Value;
|
||||
|
||||
// Call SymbolData.Update() method to handle new data slice received
|
||||
symbolData.Update(slice);
|
||||
|
||||
// Check if information in SymbolData class and new slice data are ready for trading
|
||||
if (!symbolData.IsReady || !slice.Bars.ContainsKey(symbol))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var emaCurrentValue = symbolData.EMA.Current.Value;
|
||||
if (emaCurrentValue < symbolData.Price && !symbolData.IsLong)
|
||||
{
|
||||
MarketOrder(symbolData.Mapped, 1);
|
||||
}
|
||||
else if (emaCurrentValue > symbolData.Price && !symbolData.IsShort)
|
||||
{
|
||||
MarketOrder(symbolData.Mapped, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstracted class object to hold information (state, indicators, methods, etc.) from a Symbol/Security in a multi-security algorithm
|
||||
/// </summary>
|
||||
public class SymbolData
|
||||
{
|
||||
private QCAlgorithm _algorithm;
|
||||
private Future _future;
|
||||
public ExponentialMovingAverage EMA { get; set; }
|
||||
public decimal Price { get; set; }
|
||||
public bool IsLong { get; set; }
|
||||
public bool IsShort { get; set; }
|
||||
public Symbol Symbol => _future.Symbol;
|
||||
public Symbol Mapped => _future.Mapped;
|
||||
|
||||
/// <summary>
|
||||
/// Check if symbolData class object are ready for trading
|
||||
/// </summary>
|
||||
public bool IsReady => Mapped != null && EMA.IsReady;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor to instantiate the information needed to be hold
|
||||
/// </summary>
|
||||
public SymbolData(QCAlgorithm algorithm, Future future)
|
||||
{
|
||||
_algorithm = algorithm;
|
||||
_future = future;
|
||||
EMA = algorithm.EMA(future.Symbol, 20, Resolution.Daily);
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler of new slice of data received
|
||||
/// </summary>
|
||||
public void Update(Slice slice)
|
||||
{
|
||||
if (slice.SymbolChangedEvents.TryGetValue(Symbol, out var changedEvent))
|
||||
{
|
||||
var oldSymbol = changedEvent.OldSymbol;
|
||||
var newSymbol = changedEvent.NewSymbol;
|
||||
var tag = $"Rollover - Symbol changed at {_algorithm.Time}: {oldSymbol} -> {newSymbol}";
|
||||
var quantity = _algorithm.Portfolio[oldSymbol].Quantity;
|
||||
|
||||
// Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
|
||||
_algorithm.Liquidate(oldSymbol, tag: tag);
|
||||
_algorithm.MarketOrder(newSymbol, quantity, tag: tag);
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
Price = slice.Bars.ContainsKey(Symbol) ? slice.Bars[Symbol].Price : Price;
|
||||
IsLong = _algorithm.Portfolio[Mapped].IsLong;
|
||||
IsShort = _algorithm.Portfolio[Mapped].IsShort;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset RollingWindow/indicator to adapt to newly mapped contract, then warm up the RollingWindow/indicator
|
||||
/// </summary>
|
||||
private void Reset()
|
||||
{
|
||||
EMA.Reset();
|
||||
_algorithm.WarmUpIndicator(Symbol, EMA, Resolution.Daily);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposal method to remove consolidator/update method handler, and reset RollingWindow/indicator to free up memory and speed
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
EMA.Reset();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 727;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 2;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "3"},
|
||||
{"Average Win", "0.14%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0.770%"},
|
||||
{"Drawdown", "0.100%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "1001341.4"},
|
||||
{"Net Profit", "0.134%"},
|
||||
{"Sharpe Ratio", "-0.494"},
|
||||
{"Sortino Ratio", "-0.544"},
|
||||
{"Probabilistic Sharpe Ratio", "23.043%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.015"},
|
||||
{"Beta", "0.03"},
|
||||
{"Annual Standard Deviation", "0.004"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-5.235"},
|
||||
{"Tracking Error", "0.081"},
|
||||
{"Treynor Ratio", "-0.069"},
|
||||
{"Total Fees", "$6.45"},
|
||||
{"Estimated Strategy Capacity", "$780000000000.00"},
|
||||
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
|
||||
{"Portfolio Turnover", "0.42%"},
|
||||
{"Drawdown Recovery", "3"},
|
||||
{"OrderListHash", "d17bbe62c86730e5178528a3153df0e6"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Future;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to add futures for a given underlying asset.
|
||||
/// It also shows how you can prefilter contracts easily based on expirations, and how you
|
||||
/// can inspect the futures chain to pick a specific contract to trade.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="benchmarks" />
|
||||
/// <meta name="tag" content="futures" />
|
||||
public class BasicTemplateFuturesAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _contractSymbol;
|
||||
|
||||
// S&P 500 EMini futures
|
||||
private const string RootSP500 = Futures.Indices.SP500EMini;
|
||||
|
||||
// Gold futures
|
||||
private const string RootGold = Futures.Metals.Gold;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize your algorithm and add desired assets.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 08);
|
||||
SetEndDate(2013, 10, 10);
|
||||
SetCash(1000000);
|
||||
|
||||
var futureSP500 = AddFuture(RootSP500);
|
||||
var futureGold = AddFuture(RootGold);
|
||||
|
||||
// set our expiry filter for this futures chain
|
||||
// SetFilter method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
futureSP500.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(182));
|
||||
futureGold.SetFilter(0, 182);
|
||||
|
||||
var benchmark = AddEquity("SPY");
|
||||
SetBenchmark(benchmark.Symbol);
|
||||
|
||||
var seeder = new FuncSecuritySeeder(GetLastKnownPrices);
|
||||
SetSecurityInitializer(security => seeder.SeedSecurity(security));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
|
||||
/// </summary>
|
||||
/// <param name="slice">The current slice of data keyed by symbol string</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
foreach (var changedEvent in slice.SymbolChangedEvents.Values)
|
||||
{
|
||||
Debug($"{Time} - SymbolChanged event: {changedEvent}");
|
||||
if (Time.TimeOfDay != TimeSpan.Zero)
|
||||
{
|
||||
throw new RegressionTestException($"{Time} unexpected symbol changed event {changedEvent}!");
|
||||
}
|
||||
}
|
||||
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
foreach(var chain in slice.FutureChains)
|
||||
{
|
||||
// find the front contract expiring no earlier than in 90 days
|
||||
var contract = (
|
||||
from futuresContract in chain.Value.OrderBy(x => x.Expiry)
|
||||
where futuresContract.Expiry > Time.Date.AddDays(90)
|
||||
select futuresContract
|
||||
).FirstOrDefault();
|
||||
|
||||
// if found, trade it
|
||||
if (contract != null)
|
||||
{
|
||||
_contractSymbol = contract.Symbol;
|
||||
MarketOrder(_contractSymbol, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
// Get the margin requirements
|
||||
var buyingPowerModel = Securities[_contractSymbol].BuyingPowerModel;
|
||||
var futureMarginModel = buyingPowerModel as FutureMarginModel;
|
||||
if (buyingPowerModel == null)
|
||||
{
|
||||
throw new RegressionTestException($"Invalid buying power model. Found: {buyingPowerModel.GetType().Name}. Expected: {nameof(FutureMarginModel)}");
|
||||
}
|
||||
var initialOvernight = futureMarginModel.InitialOvernightMarginRequirement;
|
||||
var maintenanceOvernight = futureMarginModel.MaintenanceOvernightMarginRequirement;
|
||||
var initialIntraday = futureMarginModel.InitialIntradayMarginRequirement;
|
||||
var maintenanceIntraday = futureMarginModel.MaintenanceIntradayMarginRequirement;
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
foreach (var addedSecurity in changes.AddedSecurities)
|
||||
{
|
||||
if (addedSecurity.Symbol.SecurityType == SecurityType.Future
|
||||
&& !addedSecurity.Symbol.IsCanonical()
|
||||
&& !addedSecurity.HasData)
|
||||
{
|
||||
throw new RegressionTestException($"Future contracts did not work up as expected: {addedSecurity.Symbol}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 40308;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 354;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2700"},
|
||||
{"Average Win", "0.00%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "-99.597%"},
|
||||
{"Drawdown", "4.400%"},
|
||||
{"Expectancy", "-0.724"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "955700.5"},
|
||||
{"Net Profit", "-4.430%"},
|
||||
{"Sharpe Ratio", "-31.63"},
|
||||
{"Sortino Ratio", "-31.63"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "83%"},
|
||||
{"Win Rate", "17%"},
|
||||
{"Profit-Loss Ratio", "0.65"},
|
||||
{"Alpha", "-3.065"},
|
||||
{"Beta", "0.128"},
|
||||
{"Annual Standard Deviation", "0.031"},
|
||||
{"Annual Variance", "0.001"},
|
||||
{"Information Ratio", "-81.232"},
|
||||
{"Tracking Error", "0.212"},
|
||||
{"Treynor Ratio", "-7.677"},
|
||||
{"Total Fees", "$6237.00"},
|
||||
{"Estimated Strategy Capacity", "$14000.00"},
|
||||
{"Lowest Capacity Asset", "GC VOFJUCDY9XNH"},
|
||||
{"Portfolio Turnover", "9912.69%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "6e0f767a46a54365287801295cf7bb75"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Securities;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data.Consolidators;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// A demonstration of consolidating futures data into larger bars for your algorithm.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="benchmarks" />
|
||||
/// <meta name="tag" content="consolidating data" />
|
||||
/// <meta name="tag" content="futures" />
|
||||
public class BasicTemplateFuturesConsolidationAlgorithm : QCAlgorithm
|
||||
{
|
||||
private const string RootSP500 = Futures.Indices.SP500EMini;
|
||||
private HashSet<Symbol> _futureContracts = new HashSet<Symbol>();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 8);
|
||||
SetEndDate(2013, 10, 11);
|
||||
SetCash(1000000);
|
||||
|
||||
var futureSP500 = AddFuture(RootSP500);
|
||||
// set our expiry filter for this future chain
|
||||
// SetFilter method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
futureSP500.SetFilter(0, 182);
|
||||
// futureSP500.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(182));
|
||||
|
||||
SetBenchmark(x => 0);
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
foreach (var chain in slice.FutureChains)
|
||||
{
|
||||
foreach (var contract in chain.Value)
|
||||
{
|
||||
if (!_futureContracts.Contains(contract.Symbol))
|
||||
{
|
||||
_futureContracts.Add(contract.Symbol);
|
||||
|
||||
var consolidator = new QuoteBarConsolidator(TimeSpan.FromMinutes(5));
|
||||
consolidator.DataConsolidated += OnDataConsolidated;
|
||||
SubscriptionManager.AddConsolidator(contract.Symbol, consolidator);
|
||||
|
||||
Log("Added new consolidator for " + contract.Symbol.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDataConsolidated(object sender, QuoteBar quoteBar)
|
||||
{
|
||||
Log("OnDataConsolidated called");
|
||||
Log(quoteBar.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Future;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to add futures with daily resolution.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="benchmarks" />
|
||||
/// <meta name="tag" content="futures" />
|
||||
public class BasicTemplateFuturesDailyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
protected virtual Resolution Resolution => Resolution.Daily;
|
||||
protected virtual bool ExtendedMarketHours => false;
|
||||
|
||||
// S&P 500 EMini futures
|
||||
private const string RootSP500 = Futures.Indices.SP500EMini;
|
||||
|
||||
// Gold futures
|
||||
private const string RootGold = Futures.Metals.Gold;
|
||||
private Future _futureSP500;
|
||||
private Future _futureGold;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize your algorithm and add desired assets.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 08);
|
||||
SetEndDate(2014, 10, 10);
|
||||
SetCash(1000000);
|
||||
|
||||
_futureSP500 = AddFuture(RootSP500, Resolution, extendedMarketHours: ExtendedMarketHours);
|
||||
_futureGold = AddFuture(RootGold, Resolution, extendedMarketHours: ExtendedMarketHours);
|
||||
|
||||
// set our expiry filter for this futures chain
|
||||
// SetFilter method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
_futureSP500.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(182));
|
||||
_futureGold.SetFilter(0, 182);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
|
||||
/// </summary>
|
||||
/// <param name="slice">The current slice of data keyed by symbol string</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
foreach(var chain in slice.FutureChains)
|
||||
{
|
||||
// find the front contract expiring no earlier than in 90 days
|
||||
var contract = (
|
||||
from futuresContract in chain.Value.OrderBy(x => x.Expiry)
|
||||
where futuresContract.Expiry > Time.Date.AddDays(90)
|
||||
select futuresContract
|
||||
).FirstOrDefault();
|
||||
|
||||
// if found, trade it.
|
||||
// Also check if exchange is open for regular or extended hours. Since daily data comes at 8PM, this allows us prevent the
|
||||
// algorithm from trading on friday when there is not after-market.
|
||||
if (contract != null)
|
||||
{
|
||||
MarketOrder(contract.Symbol, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Same as above, check for cases like trading on a friday night.
|
||||
else if (Securities.Values.Where(x => x.Invested).All(x => x.Exchange.Hours.IsOpen(Time, true)))
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
|
||||
foreach (var changedEvent in slice.SymbolChangedEvents.Values)
|
||||
{
|
||||
if (Time.TimeOfDay != TimeSpan.Zero)
|
||||
{
|
||||
throw new RegressionTestException($"{Time} unexpected symbol changed event {changedEvent}!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
if (changes.RemovedSecurities.Count > 0 &&
|
||||
Portfolio.Invested &&
|
||||
Securities.Values.Where(x => x.Invested).All(x => x.Exchange.Hours.IsOpen(Time, true)))
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public virtual bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public virtual List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 5876;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public virtual int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "22"},
|
||||
{"Average Win", "0.24%"},
|
||||
{"Average Loss", "-0.49%"},
|
||||
{"Compounding Annual Return", "-0.252%"},
|
||||
{"Drawdown", "0.300%"},
|
||||
{"Expectancy", "-0.258"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "997465.73"},
|
||||
{"Net Profit", "-0.253%"},
|
||||
{"Sharpe Ratio", "-5.753"},
|
||||
{"Sortino Ratio", "-1.032"},
|
||||
{"Probabilistic Sharpe Ratio", "0.000%"},
|
||||
{"Loss Rate", "50%"},
|
||||
{"Win Rate", "50%"},
|
||||
{"Profit-Loss Ratio", "0.48"},
|
||||
{"Alpha", "-0.009"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0.002"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-1.381"},
|
||||
{"Tracking Error", "0.089"},
|
||||
{"Treynor Ratio", "-19.581"},
|
||||
{"Total Fees", "$6.77"},
|
||||
{"Estimated Strategy Capacity", "$290000000.00"},
|
||||
{"Lowest Capacity Asset", "GC VOFJUCDY9XNH"},
|
||||
{"Portfolio Turnover", "0.12%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "140ff4560d532192be3041846667deca"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic template futures framework algorithm uses framework components to define an algorithm
|
||||
/// that trades futures.
|
||||
/// </summary>
|
||||
public class BasicTemplateFuturesFrameworkAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
protected virtual bool ExtendedMarketHours => false;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
UniverseSettings.Resolution = Resolution.Minute;
|
||||
UniverseSettings.ExtendedMarketHours = ExtendedMarketHours;
|
||||
|
||||
SetStartDate(2013, 10, 07);
|
||||
SetEndDate(2013, 10, 11);
|
||||
SetCash(100000);
|
||||
|
||||
// set framework models
|
||||
SetUniverseSelection(new FrontMonthFutureUniverseSelectionModel(SelectFutureChainSymbols));
|
||||
SetAlpha(new ConstantFutureContractAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromDays(1)));
|
||||
SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
SetRiskManagement(new NullRiskManagementModel());
|
||||
}
|
||||
|
||||
// future symbol universe selection function
|
||||
private static IEnumerable<Symbol> SelectFutureChainSymbols(DateTime utcTime)
|
||||
{
|
||||
var newYorkTime = utcTime.ConvertFromUtc(TimeZones.NewYork);
|
||||
if (newYorkTime.Date < new DateTime(2013, 10, 09))
|
||||
{
|
||||
yield return QuantConnect.Symbol.Create(Futures.Indices.SP500EMini, SecurityType.Future, Market.CME);
|
||||
}
|
||||
|
||||
if (newYorkTime.Date >= new DateTime(2013, 10, 09))
|
||||
{
|
||||
yield return QuantConnect.Symbol.Create(Futures.Metals.Gold, SecurityType.Future, Market.COMEX);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates futures chain universes that select the front month contract and runs a user
|
||||
/// defined futureChainSymbolSelector every day to enable choosing different futures chains
|
||||
/// </summary>
|
||||
class FrontMonthFutureUniverseSelectionModel : FutureUniverseSelectionModel
|
||||
{
|
||||
public FrontMonthFutureUniverseSelectionModel(Func<DateTime, IEnumerable<Symbol>> futureChainSymbolSelector)
|
||||
: base(TimeSpan.FromDays(1), futureChainSymbolSelector)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the future chain universe filter
|
||||
/// </summary>
|
||||
protected override FutureFilterUniverse Filter(FutureFilterUniverse filter)
|
||||
{
|
||||
return filter
|
||||
.FrontMonth()
|
||||
.OnlyApplyFilterAtMarketOpen();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of a constant alpha model that only emits insights for future symbols
|
||||
/// </summary>
|
||||
class ConstantFutureContractAlphaModel : ConstantAlphaModel
|
||||
{
|
||||
public ConstantFutureContractAlphaModel(InsightType type, InsightDirection direction, TimeSpan period)
|
||||
: base(type, direction, period)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool ShouldEmitInsight(DateTime utcTime, Symbol symbol)
|
||||
{
|
||||
// only emit alpha for future symbols and not underlying equity symbols
|
||||
if (symbol.SecurityType != SecurityType.Future)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.ShouldEmitInsight(utcTime, symbol);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Portfolio construction model that sets target quantities to 1 for up insights and -1 for down insights
|
||||
/// </summary>
|
||||
class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
|
||||
{
|
||||
public override IEnumerable<IPortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
|
||||
{
|
||||
foreach (var insight in insights)
|
||||
{
|
||||
yield return new PortfolioTarget(insight.Symbol, (int) insight.Direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public virtual bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public virtual List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 24883;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public virtual int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "-81.734%"},
|
||||
{"Drawdown", "4.100%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "97830.76"},
|
||||
{"Net Profit", "-2.169%"},
|
||||
{"Sharpe Ratio", "-10.299"},
|
||||
{"Sortino Ratio", "-10.299"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-1.212"},
|
||||
{"Beta", "0.238"},
|
||||
{"Annual Standard Deviation", "0.072"},
|
||||
{"Annual Variance", "0.005"},
|
||||
{"Information Ratio", "-15.404"},
|
||||
{"Tracking Error", "0.176"},
|
||||
{"Treynor Ratio", "-3.109"},
|
||||
{"Total Fees", "$4.62"},
|
||||
{"Estimated Strategy Capacity", "$17000000.00"},
|
||||
{"Lowest Capacity Asset", "GC VL5E74HP3EE5"},
|
||||
{"Portfolio Turnover", "43.23%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "c0fc1bcdc3008a8d263521bbc9d7cdbd"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic template futures framework algorithm uses framework components to define an algorithm
|
||||
/// that trades futures.
|
||||
/// </summary>
|
||||
public class BasicTemplateFuturesFrameworkWithExtendedMarketAlgorithm : BasicTemplateFuturesFrameworkAlgorithm
|
||||
{
|
||||
protected override bool ExtendedMarketHours => true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public override List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 70262;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "-92.667%"},
|
||||
{"Drawdown", "5.000%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "96685.76"},
|
||||
{"Net Profit", "-3.314%"},
|
||||
{"Sharpe Ratio", "-6.359"},
|
||||
{"Sortino Ratio", "-11.237"},
|
||||
{"Probabilistic Sharpe Ratio", "9.257%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-1.47"},
|
||||
{"Beta", "0.312"},
|
||||
{"Annual Standard Deviation", "0.134"},
|
||||
{"Annual Variance", "0.018"},
|
||||
{"Information Ratio", "-14.77"},
|
||||
{"Tracking Error", "0.192"},
|
||||
{"Treynor Ratio", "-2.742"},
|
||||
{"Total Fees", "$4.62"},
|
||||
{"Estimated Strategy Capacity", "$52000000.00"},
|
||||
{"Lowest Capacity Asset", "GC VL5E74HP3EE5"},
|
||||
{"Portfolio Turnover", "43.77%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "dcdaafcefa47465962ace2759ed99c91"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to get access to futures history for a given root symbol.
|
||||
/// It also shows how you can prefilter contracts easily based on expirations, and inspect the futures
|
||||
/// chain to pick a specific contract to trade.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="history and warm up" />
|
||||
/// <meta name="tag" content="history" />
|
||||
/// <meta name="tag" content="futures" />
|
||||
public class BasicTemplateFuturesHistoryAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
protected virtual bool ExtendedMarketHours => false;
|
||||
protected virtual int ExpectedHistoryCallCount => 42;
|
||||
|
||||
// S&P 500 EMini futures
|
||||
private string [] roots = new []
|
||||
{
|
||||
Futures.Indices.SP500EMini,
|
||||
Futures.Metals.Gold,
|
||||
};
|
||||
|
||||
private int _successCount = 0;
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 8);
|
||||
SetEndDate(2013, 10, 9);
|
||||
SetCash(1000000);
|
||||
|
||||
foreach (var root in roots)
|
||||
{
|
||||
// set our expiry filter for this futures chain
|
||||
AddFuture(root, Resolution.Minute, extendedMarketHours: ExtendedMarketHours).SetFilter(TimeSpan.Zero, TimeSpan.FromDays(182));
|
||||
}
|
||||
|
||||
SetBenchmark(d => 1000000);
|
||||
|
||||
Schedule.On(DateRules.EveryDay(), TimeRules.Every(TimeSpan.FromHours(1)), MakeHistoryCall);
|
||||
}
|
||||
|
||||
private void MakeHistoryCall()
|
||||
{
|
||||
var history = History(10, Resolution.Minute);
|
||||
if (history.Count() < 10)
|
||||
{
|
||||
throw new RegressionTestException($"Empty history at {Time}");
|
||||
}
|
||||
_successCount++;
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (_successCount < ExpectedHistoryCallCount)
|
||||
{
|
||||
throw new RegressionTestException($"Scheduled Event did not assert history call as many times as expected: {_successCount}/49");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
|
||||
/// </summary>
|
||||
/// <param name="slice">The current slice of data keyed by symbol string</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
foreach (var chain in slice.FutureChains)
|
||||
{
|
||||
foreach (var contract in chain.Value)
|
||||
{
|
||||
Log($"{contract.Symbol.Value}," +
|
||||
$"Bid={contract.BidPrice.ToStringInvariant()} " +
|
||||
$"Ask={contract.AskPrice.ToStringInvariant()} " +
|
||||
$"Last={contract.LastPrice.ToStringInvariant()} " +
|
||||
$"OI={contract.OpenInterest.ToStringInvariant()}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
foreach (var change in changes.AddedSecurities)
|
||||
{
|
||||
var history = History(change.Symbol, 10, Resolution.Minute);
|
||||
|
||||
foreach (var data in history.OrderByDescending(x => x.Time).Take(3))
|
||||
{
|
||||
Log("History: " + data.Symbol.Value + ": " + data.Time + " > " + data.Close);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Order fill event handler. On an order fill update the resulting information is passed to this method.
|
||||
/// </summary>
|
||||
/// <param name="orderEvent">Order event details containing details of the events</param>
|
||||
/// <remarks>This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects</remarks>
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Log(orderEvent.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public virtual bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public virtual List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 25316;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public virtual int AlgorithmHistoryDataPoints => 6075;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "1000000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Portfolio Turnover", "0%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to get access to futures history for a given root symbol with extended market hours.
|
||||
/// It also shows how you can prefilter contracts easily based on expirations, and inspect the futures
|
||||
/// chain to pick a specific contract to trade.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="history and warm up" />
|
||||
/// <meta name="tag" content="history" />
|
||||
/// <meta name="tag" content="futures" />
|
||||
public class BasicTemplateFuturesHistoryWithExtendedMarketHoursAlgorithm : BasicTemplateFuturesHistoryAlgorithm
|
||||
{
|
||||
protected override bool ExtendedMarketHours => true;
|
||||
protected override int ExpectedHistoryCallCount => 49;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public override List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 76063;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public override int AlgorithmHistoryDataPoints => 6112;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "1000000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Portfolio Turnover", "0%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This regressions tests the BasicTemplateFuturesDailyAlgorithm with hour data
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="benchmarks" />
|
||||
/// <meta name="tag" content="futures" />
|
||||
public class BasicTemplateFuturesHourlyAlgorithm : BasicTemplateFuturesDailyAlgorithm
|
||||
{
|
||||
protected override Resolution Resolution => Resolution.Hour;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public override List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 25409;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "66"},
|
||||
{"Average Win", "0.07%"},
|
||||
{"Average Loss", "-0.04%"},
|
||||
{"Compounding Annual Return", "0.296%"},
|
||||
{"Drawdown", "0.300%"},
|
||||
{"Expectancy", "0.213"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "1002984.28"},
|
||||
{"Net Profit", "0.298%"},
|
||||
{"Sharpe Ratio", "-0.872"},
|
||||
{"Sortino Ratio", "-0.342"},
|
||||
{"Probabilistic Sharpe Ratio", "6.244%"},
|
||||
{"Loss Rate", "53%"},
|
||||
{"Win Rate", "47%"},
|
||||
{"Profit-Loss Ratio", "1.59"},
|
||||
{"Alpha", "-0.005"},
|
||||
{"Beta", "-0.001"},
|
||||
{"Annual Standard Deviation", "0.005"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-1.325"},
|
||||
{"Tracking Error", "0.089"},
|
||||
{"Treynor Ratio", "4.124"},
|
||||
{"Total Fees", "$143.22"},
|
||||
{"Estimated Strategy Capacity", "$13000000.00"},
|
||||
{"Lowest Capacity Asset", "ES VP274HSU1AF5"},
|
||||
{"Portfolio Turnover", "1.86%"},
|
||||
{"Drawdown Recovery", "165"},
|
||||
{"OrderListHash", "12f89a137598802c39e71ee4bfdb522b"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Future;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to add futures for a given underlying asset.
|
||||
/// It also shows how you can prefilter contracts easily based on expirations, and how you
|
||||
/// can inspect the futures chain to pick a specific contract to trade.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="benchmarks" />
|
||||
/// <meta name="tag" content="futures" />
|
||||
public class BasicTemplateFuturesWithExtendedMarketAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _contractSymbol;
|
||||
|
||||
// S&P 500 EMini futures
|
||||
private const string RootSP500 = Futures.Indices.SP500EMini;
|
||||
|
||||
// Gold futures
|
||||
private const string RootGold = Futures.Metals.Gold;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize your algorithm and add desired assets.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 08);
|
||||
SetEndDate(2013, 10, 10);
|
||||
SetCash(1000000);
|
||||
|
||||
var futureSP500 = AddFuture(RootSP500, extendedMarketHours: true);
|
||||
var futureGold = AddFuture(RootGold, extendedMarketHours: true);
|
||||
|
||||
// set our expiry filter for this futures chain
|
||||
// SetFilter method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
futureSP500.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(182));
|
||||
futureGold.SetFilter(0, 182);
|
||||
|
||||
var benchmark = AddEquity("SPY");
|
||||
SetBenchmark(benchmark.Symbol);
|
||||
|
||||
var seeder = new FuncSecuritySeeder(GetLastKnownPrices);
|
||||
SetSecurityInitializer(security => seeder.SeedSecurity(security));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
|
||||
/// </summary>
|
||||
/// <param name="slice">The current slice of data keyed by symbol string</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
foreach (var changedEvent in slice.SymbolChangedEvents.Values)
|
||||
{
|
||||
Debug($"{Time} - SymbolChanged event: {changedEvent}");
|
||||
if (Time.TimeOfDay != TimeSpan.Zero)
|
||||
{
|
||||
throw new RegressionTestException($"{Time} unexpected symbol changed event {changedEvent}!");
|
||||
}
|
||||
}
|
||||
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
foreach(var chain in slice.FutureChains)
|
||||
{
|
||||
// find the front contract expiring no earlier than in 90 days
|
||||
var contract = (
|
||||
from futuresContract in chain.Value.OrderBy(x => x.Expiry)
|
||||
where futuresContract.Expiry > Time.Date.AddDays(90)
|
||||
select futuresContract
|
||||
).FirstOrDefault();
|
||||
|
||||
// if found, trade it
|
||||
if (contract != null)
|
||||
{
|
||||
_contractSymbol = contract.Symbol;
|
||||
MarketOrder(_contractSymbol, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
// Get the margin requirements
|
||||
var buyingPowerModel = Securities[_contractSymbol].BuyingPowerModel;
|
||||
var futureMarginModel = buyingPowerModel as FutureMarginModel;
|
||||
if (buyingPowerModel == null)
|
||||
{
|
||||
throw new RegressionTestException($"Invalid buying power model. Found: {buyingPowerModel.GetType().Name}. Expected: {nameof(FutureMarginModel)}");
|
||||
}
|
||||
var initialOvernight = futureMarginModel.InitialOvernightMarginRequirement;
|
||||
var maintenanceOvernight = futureMarginModel.MaintenanceOvernightMarginRequirement;
|
||||
var initialIntraday = futureMarginModel.InitialIntradayMarginRequirement;
|
||||
var maintenanceIntraday = futureMarginModel.MaintenanceIntradayMarginRequirement;
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
foreach (var addedSecurity in changes.AddedSecurities)
|
||||
{
|
||||
if (addedSecurity.Symbol.SecurityType == SecurityType.Future
|
||||
&& !addedSecurity.Symbol.IsCanonical()
|
||||
&& !addedSecurity.HasData)
|
||||
{
|
||||
throw new RegressionTestException($"Future contracts did not work up as expected: {addedSecurity.Symbol}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 117079;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 354;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "8282"},
|
||||
{"Average Win", "0.00%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "-100.000%"},
|
||||
{"Drawdown", "13.900%"},
|
||||
{"Expectancy", "-0.824"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "861260.7"},
|
||||
{"Net Profit", "-13.874%"},
|
||||
{"Sharpe Ratio", "-19.346"},
|
||||
{"Sortino Ratio", "-19.346"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "89%"},
|
||||
{"Win Rate", "11%"},
|
||||
{"Profit-Loss Ratio", "0.64"},
|
||||
{"Alpha", "2.468"},
|
||||
{"Beta", "-0.215"},
|
||||
{"Annual Standard Deviation", "0.052"},
|
||||
{"Annual Variance", "0.003"},
|
||||
{"Information Ratio", "-58.37"},
|
||||
{"Tracking Error", "0.295"},
|
||||
{"Treynor Ratio", "4.695"},
|
||||
{"Total Fees", "$19131.42"},
|
||||
{"Estimated Strategy Capacity", "$130000.00"},
|
||||
{"Lowest Capacity Asset", "GC VOFJUCDY9XNH"},
|
||||
{"Portfolio Turnover", "32523.20%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "0664a72652a19956ea3c4915269cc4b9"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to add futures with daily resolution and extended market hours.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="benchmarks" />
|
||||
/// <meta name="tag" content="futures" />
|
||||
public class BasicTemplateFuturesWithExtendedMarketDailyAlgorithm : BasicTemplateFuturesDailyAlgorithm
|
||||
{
|
||||
protected override bool ExtendedMarketHours => true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public override List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 5980;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "22"},
|
||||
{"Average Win", "0.24%"},
|
||||
{"Average Loss", "-0.49%"},
|
||||
{"Compounding Annual Return", "-0.252%"},
|
||||
{"Drawdown", "0.300%"},
|
||||
{"Expectancy", "-0.258"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "997465.73"},
|
||||
{"Net Profit", "-0.253%"},
|
||||
{"Sharpe Ratio", "-5.753"},
|
||||
{"Sortino Ratio", "-1.032"},
|
||||
{"Probabilistic Sharpe Ratio", "0.000%"},
|
||||
{"Loss Rate", "50%"},
|
||||
{"Win Rate", "50%"},
|
||||
{"Profit-Loss Ratio", "0.48"},
|
||||
{"Alpha", "-0.009"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0.002"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-1.381"},
|
||||
{"Tracking Error", "0.089"},
|
||||
{"Treynor Ratio", "-19.581"},
|
||||
{"Total Fees", "$6.77"},
|
||||
{"Estimated Strategy Capacity", "$290000000.00"},
|
||||
{"Lowest Capacity Asset", "GC VOFJUCDY9XNH"},
|
||||
{"Portfolio Turnover", "0.12%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "140ff4560d532192be3041846667deca"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This regressions tests the BasicTemplateFuturesDailyAlgorithm with hour data and extended market hours
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="benchmarks" />
|
||||
/// <meta name="tag" content="futures" />
|
||||
public class BasicTemplateFuturesWithExtendedMarketHourlyAlgorithm : BasicTemplateFuturesHourlyAlgorithm
|
||||
{
|
||||
protected override bool ExtendedMarketHours => true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public override List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 68170;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "170"},
|
||||
{"Average Win", "0.03%"},
|
||||
{"Average Loss", "-0.02%"},
|
||||
{"Compounding Annual Return", "-0.171%"},
|
||||
{"Drawdown", "0.800%"},
|
||||
{"Expectancy", "-0.100"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "998281.54"},
|
||||
{"Net Profit", "-0.172%"},
|
||||
{"Sharpe Ratio", "-1.251"},
|
||||
{"Sortino Ratio", "-0.548"},
|
||||
{"Probabilistic Sharpe Ratio", "2.934%"},
|
||||
{"Loss Rate", "65%"},
|
||||
{"Win Rate", "35%"},
|
||||
{"Profit-Loss Ratio", "1.61"},
|
||||
{"Alpha", "-0.007"},
|
||||
{"Beta", "-0.005"},
|
||||
{"Annual Standard Deviation", "0.006"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-1.354"},
|
||||
{"Tracking Error", "0.089"},
|
||||
{"Treynor Ratio", "1.669"},
|
||||
{"Total Fees", "$383.46"},
|
||||
{"Estimated Strategy Capacity", "$4800000.00"},
|
||||
{"Lowest Capacity Asset", "ES VP274HSU1AF5"},
|
||||
{"Portfolio Turnover", "4.89%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "fce6e574beb20c50ccfb1191dfade7f2"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic template algorithm simply initializes the date range and cash. This is a skeleton
|
||||
/// framework you can use for designing an algorithm.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="using quantconnect" />
|
||||
/// <meta name="tag" content="trading and orders" />
|
||||
public class BasicTemplateHourlyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _spy = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07); //Set Start Date
|
||||
SetEndDate(2013, 10, 11); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
|
||||
// Find more symbols here: http://quantconnect.com/data
|
||||
// Forex, CFD, Equities Resolutions: Tick, Second, Minute, Hour, Daily.
|
||||
// Futures Resolution: Tick, Second, Minute
|
||||
// Options Resolution: Minute Only.
|
||||
AddEquity("SPY", Resolution.Hour);
|
||||
|
||||
// There are other assets with similar methods. See "Selecting Options" etc for more details.
|
||||
// AddFuture, AddForex, AddCfd, AddOption
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="slice">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings(_spy, 1);
|
||||
Debug("Purchased Stock");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 78;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "227.693%"},
|
||||
{"Drawdown", "2.000%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "101529.08"},
|
||||
{"Net Profit", "1.529%"},
|
||||
{"Sharpe Ratio", "8.855"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "67.459%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.005"},
|
||||
{"Beta", "0.996"},
|
||||
{"Annual Standard Deviation", "0.222"},
|
||||
{"Annual Variance", "0.049"},
|
||||
{"Information Ratio", "-14.564"},
|
||||
{"Tracking Error", "0.001"},
|
||||
{"Treynor Ratio", "1.971"},
|
||||
{"Total Fees", "$3.44"},
|
||||
{"Estimated Strategy Capacity", "$110000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "19.96%"},
|
||||
{"Drawdown Recovery", "2"},
|
||||
{"OrderListHash", "60747dce5c2aed393b7dccc258d2c9b5"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Data;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to add index asset types.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="benchmarks" />
|
||||
/// <meta name="tag" content="indexes" />
|
||||
public class BasicTemplateIndexAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
protected Symbol Spx { get; set; }
|
||||
protected Symbol SpxOption { get; set; }
|
||||
private ExponentialMovingAverage _emaSlow;
|
||||
private ExponentialMovingAverage _emaFast;
|
||||
|
||||
protected virtual Resolution Resolution => Resolution.Minute;
|
||||
protected virtual int StartDay => 4;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize your algorithm and add desired assets.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2021, 1, StartDay);
|
||||
SetEndDate(2021, 1, 18);
|
||||
SetCash(1000000);
|
||||
|
||||
// Use indicator for signal; but it cannot be traded
|
||||
Spx = AddIndex("SPX", Resolution).Symbol;
|
||||
|
||||
// Trade on SPX ITM calls
|
||||
SpxOption = QuantConnect.Symbol.CreateOption(
|
||||
Spx,
|
||||
Market.USA,
|
||||
OptionStyle.European,
|
||||
OptionRight.Call,
|
||||
3200m,
|
||||
new DateTime(2021, 1, 15));
|
||||
|
||||
AddIndexOptionContract(SpxOption, Resolution);
|
||||
|
||||
_emaSlow = EMA(Spx, Resolution > Resolution.Minute ? 6 : 80);
|
||||
_emaFast = EMA(Spx, Resolution > Resolution.Minute ? 2 : 200);
|
||||
|
||||
Settings.DailyPreciseEndTime = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Index EMA Cross trading underlying.
|
||||
/// </summary>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!slice.Bars.ContainsKey(Spx) || !slice.Bars.ContainsKey(SpxOption))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Warm up indicators
|
||||
if (!_emaSlow.IsReady)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_emaFast > _emaSlow)
|
||||
{
|
||||
SetHoldings(SpxOption, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asserts indicators are ready
|
||||
/// </summary>
|
||||
/// <exception cref="RegressionTestException"></exception>
|
||||
protected void AssertIndicators()
|
||||
{
|
||||
if (!_emaSlow.IsReady || !_emaFast.IsReady)
|
||||
{
|
||||
throw new RegressionTestException("Indicators are not ready!");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (Portfolio[Spx].TotalSaleVolume > 0)
|
||||
{
|
||||
throw new RegressionTestException("Index is not tradable.");
|
||||
}
|
||||
AssertIndicators();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public virtual bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public virtual List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 16199;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public virtual int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "3"},
|
||||
{"Average Win", "7.08%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "603.355%"},
|
||||
{"Drawdown", "3.400%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "1064395"},
|
||||
{"Net Profit", "6.440%"},
|
||||
{"Sharpe Ratio", "-4.563"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0.604%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.169"},
|
||||
{"Beta", "0.073"},
|
||||
{"Annual Standard Deviation", "0.028"},
|
||||
{"Annual Variance", "0.001"},
|
||||
{"Information Ratio", "-6.684"},
|
||||
{"Tracking Error", "0.099"},
|
||||
{"Treynor Ratio", "-1.771"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$3000.00"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
|
||||
{"Portfolio Turnover", "23.97%"},
|
||||
{"Drawdown Recovery", "9"},
|
||||
{"OrderListHash", "4b560d2a8cfae510c3c8dc92603470fc"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data.Market;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression for running an Index algorithm with Daily data
|
||||
/// </summary>
|
||||
public class BasicTemplateIndexDailyAlgorithm : BasicTemplateIndexAlgorithm
|
||||
{
|
||||
protected override Resolution Resolution => Resolution.Daily;
|
||||
protected override int StartDay => 1;
|
||||
|
||||
// two complete weeks starting from the 5th. The 18th bar is not included since it is a holiday
|
||||
protected virtual int ExpectedBarCount => 2 * 5;
|
||||
protected int BarCounter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Purchase a contract when we are not invested, liquidate otherwise
|
||||
/// </summary>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
// SPX Index is not tradable, but we can trade an option
|
||||
MarketOrder(SpxOption, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
|
||||
// Count how many slices we receive with SPX data in it to assert later
|
||||
if (slice.ContainsKey(Spx))
|
||||
{
|
||||
BarCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (BarCounter != ExpectedBarCount)
|
||||
{
|
||||
throw new ArgumentException($"Bar Count {BarCounter} is not expected count of {ExpectedBarCount}");
|
||||
}
|
||||
AssertIndicators();
|
||||
|
||||
if (Resolution != Resolution.Daily)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var openInterest = Securities[SpxOption].Cache.GetAll<OpenInterest>();
|
||||
if (openInterest.Single().EndTime != new DateTime(2021, 1, 15, 15, 15, 0))
|
||||
{
|
||||
throw new ArgumentException($"Unexpected open interest time: {openInterest.Single().EndTime}");
|
||||
}
|
||||
|
||||
foreach (var symbol in new[] { SpxOption, Spx })
|
||||
{
|
||||
var history = History(symbol, 10).ToList();
|
||||
if (history.Count != 10)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected history count: {history.Count}");
|
||||
}
|
||||
if (history.Any(x => x.Time.TimeOfDay != new TimeSpan(8, 30, 0)))
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected history data start time");
|
||||
}
|
||||
if (history.Any(x => x.EndTime.TimeOfDay != new TimeSpan(15, 15, 0)))
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected history data end time");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public override bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public override List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 122;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public override int AlgorithmHistoryDataPoints => 30;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "11"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "653.545%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "1084600"},
|
||||
{"Net Profit", "8.460%"},
|
||||
{"Sharpe Ratio", "9.923"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "93.605%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "3.61"},
|
||||
{"Beta", "-0.513"},
|
||||
{"Annual Standard Deviation", "0.359"},
|
||||
{"Annual Variance", "0.129"},
|
||||
{"Information Ratio", "8.836"},
|
||||
{"Tracking Error", "0.392"},
|
||||
{"Treynor Ratio", "-6.937"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
|
||||
{"Portfolio Turnover", "2.42%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "ce421d0aeb7bde3bc92a6b87c09c510e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression for running an Index algorithm with Hourly data
|
||||
/// </summary>
|
||||
public class BasicTemplateIndexHourlyAlgorithm : BasicTemplateIndexDailyAlgorithm
|
||||
{
|
||||
protected override Resolution Resolution => Resolution.Hour;
|
||||
protected override int ExpectedBarCount => base.ExpectedBarCount * 8;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public override bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public override List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 401;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public override int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "19"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.11%"},
|
||||
{"Compounding Annual Return", "-18.082%"},
|
||||
{"Drawdown", "0.800%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "991995"},
|
||||
{"Net Profit", "-0.800%"},
|
||||
{"Sharpe Ratio", "-5.01"},
|
||||
{"Sortino Ratio", "-2.603"},
|
||||
{"Probabilistic Sharpe Ratio", "0.018%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.151"},
|
||||
{"Beta", "0.149"},
|
||||
{"Annual Standard Deviation", "0.027"},
|
||||
{"Annual Variance", "0.001"},
|
||||
{"Information Ratio", "-2.39"},
|
||||
{"Tracking Error", "0.097"},
|
||||
{"Treynor Ratio", "-0.917"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$1800000.00"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
|
||||
{"Portfolio Turnover", "5.58%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "1c7d841e0280e91b2297410fe2dbbc89"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using QuantConnect.Data;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to add index asset types and trade index options on SPX.
|
||||
/// </summary>
|
||||
public class BasicTemplateIndexOptionsAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _spx;
|
||||
private ExponentialMovingAverage _emaSlow;
|
||||
private ExponentialMovingAverage _emaFast;
|
||||
protected virtual Resolution Resolution => Resolution.Minute;
|
||||
protected virtual int StartDay => 4;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize your algorithm and add desired assets.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2021, 1, StartDay);
|
||||
SetEndDate(2021, 2, 1);
|
||||
SetCash(1000000);
|
||||
|
||||
// Use indicator for signal; but it cannot be traded.
|
||||
// We will instead trade on SPX options
|
||||
_spx = AddIndex("SPX", Resolution).Symbol;
|
||||
var spxOptions = AddIndexOption(_spx, Resolution);
|
||||
spxOptions.SetFilter(filterFunc => filterFunc.CallsOnly());
|
||||
|
||||
_emaSlow = EMA(_spx, Resolution > Resolution.Minute ? 6 : 80);
|
||||
_emaFast = EMA(_spx, Resolution > Resolution.Minute ? 2 : 200);
|
||||
|
||||
Settings.DailyPreciseEndTime = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Index EMA Cross trading index options of the index.
|
||||
/// </summary>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!slice.Bars.ContainsKey(_spx))
|
||||
{
|
||||
Debug($"No SPX on {Time}");
|
||||
return;
|
||||
}
|
||||
|
||||
// Warm up indicators
|
||||
if (!_emaSlow.IsReady)
|
||||
{
|
||||
Debug($"EMA slow not ready on {Time}");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var chain in slice.OptionChains.Values)
|
||||
{
|
||||
foreach (var contract in chain.Contracts.Values)
|
||||
{
|
||||
if (contract.Expiry.Month == 3 && contract.Symbol.ID.StrikePrice == 3700m && contract.Right == OptionRight.Call && slice.QuoteBars.ContainsKey(contract.Symbol))
|
||||
{
|
||||
Log($"{Time} {contract.Strike}{(contract.Right == OptionRight.Call ? 'C' : 'P')} -- {slice.QuoteBars[contract.Symbol]}");
|
||||
}
|
||||
|
||||
if (Portfolio.Invested)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_emaFast > _emaSlow && contract.Right == OptionRight.Call)
|
||||
{
|
||||
Liquidate(InvertOption(contract.Symbol));
|
||||
MarketOrder(contract.Symbol, 1);
|
||||
}
|
||||
else if (_emaFast < _emaSlow && contract.Right == OptionRight.Put)
|
||||
{
|
||||
Liquidate(InvertOption(contract.Symbol));
|
||||
MarketOrder(contract.Symbol, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (Portfolio[_spx].TotalSaleVolume > 0)
|
||||
{
|
||||
throw new RegressionTestException("Index is not tradable.");
|
||||
}
|
||||
if (Portfolio.TotalSaleVolume == 0)
|
||||
{
|
||||
throw new RegressionTestException("Trade volume should be greater than zero by the end of this algorithm");
|
||||
}
|
||||
AssertIndicators();
|
||||
}
|
||||
|
||||
public Symbol InvertOption(Symbol symbol)
|
||||
{
|
||||
return QuantConnect.Symbol.CreateOption(
|
||||
symbol.Underlying,
|
||||
symbol.ID.Market,
|
||||
symbol.ID.OptionStyle,
|
||||
symbol.ID.OptionRight == OptionRight.Call ? OptionRight.Put : OptionRight.Call,
|
||||
symbol.ID.StrikePrice,
|
||||
symbol.ID.Date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asserts indicators are ready
|
||||
/// </summary>
|
||||
/// <exception cref="RegressionTestException"></exception>
|
||||
protected void AssertIndicators()
|
||||
{
|
||||
if (!_emaSlow.IsReady || !_emaFast.IsReady)
|
||||
{
|
||||
throw new RegressionTestException("Indicators are not ready!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public virtual bool CanRunLocally { get; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public virtual List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 0;
|
||||
|
||||
/// </summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public virtual int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "8220"},
|
||||
{"Average Win", "0.00%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "-100.000%"},
|
||||
{"Drawdown", "13.500%"},
|
||||
{"Expectancy", "-0.818"},
|
||||
{"Net Profit", "-13.517%"},
|
||||
{"Sharpe Ratio", "-2.678"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "89%"},
|
||||
{"Win Rate", "11%"},
|
||||
{"Profit-Loss Ratio", "0.69"},
|
||||
{"Alpha", "4.398"},
|
||||
{"Beta", "-0.989"},
|
||||
{"Annual Standard Deviation", "0.373"},
|
||||
{"Annual Variance", "0.139"},
|
||||
{"Information Ratio", "-12.816"},
|
||||
{"Tracking Error", "0.504"},
|
||||
{"Treynor Ratio", "1.011"},
|
||||
{"Total Fees", "$15207.00"},
|
||||
{"Estimated Strategy Capacity", "$8800000.00"},
|
||||
{"Fitness Score", "0.033"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-8.62"},
|
||||
{"Return Over Maximum Drawdown", "-7.81"},
|
||||
{"Portfolio Turnover", "302.321"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
{"Long Insight Count", "0"},
|
||||
{"Short Insight Count", "0"},
|
||||
{"Long/Short Ratio", "100%"},
|
||||
{"Estimated Monthly Alpha Value", "$0"},
|
||||
{"Total Accumulated Estimated Alpha Value", "$0"},
|
||||
{"Mean Population Estimated Insight Value", "$0"},
|
||||
{"Mean Population Direction", "0%"},
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "35b3f4b7a225468d42ca085386a2383e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression for running an IndexOptions algorithm with Daily data
|
||||
/// </summary>
|
||||
public class BasicTemplateIndexOptionsDailyAlgorithm : BasicTemplateIndexOptionsAlgorithm
|
||||
{
|
||||
protected override Resolution Resolution => Resolution.Daily;
|
||||
protected override int StartDay => 1;
|
||||
|
||||
/// <summary>
|
||||
/// Index EMA Cross trading index options of the index.
|
||||
/// </summary>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
foreach (var chain in slice.OptionChains.Values)
|
||||
{
|
||||
// Select the contract with the lowest AskPrice
|
||||
var contract = chain.Contracts.OrderBy(x => x.Value.AskPrice).FirstOrDefault().Value;
|
||||
|
||||
if (contract == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Portfolio.Invested)
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
else
|
||||
{
|
||||
MarketOrder(contract.Symbol, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public override bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public override List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 360;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public override int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "11"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.01%"},
|
||||
{"Compounding Annual Return", "-0.092%"},
|
||||
{"Drawdown", "0.000%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "999920"},
|
||||
{"Net Profit", "-0.008%"},
|
||||
{"Sharpe Ratio", "-19.865"},
|
||||
{"Sortino Ratio", "-175397.15"},
|
||||
{"Probabilistic Sharpe Ratio", "0.000%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.003"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.454"},
|
||||
{"Tracking Error", "0.138"},
|
||||
{"Treynor Ratio", "-44.954"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P59H9OI6|SPX 31"},
|
||||
{"Portfolio Turnover", "0.00%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "34d295b82e29b1dbe8f104d3300d9255"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression for running an IndexOptions algorithm with Hourly data
|
||||
/// </summary>
|
||||
public class BasicTemplateIndexOptionsHourlyAlgorithm : BasicTemplateIndexOptionsDailyAlgorithm
|
||||
{
|
||||
protected override Resolution Resolution => Resolution.Hour;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public override bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public override List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 1269;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public override int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "19"},
|
||||
{"Average Win", "0.00%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0.000%"},
|
||||
{"Expectancy", "0.000"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "1000000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "-121.988"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0.162%"},
|
||||
{"Loss Rate", "88%"},
|
||||
{"Win Rate", "12%"},
|
||||
{"Profit-Loss Ratio", "7.00"},
|
||||
{"Alpha", "-0.002"},
|
||||
{"Beta", "-0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.449"},
|
||||
{"Tracking Error", "0.138"},
|
||||
{"Treynor Ratio", "83.436"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P59H9OI6|SPX 31"},
|
||||
{"Portfolio Turnover", "0.00%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "da45ce5558560c0b2a0d5feb2ad1a585"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Data;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic template India algorithm simply initializes the date range and cash. This is a skeleton
|
||||
/// framework you can use for designing an algorithm.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="using quantconnect" />
|
||||
/// <meta name="tag" content="trading and orders" />
|
||||
public class BasicTemplateIndiaAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetAccountCurrency("INR"); //Set Account Currency
|
||||
SetStartDate(2019, 1, 23); //Set Start Date
|
||||
SetEndDate(2019, 10, 31); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
|
||||
// Find more symbols here: http://quantconnect.com/data
|
||||
// Equities Resolutions: Tick, Second, Minute, Hour, Daily.
|
||||
AddEquity("YESBANK", Resolution.Minute, Market.India);
|
||||
|
||||
//Set Order Properties as per the requirements for order placement
|
||||
DefaultOrderProperties = new IndiaOrderProperties(exchange: Exchange.NSE);
|
||||
//override default productType value set in config.json if needed - order specific productType value
|
||||
//DefaultOrderProperties = new IndiaOrderProperties(exchange: Exchange.NSE, IndiaOrderProperties.IndiaProductType.CNC);
|
||||
|
||||
// General Debug statement for acknowledgement
|
||||
Debug("Initialization Done");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
var marketTicket = MarketOrder("YESBANK", 1);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
if (orderEvent.Status.IsFill())
|
||||
{
|
||||
Debug($"Purchased Complete: {orderEvent.Symbol}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 29524;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "-0.010%"},
|
||||
{"Drawdown", "0.000%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "99992.45"},
|
||||
{"Net Profit", "-0.008%"},
|
||||
{"Sharpe Ratio", "-497.389"},
|
||||
{"Sortino Ratio", "-73.22"},
|
||||
{"Probabilistic Sharpe Ratio", "0.794%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-1.183"},
|
||||
{"Tracking Error", "0"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "₹6.00"},
|
||||
{"Estimated Strategy Capacity", "₹61000000000.00"},
|
||||
{"Lowest Capacity Asset", "YESBANK UL"},
|
||||
{"Portfolio Turnover", "0.00%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "06f782c83dd633dac6f228b91273ba26"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Data;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to add index asset types.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="benchmarks" />
|
||||
/// <meta name="tag" content="indexes" />
|
||||
public class BasicTemplateIndiaIndexAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
protected Symbol Nifty { get; set; }
|
||||
protected Symbol NiftyETF { get; set; }
|
||||
private ExponentialMovingAverage _emaSlow;
|
||||
private ExponentialMovingAverage _emaFast;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize your algorithm and add desired assets.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetAccountCurrency("INR"); //Set Account Currency
|
||||
SetStartDate(2019, 1, 1); //Set End Date
|
||||
SetEndDate(2019, 1, 5); //Set End Date
|
||||
SetCash(1000000); //Set Strategy Cash
|
||||
|
||||
// Use indicator for signal; but it cannot be traded
|
||||
Nifty = AddIndex("NIFTY50", Resolution.Minute, Market.India).Symbol;
|
||||
|
||||
//Trade Index based ETF
|
||||
NiftyETF = AddEquity("JUNIORBEES", Resolution.Minute, Market.India).Symbol;
|
||||
|
||||
//Set Order Properties as per the requirements for order placement
|
||||
DefaultOrderProperties = new IndiaOrderProperties(exchange: Exchange.NSE);
|
||||
|
||||
_emaSlow = EMA(Nifty, 80);
|
||||
_emaFast = EMA(Nifty, 200);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Index EMA Cross trading underlying.
|
||||
/// </summary>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!slice.Bars.ContainsKey(Nifty) || !slice.Bars.ContainsKey(NiftyETF))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Warm up indicators
|
||||
if (!_emaSlow.IsReady)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_emaFast > _emaSlow)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
var marketTicket = MarketOrder(NiftyETF, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (Portfolio[Nifty].TotalSaleVolume > 0)
|
||||
{
|
||||
throw new RegressionTestException("Index is not tradable.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public virtual bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public virtual List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 2882;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "6"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "-0.386%"},
|
||||
{"Drawdown", "0.000%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "999961.17"},
|
||||
{"Net Profit", "-0.004%"},
|
||||
{"Sharpe Ratio", "-328.371"},
|
||||
{"Sortino Ratio", "-328.371"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-23.595"},
|
||||
{"Tracking Error", "0"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "₹36.00"},
|
||||
{"Estimated Strategy Capacity", "₹84000.00"},
|
||||
{"Lowest Capacity Asset", "JUNIORBEES UL"},
|
||||
{"Portfolio Turnover", "0.04%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "8790bec8175539e6d92e01608ac57733"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Custom.Intrinio;
|
||||
using QuantConnect.Indicators;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic template algorithm simply initializes the date range and cash. This is a skeleton
|
||||
/// framework you can use for designing an algorithm.
|
||||
/// </summary>
|
||||
/// <remarks>This regression test requires a valid Intrinio account</remarks>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="using quantconnect" />
|
||||
/// <meta name="tag" content="trading and orders" />
|
||||
public class BasicTemplateIntrinioEconomicData : QCAlgorithm
|
||||
{
|
||||
// Set your Intrinio user and password.
|
||||
private string _user = string.Empty;
|
||||
private string _password = string.Empty;
|
||||
|
||||
private Symbol _uso; // United States Oil Fund LP
|
||||
private Symbol _bno; // United States Brent Oil Fund LP
|
||||
|
||||
private readonly Identity _brent = new Identity("Brent");
|
||||
private readonly Identity _wti = new Identity("WTI");
|
||||
|
||||
private CompositeIndicator _spread;
|
||||
|
||||
private ExponentialMovingAverage _emaWti;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All
|
||||
/// algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(year: 2010, month: 01, day: 01); //Set Start Date
|
||||
SetEndDate(year: 2013, month: 12, day: 31); //Set End Date
|
||||
SetCash(startingCash: 100000); //Set Strategy Cash
|
||||
|
||||
// Set your Intrinio user and password.
|
||||
IntrinioConfig.SetUserAndPassword(_user, _password);
|
||||
|
||||
// Set Intrinio config to make 1 call each minute, default is 1 call each 5 seconds.
|
||||
// (1 call each minute is the free account limit for historical_data endpoint)
|
||||
IntrinioConfig.SetTimeIntervalBetweenCalls(TimeSpan.FromMinutes(1));
|
||||
|
||||
|
||||
// Find more symbols here: http://quantconnect.com/data
|
||||
// Forex, CFD, Equities Resolutions: Tick, Second, Minute, Hour, Daily.
|
||||
// Futures Resolution: Tick, Second, Minute
|
||||
// Options Resolution: Minute Only.
|
||||
_uso = AddEquity("USO", Resolution.Daily, leverage: 2m).Symbol;
|
||||
_bno = AddEquity("BNO", Resolution.Daily, leverage: 2m).Symbol;
|
||||
|
||||
AddData<IntrinioEconomicData>(IntrinioEconomicDataSources.Commodities.CrudeOilWTI, Resolution.Daily);
|
||||
AddData<IntrinioEconomicData>(IntrinioEconomicDataSources.Commodities.CrudeOilBrent, Resolution.Daily);
|
||||
_spread = _brent.Minus(_wti);
|
||||
|
||||
_emaWti = EMA(Securities[IntrinioEconomicDataSources.Commodities.CrudeOilWTI].Symbol, 10);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
var customData = slice.Get<IntrinioEconomicData>();
|
||||
if (customData.Count == 0) return;
|
||||
|
||||
foreach (var economicData in customData.Values)
|
||||
{
|
||||
if (economicData.Symbol.Value == IntrinioEconomicDataSources.Commodities.CrudeOilWTI)
|
||||
{
|
||||
_wti.Update(economicData.Time, economicData.Price);
|
||||
}
|
||||
else
|
||||
{
|
||||
_brent.Update(economicData.Time, economicData.Price);
|
||||
}
|
||||
}
|
||||
|
||||
if (_spread > 0 && !Portfolio[_bno].IsLong ||
|
||||
_spread < 0 && !Portfolio[_uso].IsShort)
|
||||
{
|
||||
var logText = _spread > 0 ?
|
||||
new[] {"higher", "long", "short"} :
|
||||
new[] {"lower", "short", "long"};
|
||||
|
||||
Log($"Brent Price is {logText[0]} than West Texas. Go {logText[1]} BNO and {logText[2]} USO. West Texas EMA: {_emaWti}");
|
||||
SetHoldings(_bno, 0.25 * Math.Sign(_spread));
|
||||
SetHoldings(_uso, -0.25 * Math.Sign(_spread));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "91"},
|
||||
{"Average Win", "0.09%"},
|
||||
{"Average Loss", "-0.01%"},
|
||||
{"Compounding Annual Return", "5.732%"},
|
||||
{"Drawdown", "4.800%"},
|
||||
{"Expectancy", "1.846"},
|
||||
{"Net Profit", "24.996%"},
|
||||
{"Sharpe Ratio", "1.142"},
|
||||
{"Loss Rate", "68%"},
|
||||
{"Win Rate", "32%"},
|
||||
{"Profit-Loss Ratio", "7.97"},
|
||||
{"Alpha", "0.076"},
|
||||
{"Beta", "-1.101"},
|
||||
{"Annual Standard Deviation", "0.048"},
|
||||
{"Annual Variance", "0.002"},
|
||||
{"Information Ratio", "0.741"},
|
||||
{"Tracking Error", "0.048"},
|
||||
{"Treynor Ratio", "-0.05"},
|
||||
{"Total Fees", "$102.64"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace QuantConnect
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic Template Library Class
|
||||
/// Library classes are snippets of code you can reuse between projects. They are added to projects on compile. This can be useful for reusing
|
||||
/// indicators, math components, risk modules etc. If you use a custom namespace make sure you add the correct using statement to the
|
||||
/// algorithm-user.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using quantconnect" />
|
||||
public class BasicTemplateLibrary
|
||||
{
|
||||
/*
|
||||
* To use this library; add its namespace at the top of the page:
|
||||
* using QuantConnect
|
||||
*
|
||||
* Then instantiate the class:
|
||||
* var btl = new BasicTemplateLibrary();
|
||||
* btl.Add(1,2)
|
||||
*/
|
||||
|
||||
public int Add(int a, int b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
|
||||
public int Subtract(int a, int b)
|
||||
{
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Option;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to create a multi asset class trading strategy.
|
||||
/// It is designed for test purposes and can be used with paper brokerage. All asset classes are not
|
||||
/// necessarily supported by some brokers. See our website for details.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="futures" />
|
||||
/// <meta name="tag" content="equity" />
|
||||
/// <meta name="tag" content="options" />
|
||||
public class BasicTemplateMultiAssetAlgorithm : QCAlgorithm
|
||||
{
|
||||
private int _barCount = 0;
|
||||
private Symbol _equitySymbol;
|
||||
private Symbol _forexSymbol;
|
||||
private Symbol _futureSymbol;
|
||||
private Symbol _optionSymbol;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2016, 01, 28);
|
||||
SetEndDate(2016, 02, 29);
|
||||
SetCash(1000000);
|
||||
|
||||
// setting up Microsoft Equity
|
||||
_equitySymbol = AddEquity("MSFT").Symbol;
|
||||
|
||||
// setting up EUR/USD FX spot pair
|
||||
_forexSymbol = AddForex("EURUSD").Symbol;
|
||||
|
||||
// setting up S&P 500 EMini futures
|
||||
var futureSP500 = AddFuture(Futures.Indices.SP500EMini);
|
||||
_futureSymbol = futureSP500.Symbol;
|
||||
|
||||
// set our expiry filter for this futures chain
|
||||
// SetFilter method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
futureSP500.SetFilter(10, 182);
|
||||
// futureSP500.SetFilter(TimeSpan.FromDays(10), TimeSpan.FromDays(182));
|
||||
|
||||
// setting up Dow Jones ETF Options
|
||||
var option = AddOption("DIA");
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.PriceModel = OptionPriceModels.BinomialCoxRossRubinstein();
|
||||
// option.EnableGreekApproximation = true;
|
||||
// set our strike/expiry filter for this option chain
|
||||
// SetFilter method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
option.SetFilter(-2, +2, 0, 180);
|
||||
// option.SetFilter(-2, +2, TimeSpan.Zero, TimeSpan.FromDays(180));
|
||||
|
||||
// specifying zero benchmark
|
||||
SetBenchmark(date => 0m);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
|
||||
/// </summary>
|
||||
/// <param name="slice">The current slice of data keyed by symbol string</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
_barCount++;
|
||||
|
||||
if (_barCount % 20 == 0)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
foreach (var chain in slice.FutureChains)
|
||||
{
|
||||
// find the front contract expiring no earlier than in 90 days
|
||||
var contract = (
|
||||
from futuresContract in chain.Value.OrderBy(x => x.Expiry)
|
||||
where futuresContract.Expiry > Time.Date.AddDays(90)
|
||||
select futuresContract
|
||||
).FirstOrDefault();
|
||||
|
||||
// if found, trade it
|
||||
if (contract != null)
|
||||
{
|
||||
MarketOrder(contract.Symbol, 1);
|
||||
}
|
||||
}
|
||||
|
||||
OptionChain optionChain;
|
||||
if (slice.OptionChains.TryGetValue(_optionSymbol, out optionChain))
|
||||
{
|
||||
// find a farthest ATM contract
|
||||
var contract = optionChain
|
||||
.OrderBy(x => Math.Abs(optionChain.Underlying.Price - x.Strike))
|
||||
.ThenByDescending(x => x.Expiry)
|
||||
.FirstOrDefault();
|
||||
|
||||
// if found, trade it
|
||||
if (contract != null)
|
||||
{
|
||||
MarketOrder(contract.Symbol, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// trade MSFT
|
||||
MarketOrder(_equitySymbol, 100);
|
||||
|
||||
// trade FX pair
|
||||
MarketOrder(_forexSymbol, 100000);
|
||||
}
|
||||
else
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
}
|
||||
|
||||
if (_barCount % 20 == 1)
|
||||
{
|
||||
Log($"P/L:{Portfolio.TotalUnrealisedProfit.ToStringInvariant("0.00")}, " +
|
||||
$"Fees:{Portfolio.TotalFees.ToStringInvariant("0.00")}, " +
|
||||
$"Profit:{Portfolio.TotalProfit.ToStringInvariant("0.00")}, " +
|
||||
$"Eq:{Portfolio.TotalPortfolioValue.ToStringInvariant("0.00")}, " +
|
||||
$"Holdings:{Portfolio.TotalHoldingsValue.ToStringInvariant("0.00")}, " +
|
||||
$"Vol: {Portfolio.TotalSaleVolume.ToStringInvariant("0.00")}, " +
|
||||
$"Margin: {Portfolio.TotalMarginUsed.ToStringInvariant("0.00")}"
|
||||
);
|
||||
|
||||
foreach (var holding in Securities.Values.OrderByDescending(x => x.Holdings.AbsoluteQuantity))
|
||||
{
|
||||
Log($" - {holding.Symbol.Value}, " +
|
||||
$"Avg Prc:{holding.Holdings.AveragePrice.ToStringInvariant("0.00")}, " +
|
||||
$"Qty:{holding.Holdings.Quantity.ToStringInvariant("0.00")}, " +
|
||||
$"Mkt Prc:{holding.Holdings.Price.ToStringInvariant("0.00")}, " +
|
||||
$"Mkt Val:{holding.Holdings.HoldingsValue.ToStringInvariant("0.00")}, " +
|
||||
$"Unreal P/L: {holding.Holdings.UnrealizedProfit.ToStringInvariant("0.00")}, " +
|
||||
$"Fees: {holding.Holdings.TotalFees.ToStringInvariant("0.00")}, " +
|
||||
$"Vol: {holding.Holdings.TotalSaleVolume.ToStringInvariant("0.00")}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (_barCount % 20 == 2)
|
||||
{
|
||||
foreach (var chain in slice.OptionChains)
|
||||
{
|
||||
var underlying = Securities[chain.Key.Underlying];
|
||||
foreach (var contract in chain.Value)
|
||||
{
|
||||
Log($"{Time.ToStringInvariant()} {contract.Symbol.Value}," +
|
||||
$"B={contract.BidPrice.ToStringInvariant()} " +
|
||||
$"A={contract.AskPrice.ToStringInvariant()} " +
|
||||
$"L={contract.LastPrice.ToStringInvariant()} " +
|
||||
$"OI={contract.OpenInterest.ToStringInvariant()} " +
|
||||
$"σ={underlying.VolatilityModel.Volatility:0.00} " +
|
||||
$"NPV={contract.TheoreticalPrice.ToStringInvariant("0.00")} " +
|
||||
$"Δ={contract.Greeks.Delta.ToStringInvariant("0.00")} " +
|
||||
$"Γ={contract.Greeks.Gamma.ToStringInvariant("0.00")} " +
|
||||
$"ν={contract.Greeks.Vega.ToStringInvariant("0.00")} " +
|
||||
$"ρ={contract.Greeks.Rho.ToStringInvariant("0.00")} " +
|
||||
$"Θ={(contract.Greeks.Theta / 365.0m).ToStringInvariant("0.00")} " +
|
||||
$"IV={contract.ImpliedVolatility.ToStringInvariant("0.00")}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var chain in slice.FutureChains)
|
||||
{
|
||||
foreach (var contract in chain.Value)
|
||||
{
|
||||
Log($"{contract.Symbol.Value}, {Time}, " +
|
||||
$"B={contract.BidPrice} " +
|
||||
$"A={contract.AskPrice} " +
|
||||
$"L={contract.LastPrice} " +
|
||||
$"OI={contract.OpenInterest}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var kpv in slice.QuoteBars)
|
||||
{
|
||||
Log($"---> QuoteBar: {Time}, {kpv.Key.Value}, {kpv.Value.Close:0.0000}");
|
||||
}
|
||||
|
||||
foreach (var kpv in slice.Bars)
|
||||
{
|
||||
Log($"---> Bar: {Time}, {kpv.Key.Value}, {kpv.Value.Close.ToStringInvariant("0.0000")}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Order fill event handler. On an order fill update the resulting information is passed to this method.
|
||||
/// </summary>
|
||||
/// <param name="orderEvent">Order event details containing details of the events</param>
|
||||
/// <remarks>This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects</remarks>
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Log(orderEvent.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Data.Market;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Securities.Option;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic template algorithm trading a Call Butterfly option equity strategy
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="options" />
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="using quantconnect" />
|
||||
/// <meta name="tag" content="trading and orders" />
|
||||
public class BasicTemplateOptionEquityStrategyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _optionSymbol;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2015, 12, 24);
|
||||
SetEndDate(2015, 12, 24);
|
||||
|
||||
var equity = AddEquity("GOOG", leverage: 4);
|
||||
var option = AddOption(equity.Symbol);
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
// set our strike/expiry filter for this option chain
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
|
||||
// Expiration method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
.Expiration(0, 180));
|
||||
}
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="slice">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
OptionChain chain;
|
||||
if (IsMarketOpen(_optionSymbol) && slice.OptionChains.TryGetValue(_optionSymbol, out chain))
|
||||
{
|
||||
var callContracts = chain.Where(contract => contract.Right == OptionRight.Call)
|
||||
.GroupBy(x => x.Expiry)
|
||||
.OrderBy(grouping => grouping.Key)
|
||||
.First()
|
||||
.OrderBy(x => x.Strike)
|
||||
.ToList();
|
||||
|
||||
var expiry = callContracts[0].Expiry;
|
||||
var lowerStrike = callContracts[0].Strike;
|
||||
var middleStrike = callContracts[1].Strike;
|
||||
var higherStrike = callContracts[2].Strike;
|
||||
|
||||
var optionStrategy = OptionStrategies.CallButterfly(_optionSymbol, higherStrike, middleStrike, lowerStrike, expiry);
|
||||
|
||||
Order(optionStrategy, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Order fill event handler. On an order fill update the resulting information is passed to this method.
|
||||
/// </summary>
|
||||
/// <param name="orderEvent">Order event details containing details of the events</param>
|
||||
/// <remarks>This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects</remarks>
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Log($"{orderEvent}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally => true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 15023;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "3"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "98024"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "$26.00"},
|
||||
{"Estimated Strategy Capacity", "$69000.00"},
|
||||
{"Lowest Capacity Asset", "GOOCV W78ZERHAT67A|GOOCV VP83T1ZUHROL"},
|
||||
{"Portfolio Turnover", "61.31%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "ccd6cb1b6244d0c6d30b2760938958f1"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities.Option;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This algorithm demonstrate how to use Option Strategies (e.g. OptionStrategies.Straddle) helper classes to batch send orders for common strategies.
|
||||
/// It also shows how you can prefilter contracts easily based on strikes and expirations, and how you can inspect the
|
||||
/// option chain to pick a specific option contract to trade.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="options" />
|
||||
/// <meta name="tag" content="option strategies" />
|
||||
/// <meta name="tag" content="filter selection" />
|
||||
public class BasicTemplateOptionStrategyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _optionSymbol;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2015, 12, 24);
|
||||
SetEndDate(2015, 12, 24);
|
||||
SetCash(1000000);
|
||||
|
||||
var option = AddOption("GOOG");
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
// set our strike/expiry filter for this option chain
|
||||
// SetFilter method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
option.SetFilter(u => u.StandardsOnly()
|
||||
.Strikes(-2, +2)
|
||||
.Expiration(0, 180));
|
||||
|
||||
// Adding this to reproduce GH issue #2314
|
||||
SetWarmup(TimeSpan.FromMinutes(1));
|
||||
|
||||
// use the underlying equity as the benchmark
|
||||
SetBenchmark("GOOG");
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
OptionChain chain;
|
||||
if (slice.OptionChains.TryGetValue(_optionSymbol, out chain))
|
||||
{
|
||||
var atmStraddle = chain
|
||||
.OrderBy(x => Math.Abs(chain.Underlying.Price - x.Strike))
|
||||
.ThenByDescending(x => x.Expiry)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (atmStraddle != null)
|
||||
{
|
||||
Sell(OptionStrategies.Straddle(_optionSymbol, atmStraddle.Strike, atmStraddle.Expiry), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
|
||||
foreach (var kpv in slice.Bars)
|
||||
{
|
||||
Log($"---> OnData: {Time}, {kpv.Key.Value}, {kpv.Value.Close:0.00}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Order fill event handler. On an order fill update the resulting information is passed to this method.
|
||||
/// </summary>
|
||||
/// <param name="orderEvent">Order event details containing details of the events</param>
|
||||
/// <remarks>This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects</remarks>
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Log(orderEvent.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 15130;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "420"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "952636.6"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "$543.40"},
|
||||
{"Estimated Strategy Capacity", "$4000.00"},
|
||||
{"Lowest Capacity Asset", "GOOCV W78ZFMEBFLDY|GOOCV VP83T1ZUHROL"},
|
||||
{"Portfolio Turnover", "338.60%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "8229716b93428dc885cf856b4cc9fc35"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Orders;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to add options for a given underlying equity security.
|
||||
/// It also shows how you can prefilter contracts easily based on strikes and expirations.
|
||||
/// It also shows how you can inspect the option chain to pick a specific option contract to trade.
|
||||
/// </summary>
|
||||
public class BasicTemplateOptionTradesAlgorithm : QCAlgorithm
|
||||
{
|
||||
private Symbol _optionSymbol;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2015, 12, 24);
|
||||
SetEndDate(2015, 12, 24);
|
||||
SetCash(10000);
|
||||
|
||||
var option = AddOption("GOOG");
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
// set our strike/expiry filter for this option chain
|
||||
// SetFilter method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yields the same filtering criteria
|
||||
option.SetFilter(-2, +2, 0, 10);
|
||||
// option.SetFilter(-2, +2, TimeSpan.Zero, TimeSpan.FromDays(10));
|
||||
|
||||
// use the underlying equity as the benchmark
|
||||
SetBenchmark("GOOG");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
|
||||
/// </summary>
|
||||
/// <param name="slice">The current slice of data keyed by symbol string</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
OptionChain chain;
|
||||
if (slice.OptionChains.TryGetValue(_optionSymbol, out chain))
|
||||
{
|
||||
// find the second call strike under market price expiring today
|
||||
var contract = chain
|
||||
.OrderBy(x => Math.Abs(chain.Underlying.Price - x.Strike))
|
||||
.ThenByDescending(x => x.Expiry)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (contract != null)
|
||||
{
|
||||
MarketOrder(contract.Symbol, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
|
||||
foreach (var kpv in slice.Bars)
|
||||
{
|
||||
Log($"---> OnData: {Time}, {kpv.Key.Value}, {kpv.Value.Close:0:00}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Order fill event handler. On an order fill update the resulting information is passed to this method.
|
||||
/// </summary>
|
||||
/// <param name="orderEvent">Order event details containing details of the events</param>
|
||||
/// <remarks>This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects</remarks>
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Log(orderEvent.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to add options for a given underlying equity security.
|
||||
/// It also shows how you can prefilter contracts easily based on strikes and expirations, and how you
|
||||
/// can inspect the option chain to pick a specific option contract to trade.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="options" />
|
||||
/// <meta name="tag" content="filter selection" />
|
||||
public class BasicTemplateOptionsAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private const string UnderlyingTicker = "GOOG";
|
||||
private Symbol _optionSymbol;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2015, 12, 24);
|
||||
SetEndDate(2015, 12, 24);
|
||||
SetCash(100000);
|
||||
|
||||
var equity = AddEquity(UnderlyingTicker);
|
||||
var option = AddOption(UnderlyingTicker);
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
// set our strike/expiry filter for this option chain
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
|
||||
// Expiration method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
.Expiration(0, 180)); // .Expiration(TimeSpan.Zero, TimeSpan.FromDays(180)));
|
||||
|
||||
// use the underlying equity as the benchmark
|
||||
SetBenchmark(equity.Symbol);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
|
||||
/// </summary>
|
||||
/// <param name="slice">The current slice of data keyed by symbol string</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested && IsMarketOpen(_optionSymbol))
|
||||
{
|
||||
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();
|
||||
|
||||
if (atmContract != null)
|
||||
{
|
||||
// if found, trade it
|
||||
MarketOrder(atmContract.Symbol, 1);
|
||||
MarketOnCloseOrder(atmContract.Symbol, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Order fill event handler. On an order fill update the resulting information is passed to this method.
|
||||
/// </summary>
|
||||
/// <param name="orderEvent">Order event details containing details of the events</param>
|
||||
/// <remarks>This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects</remarks>
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Log(orderEvent.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 15012;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "99718"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "$2.00"},
|
||||
{"Estimated Strategy Capacity", "$1300000.00"},
|
||||
{"Lowest Capacity Asset", "GOOCV 30AKMEIPOX2DI|GOOCV VP83T1ZUHROL"},
|
||||
{"Portfolio Turnover", "10.71%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "19ba1220073493495880581b38df2da9"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Consolidators;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// A demonstration of consolidating options data into larger bars for your algorithm.
|
||||
/// </summary>
|
||||
public class BasicTemplateOptionsConsolidationAlgorithm: QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Dictionary<Symbol, IDataConsolidator> _consolidators = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 7);
|
||||
SetEndDate(2013, 10, 11);
|
||||
SetCash(1000000);
|
||||
|
||||
var option = AddOption("SPY");
|
||||
option.SetFilter(-2, 2, 0, 189);
|
||||
}
|
||||
|
||||
public void OnQuoteBarConsolidated(object sender, QuoteBar quoteBar)
|
||||
{
|
||||
Log($"OnQuoteBarConsolidated called on {Time}");
|
||||
Log(quoteBar.ToString());
|
||||
}
|
||||
|
||||
public void OnTradeBarConsolidated(object sender, TradeBar tradeBar)
|
||||
{
|
||||
Log($"OnTradeBarConsolidated called on {Time}");
|
||||
Log(tradeBar.ToString());
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
foreach(var security in changes.AddedSecurities)
|
||||
{
|
||||
IDataConsolidator consolidator;
|
||||
if (security.Type == SecurityType.Equity)
|
||||
{
|
||||
consolidator = new TradeBarConsolidator(TimeSpan.FromMinutes(5));
|
||||
(consolidator as TradeBarConsolidator).DataConsolidated += OnTradeBarConsolidated;
|
||||
}
|
||||
else
|
||||
{
|
||||
consolidator = new QuoteBarConsolidator(new TimeSpan(0, 5, 0));
|
||||
(consolidator as QuoteBarConsolidator).DataConsolidated += OnQuoteBarConsolidated;
|
||||
}
|
||||
|
||||
SubscriptionManager.AddConsolidator(security.Symbol, consolidator);
|
||||
_consolidators[security.Symbol] = consolidator;
|
||||
}
|
||||
|
||||
foreach(var security in changes.RemovedSecurities)
|
||||
{
|
||||
_consolidators.Remove(security.Symbol, out var consolidator);
|
||||
SubscriptionManager.RemoveConsolidator(security.Symbol, consolidator);
|
||||
|
||||
if (security.Type == SecurityType.Equity)
|
||||
{
|
||||
(consolidator as TradeBarConsolidator).DataConsolidated -= OnTradeBarConsolidated;
|
||||
}
|
||||
else
|
||||
{
|
||||
(consolidator as QuoteBarConsolidator).DataConsolidated -= OnQuoteBarConsolidated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 3943;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "1000000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic 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", "-8.91"},
|
||||
{"Tracking Error", "0.223"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Portfolio Turnover", "0%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to add options for a given underlying equity security.
|
||||
/// It also shows how you can prefilter contracts easily based on strikes and expirations, and how you
|
||||
/// can inspect the option chain to pick a specific option contract to trade.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="options" />
|
||||
/// <meta name="tag" content="filter selection" />
|
||||
public class BasicTemplateOptionsDailyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private const string UnderlyingTicker = "AAPL";
|
||||
private Symbol _optionSymbol;
|
||||
private bool _optionExpired;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2015, 12, 15);
|
||||
SetEndDate(2016, 2, 1);
|
||||
SetCash(100000);
|
||||
|
||||
var equity = AddEquity(UnderlyingTicker, Resolution.Daily);
|
||||
var option = AddOption(UnderlyingTicker, Resolution.Daily);
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(x => x.CallsOnly().Expiration(0, 60));
|
||||
|
||||
// use the underlying equity as the benchmark
|
||||
SetBenchmark(equity.Symbol);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
|
||||
/// </summary>
|
||||
/// <param name="slice">The current slice of data keyed by symbol string</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
OptionChain chain;
|
||||
if (slice.OptionChains.TryGetValue(_optionSymbol, out chain))
|
||||
{
|
||||
// Grab us the contract nearest expiry that is not today
|
||||
var contractsByExpiration = chain.Where(x => x.Expiry != Time.Date).OrderBy(x => x.Expiry);
|
||||
var contract = contractsByExpiration.FirstOrDefault();
|
||||
|
||||
if (contract != null)
|
||||
{
|
||||
// if found, trade it
|
||||
MarketOrder(contract.Symbol, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Order fill event handler. On an order fill update the resulting information is passed to this method.
|
||||
/// </summary>
|
||||
/// <param name="orderEvent">Order event details containing details of the events</param>
|
||||
/// <remarks>This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects</remarks>
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Log(orderEvent.ToString());
|
||||
|
||||
// Check for our expected OTM option expiry
|
||||
if (orderEvent.Message.Contains("OTM", StringComparison.InvariantCulture))
|
||||
{
|
||||
// Assert it is at midnight (5AM UTC)
|
||||
if (orderEvent.UtcTime != new DateTime(2016, 1, 16, 5, 0, 0))
|
||||
{
|
||||
throw new ArgumentException($"Expiry event was not at the correct time, {orderEvent.UtcTime}");
|
||||
}
|
||||
|
||||
_optionExpired = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
// Assert we had our option expire and fill a liquidation order
|
||||
if (_optionExpired != true)
|
||||
{
|
||||
throw new ArgumentException("Algorithm did not process the option expiration like expected");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 308;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-1.16%"},
|
||||
{"Compounding Annual Return", "-8.351%"},
|
||||
{"Drawdown", "1.200%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "98844"},
|
||||
{"Net Profit", "-1.156%"},
|
||||
{"Sharpe Ratio", "-4.04"},
|
||||
{"Sortino Ratio", "-2.422"},
|
||||
{"Probabilistic Sharpe Ratio", "0.008%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.058"},
|
||||
{"Beta", "0.021"},
|
||||
{"Annual Standard Deviation", "0.017"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "1.49"},
|
||||
{"Tracking Error", "0.289"},
|
||||
{"Treynor Ratio", "-3.212"},
|
||||
{"Total Fees", "$1.00"},
|
||||
{"Estimated Strategy Capacity", "$72000.00"},
|
||||
{"Lowest Capacity Asset", "AAPL W78ZEO29CFS6|AAPL R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "0.02%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "5639c19a7d56ec312f61029b943903b8"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to add options for a given underlying equity security.
|
||||
/// It also shows how you can prefilter contracts easily based on strikes and expirations.
|
||||
/// It also shows how you can inspect the option chain to pick a specific option contract to trade.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="options" />
|
||||
/// <meta name="tag" content="filter selection" />
|
||||
public class BasicTemplateOptionsFilterUniverseAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private const string UnderlyingTicker = "GOOG";
|
||||
private Symbol _optionSymbol;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2015, 12, 24);
|
||||
SetEndDate(2015, 12, 28);
|
||||
SetCash(100000);
|
||||
|
||||
var equity = AddEquity(UnderlyingTicker);
|
||||
var option = AddOption(UnderlyingTicker);
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
// Set our custom universe filter, Expires today, is a call, and is within 10 dollars of the current price
|
||||
option.SetFilter(universe => from symbol in universe.WeeklysOnly().Expiration(0, 1)
|
||||
where symbol.ID.OptionRight != OptionRight.Put &&
|
||||
-10 < universe.Underlying.Price - symbol.ID.StrikePrice &&
|
||||
universe.Underlying.Price - symbol.ID.StrikePrice < 10
|
||||
select symbol);
|
||||
|
||||
// use the underlying equity as the benchmark
|
||||
SetBenchmark(equity.Symbol);
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
OptionChain chain;
|
||||
if (slice.OptionChains.TryGetValue(_optionSymbol, out chain))
|
||||
{
|
||||
// Get the first ITM call expiring today
|
||||
var contract = (
|
||||
from optionContract in chain.OrderByDescending(x => x.Strike)
|
||||
where optionContract.Expiry == Time.Date
|
||||
where optionContract.Strike < chain.Underlying.Price
|
||||
select optionContract
|
||||
).FirstOrDefault();
|
||||
|
||||
if (contract != null)
|
||||
{
|
||||
MarketOrder(contract.Symbol, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Log(orderEvent.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 12290;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.40%"},
|
||||
{"Compounding Annual Return", "122.246%"},
|
||||
{"Drawdown", "0.800%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "101100"},
|
||||
{"Net Profit", "1.100%"},
|
||||
{"Sharpe Ratio", "12.688"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "95.488%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0.112"},
|
||||
{"Annual Variance", "0.013"},
|
||||
{"Information Ratio", "12.777"},
|
||||
{"Tracking Error", "0.112"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$1.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"},
|
||||
{"Portfolio Turnover", "15.08%"},
|
||||
{"Drawdown Recovery", "4"},
|
||||
{"OrderListHash", "c53bc9318676161ed3b7797c945e2113"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic template options framework algorithm uses framework components to define an algorithm
|
||||
/// that trades options.
|
||||
/// </summary>
|
||||
public class BasicTemplateOptionsFrameworkAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
UniverseSettings.Resolution = Resolution.Minute;
|
||||
|
||||
SetStartDate(2014, 06, 05);
|
||||
SetEndDate(2014, 06, 09);
|
||||
SetCash(100000);
|
||||
|
||||
// set framework models
|
||||
SetUniverseSelection(new EarliestExpiringWeeklyAtTheMoneyPutOptionUniverseSelectionModel(SelectOptionChainSymbols));
|
||||
SetAlpha(new ConstantOptionContractAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromHours(0.5)));
|
||||
SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
SetRiskManagement(new NullRiskManagementModel());
|
||||
}
|
||||
|
||||
// option symbol universe selection function
|
||||
private static IEnumerable<Symbol> SelectOptionChainSymbols(DateTime utcTime)
|
||||
{
|
||||
var newYorkTime = utcTime.ConvertFromUtc(TimeZones.NewYork);
|
||||
if (newYorkTime.Date < new DateTime(2014, 06, 06))
|
||||
{
|
||||
yield return QuantConnect.Symbol.Create("TWX", SecurityType.Option, Market.USA, "?TWX");
|
||||
}
|
||||
|
||||
if (newYorkTime.Date >= new DateTime(2014, 06, 06))
|
||||
{
|
||||
yield return QuantConnect.Symbol.Create("AAPL", SecurityType.Option, Market.USA, "?AAPL");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates option chain universes that select only the earliest expiry ATM weekly put contract
|
||||
/// and runs a user defined optionChainSymbolSelector every day to enable choosing different option chains
|
||||
/// </summary>
|
||||
class EarliestExpiringWeeklyAtTheMoneyPutOptionUniverseSelectionModel : OptionUniverseSelectionModel
|
||||
{
|
||||
public EarliestExpiringWeeklyAtTheMoneyPutOptionUniverseSelectionModel(Func<DateTime, IEnumerable<Symbol>> optionChainSymbolSelector)
|
||||
: base(TimeSpan.FromDays(1), optionChainSymbolSelector)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the option chain universe filter
|
||||
/// </summary>
|
||||
protected override OptionFilterUniverse Filter(OptionFilterUniverse filter)
|
||||
{
|
||||
return filter
|
||||
.Strikes(+1, +1)
|
||||
// Expiration method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
.Expiration(0, 7)
|
||||
//.Expiration(TimeSpan.Zero, TimeSpan.FromDays(7))
|
||||
.WeeklysOnly()
|
||||
.PutsOnly()
|
||||
.OnlyApplyFilterAtMarketOpen();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of a constant alpha model that only emits insights for option symbols
|
||||
/// </summary>
|
||||
class ConstantOptionContractAlphaModel : ConstantAlphaModel
|
||||
{
|
||||
public ConstantOptionContractAlphaModel(InsightType type, InsightDirection direction, TimeSpan period)
|
||||
: base(type, direction, period)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool ShouldEmitInsight(DateTime utcTime, Symbol symbol)
|
||||
{
|
||||
// only emit alpha for option symbols and not underlying equity symbols
|
||||
if (symbol.SecurityType != SecurityType.Option)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.ShouldEmitInsight(utcTime, symbol);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Portfolio construction model that sets target quantities to 1 for up insights and -1 for down insights
|
||||
/// </summary>
|
||||
class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
|
||||
{
|
||||
public override IEnumerable<IPortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
|
||||
{
|
||||
foreach (var insight in insights)
|
||||
{
|
||||
yield return new PortfolioTarget(insight.Symbol, (int) insight.Direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 17487;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "5"},
|
||||
{"Average Win", "0.13%"},
|
||||
{"Average Loss", "-0.30%"},
|
||||
{"Compounding Annual Return", "-46.395%"},
|
||||
{"Drawdown", "1.600%"},
|
||||
{"Expectancy", "0.429"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "99149.50"},
|
||||
{"Net Profit", "-0.850%"},
|
||||
{"Sharpe Ratio", "-4.298"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "14.867%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0.43"},
|
||||
{"Alpha", "-0.84"},
|
||||
{"Beta", "0.986"},
|
||||
{"Annual Standard Deviation", "0.098"},
|
||||
{"Annual Variance", "0.01"},
|
||||
{"Information Ratio", "-9.299"},
|
||||
{"Tracking Error", "0.091"},
|
||||
{"Treynor Ratio", "-0.428"},
|
||||
{"Total Fees", "$4.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "AAPL R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "13.50%"},
|
||||
{"Drawdown Recovery", "2"},
|
||||
{"OrderListHash", "2ab4ffc0944a2888a3be0568c2570a79"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Securities.Option;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Example demonstrating how to access to options history for a given underlying equity security.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="options" />
|
||||
/// <meta name="tag" content="filter selection" />
|
||||
/// <meta name="tag" content="history" />
|
||||
public class BasicTemplateOptionsHistoryAlgorithm : QCAlgorithm
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
// this test opens position in the first day of trading, lives through stock split (7 for 1), and closes adjusted position on the second day
|
||||
SetStartDate(2015, 12, 24);
|
||||
SetEndDate(2015, 12, 24);
|
||||
SetCash(1000000);
|
||||
|
||||
var option = AddOption("GOOG");
|
||||
// add the initial contract filter
|
||||
// SetFilter method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
option.SetFilter(-2, +2, 0, 180);
|
||||
// option.SetFilter(-2, +2, TimeSpan.Zero, TimeSpan.FromDays(180));
|
||||
|
||||
// set the pricing model for Greeks and volatility
|
||||
// find more pricing models https://www.quantconnect.com/lean/documentation/topic27704.html
|
||||
option.PriceModel = OptionPriceModels.BlackScholes();
|
||||
// set the warm-up period for the pricing model
|
||||
SetWarmup(TimeSpan.FromDays(4));
|
||||
// set the benchmark to be the initial cash
|
||||
SetBenchmark(d => 1000000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
|
||||
/// </summary>
|
||||
/// <param name="slice">The current slice of data keyed by symbol string</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (IsWarmingUp) return;
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
foreach (var chain in slice.OptionChains)
|
||||
{
|
||||
var underlying = Securities[chain.Key.Underlying];
|
||||
foreach (var contract in chain.Value)
|
||||
{
|
||||
Log($"{contract.Symbol.Value}," +
|
||||
$"Bid={contract.BidPrice.ToStringInvariant()} " +
|
||||
$"Ask={contract.AskPrice.ToStringInvariant()} " +
|
||||
$"Last={contract.LastPrice.ToStringInvariant()} " +
|
||||
$"OI={contract.OpenInterest.ToStringInvariant()} " +
|
||||
$"σ={underlying.VolatilityModel.Volatility.ToStringInvariant("0.000")} " +
|
||||
$"NPV={contract.TheoreticalPrice.ToStringInvariant("0.000")} " +
|
||||
$"Δ={contract.Greeks.Delta.ToStringInvariant("0.000")} " +
|
||||
$"Γ={contract.Greeks.Gamma.ToStringInvariant("0.000")} " +
|
||||
$"ν={contract.Greeks.Vega.ToStringInvariant("0.000")} " +
|
||||
$"ρ={contract.Greeks.Rho.ToStringInvariant("0.00")} " +
|
||||
$"Θ={(contract.Greeks.Theta / 365.0m).ToStringInvariant("0.00")} " +
|
||||
$"IV={contract.ImpliedVolatility.ToStringInvariant("0.000")}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
foreach (var change in changes.AddedSecurities)
|
||||
{
|
||||
// Only print options price
|
||||
if (change.Symbol.Value == "GOOG") continue;
|
||||
var history = History(change.Symbol, 10, Resolution.Minute);
|
||||
|
||||
foreach (var data in history.OrderByDescending(x => x.Time).Take(3))
|
||||
{
|
||||
Log($"History: {data.Symbol.Value}: {data.Time} > {data.Close}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user