Compare commits
151 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4827f2f22 | ||
|
|
81d1bb5095 | ||
|
|
cdcd8fdacd | ||
|
|
eebe0425d8 | ||
|
|
caadaf62b2 | ||
|
|
19df3e1e48 | ||
|
|
66c016b284 | ||
|
|
0c77be0ba8 | ||
|
|
47bfdae372 | ||
|
|
3a2cae037f | ||
|
|
b9e6781c96 | ||
|
|
2a6771c1c0 | ||
|
|
56270464cc | ||
|
|
8bcd588602 | ||
|
|
9cd05e9f1f | ||
|
|
40bff6efb7 | ||
|
|
f5e8966eea | ||
|
|
1596ed9846 | ||
|
|
c1c4114dca | ||
|
|
6acbcf0832 | ||
|
|
5675e71a32 | ||
|
|
48914b08db | ||
|
|
852c963bbf | ||
|
|
99848a1221 | ||
|
|
7178be4f55 | ||
|
|
017837c5a5 | ||
|
|
c7294adfe4 | ||
|
|
61fb997f07 | ||
|
|
7cc6e31c43 | ||
|
|
b5ca1ac461 | ||
|
|
2a54da9e2c | ||
|
|
6fd1a002fe | ||
|
|
ace1a1f20d | ||
|
|
75f86f555e | ||
|
|
20655b334b | ||
|
|
3507c91640 | ||
|
|
ebb31d0fb4 | ||
|
|
dcd60d0551 | ||
|
|
dc2c68c754 | ||
|
|
2791765c94 | ||
|
|
f270f25eca | ||
|
|
8235de42a0 | ||
|
|
c2e21df18b | ||
|
|
35dfcd73ab | ||
|
|
3783900eef | ||
|
|
9fea859323 | ||
|
|
6e2744af7c | ||
|
|
962b91fc12 | ||
|
|
cf00d3c9f3 | ||
|
|
8af5c8b6f2 | ||
|
|
1fcef8c024 | ||
|
|
a912638496 | ||
|
|
5611b5508a | ||
|
|
b3bd15d3c2 | ||
|
|
25ab8bdacc | ||
|
|
38c5ef3e2b | ||
|
|
194f01e621 | ||
|
|
61b5231c50 | ||
|
|
4a06fcdda0 | ||
|
|
8325fd18ca | ||
|
|
2bc8783082 | ||
|
|
0d9f011758 | ||
|
|
6dfc6c710c | ||
|
|
e30232e21b | ||
|
|
8730eeb8a9 | ||
|
|
914485c595 | ||
|
|
02f085ee9e | ||
|
|
f4cf7b6733 | ||
|
|
d427970762 | ||
|
|
66ff14b3bd | ||
|
|
a7a4af6b70 | ||
|
|
b1a6aa686c | ||
|
|
14b10f5e81 | ||
|
|
4d85f27f00 | ||
|
|
c2efa65048 | ||
|
|
75eaf21e43 | ||
|
|
72a6ea9d31 | ||
|
|
2b9662c12e | ||
|
|
98314d98ed | ||
|
|
a860cfc32f | ||
|
|
6563d6e394 | ||
|
|
11cc062628 | ||
|
|
e8b95b80e1 | ||
|
|
a52822853d | ||
|
|
73e46cc9ae | ||
|
|
a9c4d29776 | ||
|
|
6ed8cb5cae | ||
|
|
1d1dc07dfb | ||
|
|
bddebe279d | ||
|
|
81a334c525 | ||
|
|
af26b66481 | ||
|
|
d7ead851a1 | ||
|
|
f428398900 | ||
|
|
19483702f8 | ||
|
|
146be2d0ba | ||
|
|
b54281b262 | ||
|
|
f12e8fc08e | ||
|
|
6b6ca5b460 | ||
|
|
ab4c3bf55e | ||
|
|
9c69ee5536 | ||
|
|
89493b1546 | ||
|
|
ee683933a3 | ||
|
|
e87c98def8 | ||
|
|
239406ef5c | ||
|
|
e13066273c | ||
|
|
7677b99bf6 | ||
|
|
c21dd716ed | ||
|
|
f87eb88f27 | ||
|
|
1d363e2c35 | ||
|
|
98273097e5 | ||
|
|
cbdf25d713 | ||
|
|
dcfdbd8c82 | ||
|
|
b5b317f490 | ||
|
|
0eecf5d139 | ||
|
|
bc513ce0e7 | ||
|
|
019ce5aa76 | ||
|
|
c4329c4132 | ||
|
|
9618c376bf | ||
|
|
3aabb11315 | ||
|
|
4d2723f851 | ||
|
|
86b74e0a09 | ||
|
|
41a730bc68 | ||
|
|
6b2dfb6b8c | ||
|
|
7a4ca7898e | ||
|
|
60028ad48a | ||
|
|
e9d690b35a | ||
|
|
db2cb57a3f | ||
|
|
3c784e5b04 | ||
|
|
31f8561330 | ||
|
|
38b87d941a | ||
|
|
83d59b5f9a | ||
|
|
f19d8cb700 | ||
|
|
fcee43b56e | ||
|
|
7898e74148 | ||
|
|
b34cea4458 | ||
|
|
e9edb8ac29 | ||
|
|
33c57bbde4 | ||
|
|
94b9b13530 | ||
|
|
682b9aa760 | ||
|
|
98c6023748 | ||
|
|
dacc679d42 | ||
|
|
3e76716b07 | ||
|
|
55b09a1ea6 | ||
|
|
5539e27905 | ||
|
|
42ed7cf2a7 | ||
|
|
62d1321d74 | ||
|
|
0fa2ea19bc | ||
|
|
e155f620e1 | ||
|
|
897e16c484 | ||
|
|
6477b40661 | ||
|
|
5bfe2491c3 |
2
.github/workflows/gh-actions.yml
vendored
2
.github/workflows/gh-actions.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
run: dotnet build /p:Configuration=Release /v:quiet /p:WarningLevel=1 QuantConnect.Lean.sln
|
||||
|
||||
- name: Run Tests
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "TestCategory!=TravisExclude&TestCategory!=ResearchRegressionTests" -- TestRunParameters.Parameter\(name=\"log-handler\", value=\"ConsoleErrorLogHandler\"\)
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --blame-hang-timeout 300seconds --blame-crash --filter "TestCategory!=TravisExclude&TestCategory!=ResearchRegressionTests" -- TestRunParameters.Parameter\(name=\"log-handler\", value=\"ConsoleErrorLogHandler\"\)
|
||||
|
||||
- name: Generate & Publish python stubs
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
|
||||
37
.github/workflows/virtual-environments.yml
vendored
37
.github/workflows/virtual-environments.yml
vendored
@@ -31,31 +31,34 @@ jobs:
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonVirtualEnvironmentTests.AssertVirtualEnvironment"
|
||||
|
||||
- name: Run Python Package Tests
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests"
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests" --blame-hang-timeout 120seconds --blame-crash
|
||||
|
||||
- name: Run Pomegranate Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.PomegranateTest"
|
||||
|
||||
- name: Run Tensorforce Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.TensorforceTests"
|
||||
- name: Run Pomegranate & Tigramite Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.PomegranateTest|Tigramite" --blame-hang-timeout 120seconds --blame-crash
|
||||
|
||||
- name: Run StableBaselines Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.StableBaselinesTest"
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.StableBaselinesTest" --blame-hang-timeout 120seconds --blame-crash
|
||||
|
||||
- name: Run AxPlatform Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.AxPlatformTest"
|
||||
|
||||
- name: Run NeuralTangents Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.NeuralTangentsTest"
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.AxPlatformTest" --blame-hang-timeout 120seconds --blame-crash
|
||||
|
||||
- name: Run NBeats Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.NBeatsTest"
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.NBeatsTest" --blame-hang-timeout 120seconds --blame-crash
|
||||
|
||||
- name: Run Tensorly Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.TensorlyTest"
|
||||
- name: Run TensorlyTest Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.TensorlyTest" --blame-hang-timeout 120seconds --blame-crash
|
||||
|
||||
- name: Run Ignite Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.IgniteTest"
|
||||
- name: Run TensorflowProbability, NeuralTangents, Ignite Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.TensorflowProbabilityTest|TensorflowTest|NeuralTangentsTest|IgniteTest" --blame-hang-timeout 120seconds --blame-crash
|
||||
|
||||
- name: Run Hvplot Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.HvplotTest"
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.HvplotTest" --blame-hang-timeout 120seconds --blame-crash
|
||||
|
||||
- name: Run Hvplot Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.StellargraphTest" --blame-hang-timeout 120seconds --blame-crash
|
||||
|
||||
- name: Run Keras Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.KerasTest" --blame-hang-timeout 120seconds --blame-crash
|
||||
|
||||
- name: Run Keras Python Package Test
|
||||
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "FullyQualifiedName=QuantConnect.Tests.Python.PythonPackagesTests.ScikerasTest" --blame-hang-timeout 120seconds --blame-crash
|
||||
@@ -20,8 +20,8 @@ To use Lean CLI follow the instructions for installation and tutorial for usage
|
||||
|
||||
1. Install [.Net 6](https://dotnet.microsoft.com/download) for the project
|
||||
|
||||
2. (Optional) Get [Python 3.6.8](https://www.python.org/downloads/release/python-368/) for running Python algorithms
|
||||
- Follow Python instructions [here](https://github.com/QuantConnect/Lean/tree/master/Algorithm.Python#installing-python-36) for your platform
|
||||
2. (Optional) Get [Python 3.8.13](https://www.python.org/downloads/release/python-3813/) for running Python algorithms
|
||||
- Follow Python instructions [here](https://github.com/QuantConnect/Lean/tree/master/Algorithm.Python#installing-python-38) for your platform
|
||||
|
||||
3. Get [Visual Studio](https://visualstudio.microsoft.com/vs/)
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 608437;
|
||||
public long DataPoints => 612882;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -170,7 +170,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "4f50b8360ea317ef974801649088bd06"}
|
||||
{"OrderListHash", "568fe7c2a11960436660db1231f2cfd2"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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);
|
||||
|
||||
// Susbtract one minute to get the actual market open. If market open is at 9:30am, this will be invoked at 9:31am
|
||||
var expectedTime = Time.TimeOfDay - TimeSpan.FromMinutes(1);
|
||||
var allOptionsWereChangedOnMarketOpen = changeOptions.All(s =>
|
||||
{
|
||||
var firstMarketSegment = s.Exchange.Hours.MarketHours[Time.DayOfWeek].Segments
|
||||
.First(segment => segment.State == MarketHoursState.Market);
|
||||
|
||||
return firstMarketSegment.Start == expectedTime;
|
||||
});
|
||||
|
||||
if (!allOptionsWereChangedOnMarketOpen)
|
||||
{
|
||||
throw new Exception("Expected options filter to be run only on market open");
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all time slices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 6023980;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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", ""},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"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", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 6214;
|
||||
public override long DataPoints => 6202;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -59,7 +59,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0.01%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "-78.502%"},
|
||||
{"Compounding Annual Return", "-78.519%"},
|
||||
{"Drawdown", "3.100%"},
|
||||
{"Expectancy", "7.797"},
|
||||
{"Net Profit", "-1.134%"},
|
||||
|
||||
@@ -296,7 +296,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 1748811;
|
||||
public long DataPoints => 1341291;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -349,7 +349,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "f67306bc706a2cf66288f1cadf6148ed"}
|
||||
{"OrderListHash", "85cbf92f01c2c91b5f710b7eeefecbe1"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 4324;
|
||||
public long DataPoints => 4319;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 284403;
|
||||
public long DataPoints => 709638;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -156,7 +156,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "-1.993"},
|
||||
{"Return Over Maximum Drawdown", "-1.996"},
|
||||
{"Portfolio Turnover", "0.01"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 884815;
|
||||
public long DataPoints => 2202510;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -201,7 +201,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 12970;
|
||||
public long DataPoints => 12965;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
292
Algorithm.CSharp/BasicTemplateCryptoFutureAlgorithm.cs
Normal file
292
Algorithm.CSharp/BasicTemplateCryptoFutureAlgorithm.cs
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* 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(NodaTime.DateTimeZone.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 data)
|
||||
{
|
||||
var interestRates = data.Get<MarginInterestRate>();
|
||||
foreach (var interestRate in interestRates)
|
||||
{
|
||||
_interestPerSymbol[interestRate.Key]++;
|
||||
|
||||
var cachedInterestRate = Securities[interestRate.Key].Cache.GetData<MarginInterestRate>();
|
||||
if (cachedInterestRate != interestRate.Value)
|
||||
{
|
||||
throw new Exception($"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 Exception($"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 Exception($"Unexpected TotalSaleVolume {btcUsdHoldings.TotalSaleVolume}");
|
||||
}
|
||||
if (Math.Abs(btcUsdHoldings.AbsoluteHoldingsCost - holdingsValueBtcUsd) > 1)
|
||||
{
|
||||
throw new Exception($"Unexpected holdings cost {btcUsdHoldings.HoldingsCost}");
|
||||
}
|
||||
// margin used is based on the maintenance rate
|
||||
if (Math.Abs(btcUsdHoldings.AbsoluteHoldingsCost * 0.05m - marginUsed) > 1
|
||||
|| _btcUsd.BuyingPowerModel.GetMaintenanceMargin(_btcUsd) != marginUsed)
|
||||
{
|
||||
throw new Exception($"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 Exception($"Unexpected TotalSaleVolume {adaUsdtHoldings.TotalSaleVolume}");
|
||||
}
|
||||
if (Math.Abs(adaUsdtHoldings.AbsoluteHoldingsCost - holdingsValueUsdt) > 1)
|
||||
{
|
||||
throw new Exception($"Unexpected holdings cost {adaUsdtHoldings.HoldingsCost}");
|
||||
}
|
||||
if (Math.Abs(adaUsdtHoldings.AbsoluteHoldingsCost * 0.05m - marginUsed) > 1
|
||||
|| _adaUsdt.BuyingPowerModel.GetMaintenanceMargin(_adaUsdt) != marginUsed)
|
||||
{
|
||||
throw new Exception($"Unexpected margin used {marginUsed}");
|
||||
}
|
||||
|
||||
// position just opened should be just spread here
|
||||
var profit = Portfolio.TotalUnrealizedProfit;
|
||||
if ((5 - Math.Abs(profit)) < 0)
|
||||
{
|
||||
throw new Exception($"Unexpected TotalUnrealizedProfit {Portfolio.TotalUnrealizedProfit}");
|
||||
}
|
||||
|
||||
if (Portfolio.TotalProfit != 0)
|
||||
{
|
||||
throw new Exception($"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 Exception($"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 Exception($"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 Exception($"Unexpected TotalUnrealizedProfit {Portfolio.TotalUnrealizedProfit}");
|
||||
}
|
||||
// we barely did any difference on the previous trade
|
||||
if ((5 - Math.Abs(Portfolio.TotalProfit)) < 0)
|
||||
{
|
||||
throw new Exception($"Unexpected TotalProfit {Portfolio.TotalProfit}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (_interestPerSymbol[_adaUsdt.Symbol] != 1)
|
||||
{
|
||||
throw new Exception($"Unexpected interest rate count {_interestPerSymbol[_adaUsdt.Symbol]}");
|
||||
}
|
||||
|
||||
if (_interestPerSymbol[_btcUsd.Symbol] != 3)
|
||||
{
|
||||
throw new Exception($"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 Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <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>
|
||||
/// 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 Trades", "4"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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", "$630000000.00"},
|
||||
{"Lowest Capacity Asset", "ADAUSDT 18R"},
|
||||
{"Fitness Score", "0.001"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
|
||||
{"Portfolio Turnover", "0.001"},
|
||||
{"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", "d4520985f69c915060f6bee3b7926cf5"}
|
||||
};
|
||||
}
|
||||
}
|
||||
255
Algorithm.CSharp/BasicTemplateCryptoFutureHourlyAlgorithm.cs
Normal file
255
Algorithm.CSharp/BasicTemplateCryptoFutureHourlyAlgorithm.cs
Normal file
@@ -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 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(NodaTime.DateTimeZone.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 data)
|
||||
{
|
||||
var interestRates = data.Get<MarginInterestRate>();
|
||||
foreach (var interestRate in interestRates)
|
||||
{
|
||||
_interestPerSymbol[interestRate.Key]++;
|
||||
|
||||
var cachedInterestRate = Securities[interestRate.Key].Cache.GetData<MarginInterestRate>();
|
||||
if (cachedInterestRate != interestRate.Value)
|
||||
{
|
||||
throw new Exception($"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 Exception($"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 Exception($"Unexpected TotalSaleVolume {adaUsdtHoldings.TotalSaleVolume}");
|
||||
}
|
||||
if (Math.Abs(adaUsdtHoldings.AbsoluteHoldingsCost - holdingsValueUsdt) > 1)
|
||||
{
|
||||
throw new Exception($"Unexpected holdings cost {adaUsdtHoldings.HoldingsCost}");
|
||||
}
|
||||
if (Math.Abs(adaUsdtHoldings.AbsoluteHoldingsCost * 0.05m - marginUsed) > 1
|
||||
|| _adaUsdt.BuyingPowerModel.GetMaintenanceMargin(_adaUsdt) != marginUsed)
|
||||
{
|
||||
throw new Exception($"Unexpected margin used {marginUsed}");
|
||||
}
|
||||
|
||||
// position just opened should be just spread here
|
||||
var profit = Portfolio.TotalUnrealizedProfit;
|
||||
if ((5 - Math.Abs(profit)) < 0)
|
||||
{
|
||||
throw new Exception($"Unexpected TotalUnrealizedProfit {Portfolio.TotalUnrealizedProfit}");
|
||||
}
|
||||
|
||||
if (Portfolio.TotalProfit != 0)
|
||||
{
|
||||
throw new Exception($"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 Exception($"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 Exception($"Unexpected TotalUnrealizedProfit {Portfolio.TotalUnrealizedProfit}");
|
||||
}
|
||||
// we barely did any difference on the previous trade
|
||||
if ((5 - Math.Abs(Portfolio.TotalProfit)) < 0)
|
||||
{
|
||||
throw new Exception($"Unexpected TotalProfit {Portfolio.TotalProfit}");
|
||||
}
|
||||
}
|
||||
|
||||
if (Time.Hour >= 22 && Transactions.OrdersCount == 3)
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (_interestPerSymbol[_adaUsdt.Symbol] != 1)
|
||||
{
|
||||
throw new Exception($"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 Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <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>
|
||||
/// 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 Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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", "$520000000.00"},
|
||||
{"Lowest Capacity Asset", "ADAUSDT 18R"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "-364.224"},
|
||||
{"Portfolio Turnover", "0.001"},
|
||||
{"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", "17f99ecc3f35f94fff1ea5694c40d32c"}
|
||||
};
|
||||
}
|
||||
}
|
||||
235
Algorithm.CSharp/BasicTemplateFutureRolloverAlgorithm.cs
Normal file
235
Algorithm.CSharp/BasicTemplateFutureRolloverAlgorithm.cs
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* 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;
|
||||
public decimal Price;
|
||||
public bool IsLong;
|
||||
public bool IsShort;
|
||||
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 Language[] Languages { get; } = { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 1345;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 4;
|
||||
|
||||
/// <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 Trades", "2"},
|
||||
{"Average Win", "0.53%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "3.011%"},
|
||||
{"Drawdown", "0.000%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0.528%"},
|
||||
{"Sharpe Ratio", "1.999"},
|
||||
{"Probabilistic Sharpe Ratio", "83.704%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.023"},
|
||||
{"Beta", "-0.004"},
|
||||
{"Annual Standard Deviation", "0.011"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-4.774"},
|
||||
{"Tracking Error", "0.084"},
|
||||
{"Treynor Ratio", "-4.853"},
|
||||
{"Total Fees", "$4.30"},
|
||||
{"Estimated Strategy Capacity", "$5900000000.00"},
|
||||
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
|
||||
{"Fitness Score", "0.002"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "1792.236"},
|
||||
{"Portfolio Turnover", "0.002"},
|
||||
{"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", "40e4b91ec89383f6501d9ba324e50eb9"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -188,8 +188,8 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Fitness Score", "0.001"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-58.725"},
|
||||
{"Return Over Maximum Drawdown", "-32.073"},
|
||||
{"Sortino Ratio", "-58.8"},
|
||||
{"Return Over Maximum Drawdown", "-32.114"},
|
||||
{"Portfolio Turnover", "98.477"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 11709;
|
||||
public virtual long DataPoints => 15217;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -173,8 +173,8 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Fitness Score", "0.006"},
|
||||
{"Kelly Criterion Estimate", "-50.022"},
|
||||
{"Kelly Criterion Probability Value", "0.711"},
|
||||
{"Sortino Ratio", "-9.907"},
|
||||
{"Return Over Maximum Drawdown", "-50.79"},
|
||||
{"Sortino Ratio", "-10.107"},
|
||||
{"Return Over Maximum Drawdown", "-51.815"},
|
||||
{"Portfolio Turnover", "0.54"},
|
||||
{"Total Insights Generated", "5"},
|
||||
{"Total Insights Closed", "4"},
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 73252;
|
||||
public override long DataPoints => 96027;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
@@ -73,8 +73,8 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Fitness Score", "0.045"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-4.326"},
|
||||
{"Return Over Maximum Drawdown", "-0.994"},
|
||||
{"Sortino Ratio", "-4.328"},
|
||||
{"Return Over Maximum Drawdown", "-0.995"},
|
||||
{"Portfolio Turnover", "0.205"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 13559;
|
||||
public override long DataPoints => 17431;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 205645;
|
||||
public override long DataPoints => 248521;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
protected Symbol SpxOption;
|
||||
private ExponentialMovingAverage _emaSlow;
|
||||
private ExponentialMovingAverage _emaFast;
|
||||
|
||||
|
||||
protected virtual Resolution Resolution => Resolution.Minute;
|
||||
protected virtual int StartDay => 4;
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 16690;
|
||||
public virtual long DataPoints => 16049;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -124,34 +124,34 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// </summary>
|
||||
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "4"},
|
||||
{"Total Trades", "3"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-53.10%"},
|
||||
{"Compounding Annual Return", "-92.544%"},
|
||||
{"Drawdown", "10.100%"},
|
||||
{"Average Loss", "-2.45%"},
|
||||
{"Compounding Annual Return", "-62.036%"},
|
||||
{"Drawdown", "9.300%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-9.915%"},
|
||||
{"Sharpe Ratio", "-3.845"},
|
||||
{"Probabilistic Sharpe Ratio", "0.053%"},
|
||||
{"Net Profit", "-3.051%"},
|
||||
{"Sharpe Ratio", "-4.466"},
|
||||
{"Probabilistic Sharpe Ratio", "0.781%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.558"},
|
||||
{"Beta", "0.313"},
|
||||
{"Annual Standard Deviation", "0.112"},
|
||||
{"Annual Variance", "0.013"},
|
||||
{"Information Ratio", "-6.652"},
|
||||
{"Tracking Error", "0.125"},
|
||||
{"Treynor Ratio", "-1.379"},
|
||||
{"Alpha", "-0.172"},
|
||||
{"Beta", "0.076"},
|
||||
{"Annual Standard Deviation", "0.029"},
|
||||
{"Annual Variance", "0.001"},
|
||||
{"Information Ratio", "-6.723"},
|
||||
{"Tracking Error", "0.099"},
|
||||
{"Treynor Ratio", "-1.733"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$13000000.00"},
|
||||
{"Estimated Strategy Capacity", "$9100000.00"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
|
||||
{"Fitness Score", "0.039"},
|
||||
{"Fitness Score", "0.025"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-1.763"},
|
||||
{"Return Over Maximum Drawdown", "-9.371"},
|
||||
{"Portfolio Turnover", "0.278"},
|
||||
{"Sortino Ratio", "-3.11"},
|
||||
{"Return Over Maximum Drawdown", "-21.007"},
|
||||
{"Portfolio Turnover", "0.332"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
@@ -165,7 +165,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "0668385036aba3e95127607dfc2f1a59"}
|
||||
{"OrderListHash", "905811fc779835bf0c514963a20e40f9"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
/*
|
||||
* 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 System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
@@ -12,10 +28,10 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
protected override Resolution Resolution => Resolution.Daily;
|
||||
protected override int StartDay => 1;
|
||||
|
||||
// two complete weeks starting from the 5th plus the 18th bar
|
||||
protected virtual int ExpectedBarCount => 2 * 5 + 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 = 0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Purchase a contract when we are not invested, liquidate otherwise
|
||||
/// </summary>
|
||||
@@ -30,7 +46,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
|
||||
|
||||
// Count how many slices we receive with SPX data in it to assert later
|
||||
if (slice.ContainsKey(Spx))
|
||||
{
|
||||
@@ -59,7 +75,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 122;
|
||||
public override long DataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -71,48 +87,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "9"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-39.42%"},
|
||||
{"Compounding Annual Return", "394.321%"},
|
||||
{"Drawdown", "0.200%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "8.219%"},
|
||||
{"Sharpe Ratio", "6.812"},
|
||||
{"Probabilistic Sharpe Ratio", "91.380%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "2.236"},
|
||||
{"Beta", "-1.003"},
|
||||
{"Annual Standard Deviation", "0.317"},
|
||||
{"Annual Variance", "0.101"},
|
||||
{"Information Ratio", "5.805"},
|
||||
{"Tracking Error", "0.359"},
|
||||
{"Treynor Ratio", "-2.153"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
|
||||
{"Fitness Score", "0.027"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "1776.081"},
|
||||
{"Portfolio Turnover", "0.027"},
|
||||
{"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", "474e8e0e28ee84c869f8c69ec3efe371"}
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public class BasicTemplateIndexHourlyAlgorithm : BasicTemplateIndexDailyAlgorithm
|
||||
{
|
||||
protected override Resolution Resolution => Resolution.Hour;
|
||||
protected override int ExpectedBarCount => base.ExpectedBarCount * 8;
|
||||
protected override int ExpectedBarCount => base.ExpectedBarCount * 7;
|
||||
|
||||
/// <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.
|
||||
@@ -23,7 +23,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 408;
|
||||
public override long DataPoints => 391;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -35,34 +35,34 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "70"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.23%"},
|
||||
{"Compounding Annual Return", "-34.441%"},
|
||||
{"Drawdown", "2.000%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-2.028%"},
|
||||
{"Sharpe Ratio", "-11.139"},
|
||||
{"Probabilistic Sharpe Ratio", "0.000%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.269"},
|
||||
{"Beta", "0.086"},
|
||||
{"Annual Standard Deviation", "0.023"},
|
||||
{"Annual Variance", "0.001"},
|
||||
{"Information Ratio", "-3.624"},
|
||||
{"Tracking Error", "0.094"},
|
||||
{"Treynor Ratio", "-3.042"},
|
||||
{"Total Trades", "71"},
|
||||
{"Average Win", "1.28%"},
|
||||
{"Average Loss", "-0.06%"},
|
||||
{"Compounding Annual Return", "-20.546%"},
|
||||
{"Drawdown", "1.800%"},
|
||||
{"Expectancy", "-0.402"},
|
||||
{"Net Profit", "-0.922%"},
|
||||
{"Sharpe Ratio", "-2.856"},
|
||||
{"Probabilistic Sharpe Ratio", "22.230%"},
|
||||
{"Loss Rate", "97%"},
|
||||
{"Win Rate", "3%"},
|
||||
{"Profit-Loss Ratio", "19.95"},
|
||||
{"Alpha", "-0.155"},
|
||||
{"Beta", "0.025"},
|
||||
{"Annual Standard Deviation", "0.053"},
|
||||
{"Annual Variance", "0.003"},
|
||||
{"Information Ratio", "-2.07"},
|
||||
{"Tracking Error", "0.121"},
|
||||
{"Treynor Ratio", "-6.089"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$310000.00"},
|
||||
{"Estimated Strategy Capacity", "$200000.00"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
|
||||
{"Fitness Score", "0.002"},
|
||||
{"Fitness Score", "0.01"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-14.51"},
|
||||
{"Return Over Maximum Drawdown", "-17.213"},
|
||||
{"Portfolio Turnover", "0.299"},
|
||||
{"Sortino Ratio", "-6.834"},
|
||||
{"Return Over Maximum Drawdown", "-10.862"},
|
||||
{"Portfolio Turnover", "0.327"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
@@ -76,7 +76,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "3eb56c551f20e2ffa1c56c47c5ee6667"}
|
||||
{"OrderListHash", "9e974939d13fd3255c6291a65d2c1eb9"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
@@ -68,7 +67,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 381;
|
||||
public override long DataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -80,48 +79,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "9"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.01%"},
|
||||
{"Compounding Annual Return", "-0.091%"},
|
||||
{"Drawdown", "0.000%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-0.008%"},
|
||||
{"Sharpe Ratio", "-4.033"},
|
||||
{"Probabilistic Sharpe Ratio", "0.013%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.001"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.447"},
|
||||
{"Tracking Error", "0.136"},
|
||||
{"Treynor Ratio", "-4.612"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-50718.291"},
|
||||
{"Return Over Maximum Drawdown", "-11.386"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"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", "5f5df233d68d9115a0d81785de54e71d"}
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 2212;
|
||||
public override long DataPoints => 2143;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -50,33 +50,33 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "70"},
|
||||
{"Total Trades", "72"},
|
||||
{"Average Win", "0.00%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Compounding Annual Return", "-0.006%"},
|
||||
{"Drawdown", "0.000%"},
|
||||
{"Expectancy", "0.000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "36.504%"},
|
||||
{"Expectancy", "-0.486"},
|
||||
{"Net Profit", "0.000%"},
|
||||
{"Sharpe Ratio", "-1.628"},
|
||||
{"Probabilistic Sharpe Ratio", "17.439%"},
|
||||
{"Loss Rate", "97%"},
|
||||
{"Win Rate", "3%"},
|
||||
{"Profit-Loss Ratio", "34.00"},
|
||||
{"Alpha", "0"},
|
||||
{"Profit-Loss Ratio", "17.50"},
|
||||
{"Alpha", "-0"},
|
||||
{"Beta", "-0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.449"},
|
||||
{"Tracking Error", "0.138"},
|
||||
{"Treynor Ratio", "-0"},
|
||||
{"Treynor Ratio", "1.87"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "0"},
|
||||
{"Sortino Ratio", "-206998.942"},
|
||||
{"Return Over Maximum Drawdown", "-5.808"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
@@ -91,7 +91,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "f21910eb98ceaa39e02020de95354d86"}
|
||||
{"OrderListHash", "0df3713aeb32e9c0738200f2a109e2f9"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 884208;
|
||||
public long DataPoints => 475788;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -133,7 +133,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Information Ratio", "0"},
|
||||
{"Tracking Error", "0"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$10.00"},
|
||||
{"Total Fees", "$7.50"},
|
||||
{"Estimated Strategy Capacity", "$84000.00"},
|
||||
{"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
|
||||
{"Fitness Score", "0"},
|
||||
@@ -155,7 +155,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "82c29cc9db9a300074d6ff136253f4ac"}
|
||||
{"OrderListHash", "92610619a10e30863020cc84aa30be3b"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 884616;
|
||||
public long DataPoints => 476196;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -124,7 +124,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "778"},
|
||||
{"Total Trades", "418"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
@@ -143,8 +143,8 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Information Ratio", "0"},
|
||||
{"Tracking Error", "0"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$778.00"},
|
||||
{"Estimated Strategy Capacity", "$1000.00"},
|
||||
{"Total Fees", "$418.00"},
|
||||
{"Estimated Strategy Capacity", "$3000.00"},
|
||||
{"Lowest Capacity Asset", "GOOCV W78ZFMEBBB2E|GOOCV VP83T1ZUHROL"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
@@ -165,7 +165,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "6a88f302b7f29a2c59e4b1e978161da1"}
|
||||
{"OrderListHash", "7bd09d7b4f8da2b9f594ce077cd6f0ee"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 884197;
|
||||
public long DataPoints => 475777;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -162,7 +162,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "9d9f9248ee8fe30d87ff0a6f6fea5112"}
|
||||
{"OrderListHash", "838e313ba57850227ec810ed8fb85a23"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
Log(orderEvent.ToString());
|
||||
|
||||
// Check for our expected OTM option expiry
|
||||
if (orderEvent.Message == "OTM")
|
||||
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))
|
||||
@@ -175,7 +175,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "c6d089f1fb86379c74a7413a9c2f8553"}
|
||||
{"OrderListHash", "0b52bbe98ade8e3aab943e64fcf4abfe"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 1722373;
|
||||
public long DataPoints => 1322413;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -153,7 +153,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "452e7a36e0a95e33d3457a908add3ead"}
|
||||
{"OrderListHash", "0f8537495f5744c02191656d6b3f9205"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "50.0482%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "87603bd45898dd9c456745fa51f989a5"}
|
||||
{"OrderListHash", "83c9fb13ee32284702779eff8d11c608"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
164
Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsAlgorithm.cs
Normal file
164
Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsAlgorithm.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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.Data.Market;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to add and trade SPX index weekly options
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="options" />
|
||||
/// <meta name="tag" content="indexes" />
|
||||
public class BasicTemplateSPXWeeklyIndexOptionsAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _spxOption;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize your algorithm and add desired assets.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2021, 1, 4);
|
||||
SetEndDate(2021, 1, 10);
|
||||
SetCash(1000000);
|
||||
|
||||
var spx = AddIndex("SPX").Symbol;
|
||||
|
||||
// regular option SPX contracts
|
||||
var spxOptions = AddIndexOption(spx);
|
||||
spxOptions.SetFilter(u => u.Strikes(0, 1).Expiration(0, 30));
|
||||
|
||||
// weekly option SPX contracts
|
||||
var spxw = AddIndexOption(spx, "SPXW");
|
||||
spxw.SetFilter(u => u.Strikes(0, 1)
|
||||
// single week ahead since there are many SPXW contracts and we want to preserve performance
|
||||
.Expiration(0, 7)
|
||||
.IncludeWeeklys());
|
||||
|
||||
_spxOption = spxw.Symbol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Index EMA Cross trading underlying.
|
||||
/// </summary>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (Portfolio.Invested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OptionChain chain;
|
||||
if (slice.OptionChains.TryGetValue(_spxOption, out chain))
|
||||
{
|
||||
// we find at the money (ATM) put contract with closest expiration
|
||||
var atmContract = chain
|
||||
.OrderBy(x => x.Expiry)
|
||||
.ThenBy(x => Math.Abs(chain.Underlying.Price - x.Strike))
|
||||
.ThenByDescending(x => x.Right)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (atmContract != null)
|
||||
{
|
||||
// if found, buy until it expires
|
||||
MarketOrder(atmContract.Symbol, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Debug(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 Language[] Languages { get; } = { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 66015;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public virtual int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "5"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.69%"},
|
||||
{"Compounding Annual Return", "58.005%"},
|
||||
{"Drawdown", "0.400%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "0.588%"},
|
||||
{"Sharpe Ratio", "1.448"},
|
||||
{"Probabilistic Sharpe Ratio", "51.980%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.288"},
|
||||
{"Beta", "-0.04"},
|
||||
{"Annual Standard Deviation", "0.004"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-98.963"},
|
||||
{"Tracking Error", "0.072"},
|
||||
{"Treynor Ratio", "-0.149"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$8400000.00"},
|
||||
{"Lowest Capacity Asset", "SPXW 31K54PVWHUJHQ|SPX 31"},
|
||||
{"Fitness Score", "0.006"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "496.165"},
|
||||
{"Return Over Maximum Drawdown", "1786.884"},
|
||||
{"Portfolio Turnover", "0.006"},
|
||||
{"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", "174bd0a99916d58ca3f12139306940db"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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;
|
||||
using System;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to add and trade SPX index weekly option strategy
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="options" />
|
||||
/// <meta name="tag" content="indexes" />
|
||||
public class BasicTemplateSPXWeeklyIndexOptionsStrategyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _spxOption;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize your algorithm and add desired assets.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2021, 1, 4);
|
||||
SetEndDate(2021, 1, 10);
|
||||
SetCash(1000000);
|
||||
|
||||
var spx = AddIndex("SPX").Symbol;
|
||||
|
||||
// weekly option SPX contracts
|
||||
var spxw = AddIndexOption(spx, "SPXW");
|
||||
spxw.SetFilter(u => u.Strikes(0, 1)
|
||||
// single week ahead since there are many SPXW contracts and we want to preserve performance
|
||||
.Expiration(0, 7)
|
||||
.IncludeWeeklys());
|
||||
|
||||
_spxOption = spxw.Symbol;
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (Portfolio.Invested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OptionChain chain;
|
||||
if (slice.OptionChains.TryGetValue(_spxOption, out chain))
|
||||
{
|
||||
// we find the first expiration group of call options and order them in ascending strike
|
||||
var contracts = chain
|
||||
.Where(x => x.Right == OptionRight.Call)
|
||||
.OrderBy(x => x.Expiry)
|
||||
.GroupBy(x => x.Expiry)
|
||||
.First()
|
||||
.OrderBy(x => x.Strike)
|
||||
.ToList();
|
||||
|
||||
if (contracts.Count > 1)
|
||||
{
|
||||
var smallerStrike = contracts[0];
|
||||
var higherStrike = contracts[1];
|
||||
|
||||
// if found, buy until it expires
|
||||
var optionStrategy = OptionStrategies.BearCallSpread(_spxOption, smallerStrike.Strike, higherStrike.Strike, smallerStrike.Expiry);
|
||||
Buy(optionStrategy, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Debug(orderEvent.ToString());
|
||||
if (orderEvent.Symbol.ID.Symbol != "SPXW")
|
||||
{
|
||||
throw new Exception("Unexpected order event 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 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 Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 35811;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public virtual int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "4"},
|
||||
{"Average Win", "0.46%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "41.434%"},
|
||||
{"Drawdown", "0.100%"},
|
||||
{"Expectancy", "115.281"},
|
||||
{"Net Profit", "0.445%"},
|
||||
{"Sharpe Ratio", "-7.925"},
|
||||
{"Probabilistic Sharpe Ratio", "1.216%"},
|
||||
{"Loss Rate", "50%"},
|
||||
{"Win Rate", "50%"},
|
||||
{"Profit-Loss Ratio", "231.56"},
|
||||
{"Alpha", "-0.012"},
|
||||
{"Beta", "0.001"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-103.222"},
|
||||
{"Tracking Error", "0.069"},
|
||||
{"Treynor Ratio", "-2.449"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$4100000.00"},
|
||||
{"Lowest Capacity Asset", "SPXW XKX6S2GM9PGU|SPX 31"},
|
||||
{"Fitness Score", "0.001"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
|
||||
{"Portfolio Turnover", "0.001"},
|
||||
{"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", "4adb43a8298b9192e0f45d2ef1e5d370"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* 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 RDotNet;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Demonstration of the R-integration for calling external statistics operations in QuantConnect.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using r" />
|
||||
/// <meta name="tag" content="statistics libraries" />
|
||||
public class CallingRFromCSharp : QCAlgorithm
|
||||
{
|
||||
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
|
||||
AddEquity("SPY", Resolution.Second);
|
||||
|
||||
var engine = REngine.GetInstance();
|
||||
engine.Evaluate("print('This is from R command.')");
|
||||
// .NET Framework array to R vector.
|
||||
var group1 = engine.CreateNumericVector(new double[] { 30.02, 29.99, 30.11, 29.97, 30.01, 29.99 });
|
||||
engine.SetSymbol("group1", group1);
|
||||
// Direct parsing from R script.
|
||||
var group2 = engine.Evaluate("group2 <- c(29.89, 29.93, 29.72, 29.98, 30.02, 29.98)").AsNumeric();
|
||||
// Test difference of mean and get the P-value.
|
||||
var testResult = engine.Evaluate("t.test(group1, group2)").AsList();
|
||||
var p = testResult["p.value"].AsNumeric().First();
|
||||
// you should always dispose of the REngine properly.
|
||||
// After disposing of the engine, you cannot reinitialize nor reuse it
|
||||
engine.Dispose();
|
||||
|
||||
}
|
||||
|
||||
/// <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 (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings(_spy, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
112
Algorithm.CSharp/ComboLegLimitOrderAlgorithm.cs
Normal file
112
Algorithm.CSharp/ComboLegLimitOrderAlgorithm.cs
Normal file
@@ -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 QuantConnect.Orders;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm to test combo leg limit orders
|
||||
/// </summary>
|
||||
public class ComboLegLimitOrderAlgorithm : ComboOrderAlgorithm
|
||||
{
|
||||
protected override IEnumerable<OrderTicket> PlaceComboOrder(List<Leg> legs, int quantity, decimal? limitPrice = null)
|
||||
{
|
||||
return ComboLegLimitOrder(legs, quantity);
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
base.OnEndOfAlgorithm();
|
||||
|
||||
if (FillOrderEvents.Zip(OrderLegs).Any(x => x.Second.OrderPrice < x.First.FillPrice))
|
||||
{
|
||||
throw new Exception($"Limit price expected to be greater that the fill price for each order. Limit prices: {string.Join(",", OrderLegs.Select(x => x.OrderPrice))} Fill prices: {string.Join(",", FillOrderEvents.Select(x => x.FillPrice))}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 => true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public override Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 475788;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public override int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "3"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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", "$7.50"},
|
||||
{"Estimated Strategy Capacity", "$8000.00"},
|
||||
{"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Return Over Maximum Drawdown", "0"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"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", "c0f4b5d5c796e17949f7ec42c6569ce4"}
|
||||
};
|
||||
}
|
||||
}
|
||||
179
Algorithm.CSharp/ComboLimitOrderAlgorithm.cs
Normal file
179
Algorithm.CSharp/ComboLimitOrderAlgorithm.cs
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* 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.Orders;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm to test combo limit orders
|
||||
/// </summary>
|
||||
public class ComboLimitOrderAlgorithm : ComboOrderAlgorithm
|
||||
{
|
||||
private decimal _limitPrice;
|
||||
private int _comboQuantity;
|
||||
|
||||
private int _fillCount;
|
||||
|
||||
private decimal _liquidatedQuantity;
|
||||
|
||||
private bool _liquidated;
|
||||
|
||||
protected override int ExpectedFillCount
|
||||
{
|
||||
get
|
||||
{
|
||||
// times 2 because of liquidation
|
||||
return OrderLegs.Count * 2;
|
||||
}
|
||||
}
|
||||
|
||||
protected override IEnumerable<OrderTicket> PlaceComboOrder(List<Leg> legs, int quantity, decimal? limitPrice)
|
||||
{
|
||||
_limitPrice = limitPrice.Value;
|
||||
_comboQuantity = quantity;
|
||||
|
||||
legs.ForEach(x => { x.OrderPrice = null; });
|
||||
|
||||
return ComboLimitOrder(legs, quantity, _limitPrice);
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
base.OnOrderEvent(orderEvent);
|
||||
|
||||
if (orderEvent.Status == OrderStatus.Filled)
|
||||
{
|
||||
_fillCount++;
|
||||
if (_fillCount == OrderLegs.Count)
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
else if (_fillCount < 2 * OrderLegs.Count)
|
||||
{
|
||||
_liquidatedQuantity += orderEvent.FillQuantity;
|
||||
}
|
||||
else if (_fillCount == 2 * OrderLegs.Count)
|
||||
{
|
||||
_liquidated = true;
|
||||
var totalComboQuantity = _comboQuantity * OrderLegs.Select(x => x.Quantity).Sum();
|
||||
|
||||
if (_liquidatedQuantity != totalComboQuantity)
|
||||
{
|
||||
throw new Exception($"Liquidated quantity {_liquidatedQuantity} does not match combo quantity {totalComboQuantity}");
|
||||
}
|
||||
|
||||
if (Portfolio.TotalHoldingsValue != 0)
|
||||
{
|
||||
throw new Exception($"Portfolio value {Portfolio.TotalPortfolioValue} is not zero");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
base.OnEndOfAlgorithm();
|
||||
|
||||
if (_limitPrice == null)
|
||||
{
|
||||
throw new Exception("Limit price was not set");
|
||||
}
|
||||
|
||||
var fillPricesSum = FillOrderEvents.Take(OrderLegs.Count).Select(x => x.FillPrice * x.FillQuantity / _comboQuantity).Sum();
|
||||
if (_limitPrice < fillPricesSum)
|
||||
{
|
||||
throw new Exception($"Limit price expected to be greater that the sum of the fill prices ({fillPricesSum}), but was {_limitPrice}");
|
||||
}
|
||||
|
||||
if (!_liquidated)
|
||||
{
|
||||
throw new Exception("Combo order was not 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 override bool CanRunLocally => true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public override Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 475788;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public override int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "6"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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", "$17.50"},
|
||||
{"Estimated Strategy Capacity", "$5000.00"},
|
||||
{"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Return Over Maximum Drawdown", "0"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"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", "17a5427a539f2b02a626fda15d6eb13f"}
|
||||
};
|
||||
}
|
||||
}
|
||||
101
Algorithm.CSharp/ComboMarketOrderAlgorithm.cs
Normal file
101
Algorithm.CSharp/ComboMarketOrderAlgorithm.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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.Orders;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm to test combo market orders
|
||||
/// </summary>
|
||||
public class ComboMarketOrderAlgorithm : ComboOrderAlgorithm
|
||||
{
|
||||
protected override IEnumerable<OrderTicket> PlaceComboOrder(List<Leg> legs, int quantity, decimal? limitPrice = null)
|
||||
{
|
||||
legs.ForEach(x => { x.OrderPrice = null; });
|
||||
return ComboMarketOrder(legs, quantity);
|
||||
}
|
||||
|
||||
/// <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 => true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public override Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 475788;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public override int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "3"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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", "$7.50"},
|
||||
{"Estimated Strategy Capacity", "$9000.00"},
|
||||
{"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Return Over Maximum Drawdown", "0"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"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", "47f02f5139c4c4def9b26e8f5433fdcc"}
|
||||
};
|
||||
}
|
||||
}
|
||||
139
Algorithm.CSharp/ComboOrderAlgorithm.cs
Normal file
139
Algorithm.CSharp/ComboOrderAlgorithm.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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 System.Collections.Generic;
|
||||
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm asserting that combo orders are filled correctly and at the same time
|
||||
/// </summary>
|
||||
public abstract class ComboOrderAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _optionSymbol;
|
||||
|
||||
protected List<OrderEvent> FillOrderEvents { get; private set; } = new();
|
||||
|
||||
protected List<Leg> OrderLegs { get; private set; }
|
||||
|
||||
protected int ComboOrderQuantity { get; } = 10;
|
||||
|
||||
protected virtual int ExpectedFillCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return OrderLegs.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2015, 12, 24);
|
||||
SetEndDate(2015, 12, 24);
|
||||
SetCash(10000);
|
||||
|
||||
var equity = AddEquity("GOOG", leverage: 4, fillDataForward: true);
|
||||
var option = AddOption(equity.Symbol, fillDataForward: true);
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(u => u.Strikes(-2, +2)
|
||||
.Expiration(0, 180));
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (OrderLegs == null)
|
||||
{
|
||||
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();
|
||||
|
||||
// Let's wait until we have at least three contracts
|
||||
if (callContracts.Count < 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OrderLegs = new List<Leg>()
|
||||
{
|
||||
Leg.Create(callContracts[0].Symbol, 1, 16.7m),
|
||||
Leg.Create(callContracts[1].Symbol, -2, 14.6m),
|
||||
Leg.Create(callContracts[2].Symbol, 1, 14.0m)
|
||||
};
|
||||
PlaceComboOrder(OrderLegs, ComboOrderQuantity, 1.9m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Debug($" Order Event: {orderEvent}");
|
||||
|
||||
if (orderEvent.Status == OrderStatus.Filled)
|
||||
{
|
||||
FillOrderEvents.Add(orderEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (OrderLegs == null)
|
||||
{
|
||||
throw new Exception("Combo order legs were not initialized");
|
||||
}
|
||||
|
||||
if (FillOrderEvents.Count != ExpectedFillCount)
|
||||
{
|
||||
throw new Exception($"Expected {ExpectedFillCount} fill order events, found {FillOrderEvents.Count}");
|
||||
}
|
||||
|
||||
var fillTimes = FillOrderEvents.Select(x => x.UtcTime).ToHashSet();
|
||||
if (fillTimes.Count != 1)
|
||||
{
|
||||
throw new Exception($"Expected all fill order events to have the same time, found {string.Join(", ", fillTimes)}");
|
||||
}
|
||||
|
||||
if (FillOrderEvents.Zip(OrderLegs).Any(x => x.First.FillQuantity != x.Second.Quantity * ComboOrderQuantity))
|
||||
{
|
||||
throw new Exception("Fill quantity does not match expected quantity for at least one order leg");
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<OrderTicket> PlaceComboOrder(List<Leg> legs, int quantity, decimal? limitPrice = null);
|
||||
|
||||
public abstract bool CanRunLocally { get; }
|
||||
|
||||
public abstract Language[] Languages { get; }
|
||||
|
||||
public abstract long DataPoints { get; }
|
||||
|
||||
public abstract int AlgorithmHistoryDataPoints { get; }
|
||||
|
||||
public abstract Dictionary<string, string> ExpectedStatistics { get; }
|
||||
}
|
||||
}
|
||||
375
Algorithm.CSharp/ComboOrderTicketDemoAlgorithm.cs
Normal file
375
Algorithm.CSharp/ComboOrderTicketDemoAlgorithm.cs
Normal file
@@ -0,0 +1,375 @@
|
||||
|
||||
/*
|
||||
* 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.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data.Market;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm for testing submit/update/cancel for combo orders
|
||||
/// </summary>
|
||||
public class ComboOrderTicketDemoAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private readonly List<OrderTicket> _openMarketOrders = new();
|
||||
private readonly List<OrderTicket> _openLegLimitOrders = new();
|
||||
private readonly List<OrderTicket> _openLimitOrders = new();
|
||||
|
||||
private Symbol _optionSymbol;
|
||||
private List<Leg> _orderLegs;
|
||||
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2015, 12, 24);
|
||||
SetEndDate(2015, 12, 24);
|
||||
SetCash(100000);
|
||||
|
||||
var equity = AddEquity("GOOG", leverage: 4, fillDataForward: true);
|
||||
var option = AddOption(equity.Symbol, fillDataForward: true);
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(u => u.Strikes(-2, +2)
|
||||
.Expiration(0, 180));
|
||||
}
|
||||
|
||||
public override void OnData(Slice data)
|
||||
{
|
||||
if (_orderLegs == null)
|
||||
{
|
||||
OptionChain chain;
|
||||
if (IsMarketOpen(_optionSymbol) && data.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();
|
||||
|
||||
// Let's wait until we have at least three contracts
|
||||
if (callContracts.Count < 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_orderLegs = new List<Leg>()
|
||||
{
|
||||
Leg.Create(callContracts[0].Symbol, 1),
|
||||
Leg.Create(callContracts[1].Symbol, -2),
|
||||
Leg.Create(callContracts[2].Symbol, 1),
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// COMBO MARKET ORDERS
|
||||
|
||||
ComboMarketOrders();
|
||||
|
||||
// COMBO LIMIT ORDERS
|
||||
|
||||
ComboLimitOrders();
|
||||
|
||||
// COMBO LEG LIMIT ORDERS
|
||||
|
||||
ComboLegLimitOrders();
|
||||
}
|
||||
}
|
||||
|
||||
private void ComboMarketOrders()
|
||||
{
|
||||
if (_openMarketOrders.Count != 0 || _orderLegs == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log("Submitting combo market orders");
|
||||
|
||||
var tickets = ComboMarketOrder(_orderLegs, 2, asynchronous: false);
|
||||
_openMarketOrders.AddRange(tickets);
|
||||
|
||||
tickets = ComboMarketOrder(_orderLegs, 2, asynchronous: true);
|
||||
_openMarketOrders.AddRange(tickets);
|
||||
|
||||
foreach (var ticket in tickets)
|
||||
{
|
||||
var response = ticket.Cancel("Attempt to cancel combo market order");
|
||||
if (response.IsSuccess)
|
||||
{
|
||||
throw new Exception("Combo market orders should fill instantly, they should not be cancelable in backtest mode: " + response.OrderId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ComboLimitOrders()
|
||||
{
|
||||
if (_openLimitOrders.Count == 0)
|
||||
{
|
||||
Log("Submitting ComboLimitOrder");
|
||||
|
||||
var currentPrice = _orderLegs.Sum(leg => leg.Quantity * Securities[leg.Symbol].Close);
|
||||
|
||||
var tickets = ComboLimitOrder(_orderLegs, 2, currentPrice - 2m);
|
||||
_openLimitOrders.AddRange(tickets);
|
||||
|
||||
// These won't fill, we will test cancel with this
|
||||
tickets = ComboLimitOrder(_orderLegs, -2, currentPrice + 3m);
|
||||
_openLimitOrders.AddRange(tickets);
|
||||
}
|
||||
else
|
||||
{
|
||||
var combo1 = _openLimitOrders.Take(_orderLegs.Count).ToList();
|
||||
var combo2 = _openLimitOrders.Skip(_orderLegs.Count).Take(_orderLegs.Count).ToList();
|
||||
|
||||
// check if either is filled and cancel the other
|
||||
if (CheckGroupOrdersForFills(combo1, combo2))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if neither order has filled, bring in the limits by a penny
|
||||
|
||||
var ticket = combo1[0];
|
||||
var newLimit = Math.Round(ticket.Get(OrderField.LimitPrice) + 0.01m, 2);
|
||||
Debug($"Updating limits - Combo 1 {ticket.OrderId}: {newLimit.ToStringInvariant("0.00")}");
|
||||
ticket.Update(new UpdateOrderFields
|
||||
{
|
||||
LimitPrice = newLimit,
|
||||
Tag = "Update #" + (ticket.UpdateRequests.Count + 1)
|
||||
});
|
||||
|
||||
ticket = combo2[0];
|
||||
newLimit = Math.Round(ticket.Get(OrderField.LimitPrice) - 0.01m, 2);
|
||||
Debug($"Updating limits - Combo 2 {ticket.OrderId}: {newLimit.ToStringInvariant("0.00")}");
|
||||
ticket.Update(new UpdateOrderFields
|
||||
{
|
||||
LimitPrice = newLimit,
|
||||
Tag = "Update #" + (ticket.UpdateRequests.Count + 1)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void ComboLegLimitOrders()
|
||||
{
|
||||
if (_openLegLimitOrders.Count == 0)
|
||||
{
|
||||
Log("Submitting ComboLegLimitOrder");
|
||||
|
||||
// submit a limit order to buy 2 shares at .1% below the bar's close
|
||||
foreach (var leg in _orderLegs)
|
||||
{
|
||||
var close = Securities[leg.Symbol].Close;
|
||||
leg.OrderPrice = close * .999m;
|
||||
}
|
||||
|
||||
var tickets = ComboLegLimitOrder(_orderLegs, quantity: 2);
|
||||
_openLegLimitOrders.AddRange(tickets);
|
||||
|
||||
// submit another limit order to sell 2 shares at .1% above the bar's close
|
||||
foreach (var leg in _orderLegs)
|
||||
{
|
||||
var close = Securities[leg.Symbol].Close;
|
||||
leg.OrderPrice = close * 1.001m;
|
||||
}
|
||||
|
||||
tickets = ComboLegLimitOrder(_orderLegs, -2);
|
||||
_openLegLimitOrders.AddRange(tickets);
|
||||
}
|
||||
else
|
||||
{
|
||||
var combo1 = _openLegLimitOrders.Take(_orderLegs.Count).ToList();
|
||||
var combo2 = _openLegLimitOrders.Skip(_orderLegs.Count).Take(_orderLegs.Count).ToList();
|
||||
|
||||
// check if either is filled and cancel the other
|
||||
if (CheckGroupOrdersForFills(combo1, combo2))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if neither order has filled, bring in the limits by a penny
|
||||
|
||||
foreach (var ticket in combo1)
|
||||
{
|
||||
var newLimit = ticket.Get(OrderField.LimitPrice) + (ticket.Quantity > 0 ? 1m : -1m) * 0.01m;
|
||||
Debug($"Updating limits - Combo #1: {newLimit.ToStringInvariant("0.00")}");
|
||||
|
||||
ticket.Update(new UpdateOrderFields
|
||||
{
|
||||
LimitPrice = newLimit,
|
||||
Tag = "Update #" + (ticket.UpdateRequests.Count + 1)
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var ticket in combo2)
|
||||
{
|
||||
var newLimit = ticket.Get(OrderField.LimitPrice) + (ticket.Quantity > 0 ? 1m : -1m) * 0.01m;
|
||||
Debug($"Updating limits - Combo #2: {newLimit.ToStringInvariant("0.00")}");
|
||||
|
||||
ticket.Update(new UpdateOrderFields
|
||||
{
|
||||
LimitPrice = newLimit,
|
||||
Tag = "Update #" + (ticket.UpdateRequests.Count + 1)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
var order = Transactions.GetOrderById(orderEvent.OrderId);
|
||||
|
||||
if (orderEvent.Quantity == 0)
|
||||
{
|
||||
throw new Exception("OrderEvent quantity is Not expected to be 0, it should hold the current order Quantity");
|
||||
}
|
||||
if (orderEvent.Quantity != order.Quantity)
|
||||
{
|
||||
throw new Exception("OrderEvent quantity should hold the current order Quantity");
|
||||
}
|
||||
if (order is ComboLegLimitOrder && orderEvent.LimitPrice == 0)
|
||||
{
|
||||
throw new Exception("OrderEvent.LimitPrice is not expected to be 0 for ComboLegLimitOrder");
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckGroupOrdersForFills(List<OrderTicket> combo1, List<OrderTicket> combo2)
|
||||
{
|
||||
if (combo1.All(x => x.Status == OrderStatus.Filled))
|
||||
{
|
||||
if (combo2.Any(x => x.Status.IsOpen()))
|
||||
{
|
||||
Log(combo1[0].OrderType + ": Canceling combo #2, combo #1 is filled.");
|
||||
combo2.ForEach(x => x.Cancel("Combo #1 filled."));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (combo2.All(x => x.Status == OrderStatus.Filled))
|
||||
{
|
||||
if (combo1.Any(x => x.Status.IsOpen()))
|
||||
{
|
||||
Log(combo1[0].OrderType + ": Canceling combo #1, combo #2 is filled.");
|
||||
combo1.ForEach(x => x.Cancel("Combo #2 filled."));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
var filledOrders = Transactions.GetOrders(x => x.Status == OrderStatus.Filled).ToList();
|
||||
var orderTickets = Transactions.GetOrderTickets().ToList();
|
||||
var openOrders = Transactions.GetOpenOrders();
|
||||
var openOrderTickets = Transactions.GetOpenOrderTickets().ToList();
|
||||
var remainingOpenOrders = Transactions.GetOpenOrdersRemainingQuantity();
|
||||
|
||||
// We expect 3 of the limit orders to be canceled
|
||||
var expectedOrdersCount = 18;
|
||||
var expectedFillsCount = 15;
|
||||
if (filledOrders.Count != expectedFillsCount || orderTickets.Count != expectedOrdersCount)
|
||||
{
|
||||
throw new Exception($"There were expected {expectedFillsCount} filled orders and {expectedOrdersCount} order tickets, but there were {filledOrders.Count} filled orders and {orderTickets.Count} order tickets");
|
||||
}
|
||||
if (openOrders.Count != 0 || openOrderTickets.Count != 0)
|
||||
{
|
||||
throw new Exception($"No open orders or tickets were expected");
|
||||
}
|
||||
if (remainingOpenOrders != 0m)
|
||||
{
|
||||
throw new Exception($"No remaining quantity to be filled from open orders was 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 Language[] Languages { get; } = { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 475788;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "15"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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", "$15.00"},
|
||||
{"Estimated Strategy Capacity", "$8000.00"},
|
||||
{"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Return Over Maximum Drawdown", "0"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"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", "06328fbd9bbb25d9ec80b9151a7ceb7b"}
|
||||
};
|
||||
}
|
||||
}
|
||||
216
Algorithm.CSharp/CompleteOrderTagUpdateAlgorithm.cs
Normal file
216
Algorithm.CSharp/CompleteOrderTagUpdateAlgorithm.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* 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.Orders;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm asserting that closed orders can be updated with a new tag
|
||||
/// </summary>
|
||||
public class CompleteOrderTagUpdateAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private static string TagAfterFill = "This is the tag set after order was filled.";
|
||||
private static string TagAfterCanceled = "This is the tag set after order was canceled.";
|
||||
|
||||
private OrderTicket _marketOrderTicket;
|
||||
private OrderTicket _limitOrderTicket;
|
||||
|
||||
private int _quantity = 100;
|
||||
|
||||
private Symbol _spy;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07);
|
||||
SetEndDate(2013, 10, 11);
|
||||
SetCash(100000);
|
||||
|
||||
_spy = AddEquity("SPY", Resolution.Minute).Symbol;
|
||||
}
|
||||
|
||||
public override void OnData(Slice data)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
// a limit order to test the tag update after order was canceled
|
||||
if (_limitOrderTicket == null)
|
||||
{
|
||||
// low price, we don't want it to fill since we are canceling it
|
||||
_limitOrderTicket = LimitOrder(_spy, 100, Securities[_spy].Price * 0.1m);
|
||||
_limitOrderTicket.Cancel();
|
||||
}
|
||||
// a market order to test the tag update after order was filled
|
||||
else
|
||||
{
|
||||
Buy(_spy, _quantity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
if (orderEvent.Status == OrderStatus.Canceled)
|
||||
{
|
||||
if (orderEvent.OrderId != _limitOrderTicket.OrderId)
|
||||
{
|
||||
throw new Exception("The only canceled order should have been the limit order.");
|
||||
}
|
||||
|
||||
// update canceled order tag
|
||||
UpdateOrderTag(_limitOrderTicket, TagAfterCanceled, "Error updating order tag after canceled");
|
||||
}
|
||||
else if (orderEvent.Status == OrderStatus.Filled)
|
||||
{
|
||||
_marketOrderTicket = Transactions.GetOrderTickets(x => x.OrderType == OrderType.Market).Single();
|
||||
if (orderEvent.OrderId != _marketOrderTicket.OrderId)
|
||||
{
|
||||
throw new Exception("The only filled order should have been the market order.");
|
||||
}
|
||||
|
||||
// try to update a field other than the tag
|
||||
var updateFields = new UpdateOrderFields();
|
||||
updateFields.Quantity = 50;
|
||||
var response = _marketOrderTicket.Update(updateFields);
|
||||
if (response.IsSuccess)
|
||||
{
|
||||
throw new Exception("The market order quantity should not have been updated.");
|
||||
}
|
||||
|
||||
// update filled order tag
|
||||
UpdateOrderTag(_marketOrderTicket, TagAfterFill, "Error updating order tag after fill");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
// check the filled order
|
||||
AssertOrderTagUpdate(_marketOrderTicket, TagAfterFill, "filled");
|
||||
if (_marketOrderTicket.Quantity != _quantity || _marketOrderTicket.QuantityFilled != _quantity)
|
||||
{
|
||||
throw new Exception("The market order quantity should not have been updated.");
|
||||
}
|
||||
|
||||
// check the canceled order
|
||||
AssertOrderTagUpdate(_limitOrderTicket, TagAfterCanceled, "canceled");
|
||||
}
|
||||
|
||||
private void AssertOrderTagUpdate(OrderTicket ticket, string expectedTag, string orderAction)
|
||||
{
|
||||
if (ticket == null)
|
||||
{
|
||||
throw new Exception($"The order ticket was not set for the {orderAction} order");
|
||||
}
|
||||
|
||||
if (ticket.Tag != expectedTag)
|
||||
{
|
||||
throw new Exception($"Order ticket tag was not updated after order was {orderAction}");
|
||||
}
|
||||
|
||||
var order = Transactions.GetOrderById(ticket.OrderId);
|
||||
if (order.Tag != expectedTag)
|
||||
{
|
||||
throw new Exception($"Order tag was not updated after order was {orderAction}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateOrderTag(OrderTicket ticket, string tag, string errorMessagePrefix)
|
||||
{
|
||||
var updateFields = new UpdateOrderFields();
|
||||
updateFields.Tag = tag;
|
||||
var response = ticket.Update(updateFields);
|
||||
|
||||
if (response.IsError)
|
||||
{
|
||||
throw new Exception($"{errorMessagePrefix}: {response.ErrorMessage}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 Language[] Languages { get; } = { 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>
|
||||
/// 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 Trades", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "21.706%"},
|
||||
{"Drawdown", "0.300%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0.251%"},
|
||||
{"Sharpe Ratio", "5.312"},
|
||||
{"Probabilistic Sharpe Ratio", "67.483%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.115"},
|
||||
{"Beta", "0.144"},
|
||||
{"Annual Standard Deviation", "0.032"},
|
||||
{"Annual Variance", "0.001"},
|
||||
{"Information Ratio", "-9.515"},
|
||||
{"Tracking Error", "0.191"},
|
||||
{"Treynor Ratio", "1.182"},
|
||||
{"Total Fees", "$1.00"},
|
||||
{"Estimated Strategy Capacity", "$210000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Fitness Score", "0.036"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "72.372"},
|
||||
{"Portfolio Turnover", "0.036"},
|
||||
{"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", "cbf413671bbd919d0113b4f2a6a9608f"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,9 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// </summary>
|
||||
public class ConsolidateRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private List<int> _consolidationCount;
|
||||
private List<int> _consolidationCounts;
|
||||
private List<SimpleMovingAverage> _smas;
|
||||
private List<DateTime> _lastSmaUpdates;
|
||||
private int _customDataConsolidator;
|
||||
private Symbol _symbol;
|
||||
|
||||
@@ -40,38 +42,37 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 08);
|
||||
SetEndDate(2013, 10, 11);
|
||||
SetEndDate(2013, 10, 20);
|
||||
|
||||
var SP500 = QuantConnect.Symbol.Create(Futures.Indices.SP500EMini, SecurityType.Future, Market.CME);
|
||||
_symbol = FutureChainProvider.GetFutureContractList(SP500, StartDate).First();
|
||||
AddFutureContract(_symbol);
|
||||
|
||||
_consolidationCount = new List<int> { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
_consolidationCounts = Enumerable.Repeat(0, 9).ToList();
|
||||
_smas = _consolidationCounts.Select(_ => new SimpleMovingAverage(10)).ToList();
|
||||
_lastSmaUpdates = _consolidationCounts.Select(_ => DateTime.MinValue).ToList();
|
||||
|
||||
var sma = new SimpleMovingAverage(10);
|
||||
Consolidate<QuoteBar>(_symbol, time => new CalendarInfo(time.RoundDown(TimeSpan.FromDays(1)), TimeSpan.FromDays(1)),
|
||||
bar => UpdateQuoteBar(sma, bar, 0));
|
||||
bar => UpdateQuoteBar(bar, 0));
|
||||
|
||||
var sma2 = new SimpleMovingAverage(10);
|
||||
Consolidate<QuoteBar>(_symbol, TimeSpan.FromDays(1), bar => UpdateQuoteBar(sma2, bar, 1));
|
||||
Consolidate<QuoteBar>(_symbol, time => new CalendarInfo(time.RoundDown(TimeSpan.FromDays(1)), TimeSpan.FromDays(1)),
|
||||
TickType.Quote, bar => UpdateQuoteBar(bar, 1));
|
||||
|
||||
var sma3 = new SimpleMovingAverage(10);
|
||||
Consolidate(_symbol, Resolution.Daily, TickType.Quote, (Action<QuoteBar>)(bar => UpdateQuoteBar(sma3, bar, 2)));
|
||||
Consolidate<QuoteBar>(_symbol, TimeSpan.FromDays(1), bar => UpdateQuoteBar(bar, 2));
|
||||
|
||||
var sma4 = new SimpleMovingAverage(10);
|
||||
Consolidate(_symbol, TimeSpan.FromDays(1), bar => UpdateTradeBar(sma4, bar, 3));
|
||||
Consolidate(_symbol, Resolution.Daily, TickType.Quote, (Action<QuoteBar>)(bar => UpdateQuoteBar(bar, 3)));
|
||||
|
||||
var sma5 = new SimpleMovingAverage(10);
|
||||
Consolidate<TradeBar>(_symbol, TimeSpan.FromDays(1), bar => UpdateTradeBar(sma5, bar, 4));
|
||||
Consolidate(_symbol, TimeSpan.FromDays(1), bar => UpdateTradeBar(bar, 4));
|
||||
|
||||
Consolidate<TradeBar>(_symbol, TimeSpan.FromDays(1), bar => UpdateTradeBar(bar, 5));
|
||||
|
||||
// custom data
|
||||
var sma6 = new SimpleMovingAverage(10);
|
||||
var symbol = AddData<CustomDataRegressionAlgorithm.Bitcoin>("BTC", Resolution.Minute).Symbol;
|
||||
Consolidate<TradeBar>(symbol, TimeSpan.FromDays(1), bar => _customDataConsolidator++);
|
||||
|
||||
try
|
||||
{
|
||||
Consolidate<QuoteBar>(symbol, TimeSpan.FromDays(1), bar => { UpdateQuoteBar(sma6, bar, -1); });
|
||||
Consolidate<QuoteBar>(symbol, TimeSpan.FromDays(1), bar => { UpdateQuoteBar(bar, -1); });
|
||||
throw new Exception($"Expected {nameof(ArgumentException)} to be thrown");
|
||||
}
|
||||
catch (ArgumentException)
|
||||
@@ -80,41 +81,56 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
}
|
||||
|
||||
// Test using abstract T types, through defining a 'BaseData' handler
|
||||
var sma7 = new SimpleMovingAverage(10);
|
||||
Consolidate(_symbol, Resolution.Daily, null, (Action<BaseData>)(bar => UpdateBar(sma7, bar, 5)));
|
||||
Consolidate(_symbol, Resolution.Daily, null, (Action<BaseData>)(bar => UpdateBar(bar, 6)));
|
||||
|
||||
var sma8 = new SimpleMovingAverage(10);
|
||||
Consolidate(_symbol, TimeSpan.FromDays(1), null, (Action<BaseData>)(bar => UpdateBar(sma8, bar, 6)));
|
||||
Consolidate(_symbol, TimeSpan.FromDays(1), null, (Action<BaseData>)(bar => UpdateBar(bar, 7)));
|
||||
|
||||
var sma9 = new SimpleMovingAverage(10);
|
||||
Consolidate(_symbol, TimeSpan.FromDays(1), (Action<BaseData>)(bar => UpdateBar(sma9, bar, 7)));
|
||||
Consolidate(_symbol, TimeSpan.FromDays(1), (Action<BaseData>)(bar => UpdateBar(bar, 8)));
|
||||
}
|
||||
private void UpdateBar(SimpleMovingAverage sma, BaseData tradeBar, int position)
|
||||
private void UpdateBar(BaseData tradeBar, int position)
|
||||
{
|
||||
if (!(tradeBar is TradeBar))
|
||||
{
|
||||
throw new Exception("Expected a TradeBar");
|
||||
}
|
||||
_consolidationCount[position]++;
|
||||
sma.Update(tradeBar.EndTime, tradeBar.Value);
|
||||
_consolidationCounts[position]++;
|
||||
_smas[position].Update(tradeBar.EndTime, tradeBar.Value);
|
||||
_lastSmaUpdates[position] = tradeBar.EndTime;
|
||||
}
|
||||
private void UpdateTradeBar(SimpleMovingAverage sma, TradeBar tradeBar, int position)
|
||||
private void UpdateTradeBar(TradeBar tradeBar, int position)
|
||||
{
|
||||
_consolidationCount[position]++;
|
||||
sma.Update(tradeBar.EndTime, tradeBar.High);
|
||||
_consolidationCounts[position]++;
|
||||
_smas[position].Update(tradeBar.EndTime, tradeBar.High);
|
||||
_lastSmaUpdates[position] = tradeBar.EndTime;
|
||||
}
|
||||
private void UpdateQuoteBar(SimpleMovingAverage sma, QuoteBar quoteBar, int position)
|
||||
private void UpdateQuoteBar(QuoteBar quoteBar, int position)
|
||||
{
|
||||
_consolidationCount[position]++;
|
||||
sma.Update(quoteBar.EndTime, quoteBar.High);
|
||||
_consolidationCounts[position]++;
|
||||
_smas[position].Update(quoteBar.EndTime, quoteBar.High);
|
||||
_lastSmaUpdates[position] = quoteBar.EndTime;
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (_consolidationCount.Any(i => i != 3) || _customDataConsolidator == 0)
|
||||
var expectedConsolidations = 8;
|
||||
|
||||
if (_consolidationCounts.Any(i => i != expectedConsolidations) || _customDataConsolidator == 0)
|
||||
{
|
||||
throw new Exception("Unexpected consolidation count");
|
||||
}
|
||||
|
||||
for (var i = 0; i < _smas.Count; i++)
|
||||
{
|
||||
if (_smas[i].Samples != expectedConsolidations)
|
||||
{
|
||||
throw new Exception($"Expected {expectedConsolidations} samples in each SMA but found {_smas[i].Samples} in SMA in index {i}");
|
||||
}
|
||||
|
||||
if (_smas[i].Current.Time != _lastSmaUpdates[i])
|
||||
{
|
||||
throw new Exception($"Expected SMA in index {i} to have been last updated at {_lastSmaUpdates[i]} but was {_smas[i].Current.Time}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -142,7 +158,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 5450;
|
||||
public long DataPoints => 12244;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -157,31 +173,31 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Total Trades", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "87589624.963%"},
|
||||
{"Compounding Annual Return", "6636.699%"},
|
||||
{"Drawdown", "15.900%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "16.178%"},
|
||||
{"Sharpe Ratio", "43229388091.465"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Sharpe Ratio", "640.32"},
|
||||
{"Probabilistic Sharpe Ratio", "99.824%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "69177566862.121"},
|
||||
{"Beta", "8.93"},
|
||||
{"Annual Standard Deviation", "1.6"},
|
||||
{"Annual Variance", "2.561"},
|
||||
{"Information Ratio", "48583550955.512"},
|
||||
{"Tracking Error", "1.424"},
|
||||
{"Treynor Ratio", "7746445590.006"},
|
||||
{"Alpha", "636.128"},
|
||||
{"Beta", "5.924"},
|
||||
{"Annual Standard Deviation", "1.012"},
|
||||
{"Annual Variance", "1.024"},
|
||||
{"Information Ratio", "696.123"},
|
||||
{"Tracking Error", "0.928"},
|
||||
{"Treynor Ratio", "109.405"},
|
||||
{"Total Fees", "$23.65"},
|
||||
{"Estimated Strategy Capacity", "$210000000.00"},
|
||||
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
|
||||
{"Fitness Score", "0.999"},
|
||||
{"Fitness Score", "0.811"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "6752050.52"},
|
||||
{"Portfolio Turnover", "2.638"},
|
||||
{"Return Over Maximum Drawdown", "511.605"},
|
||||
{"Portfolio Turnover", "0.811"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 264153;
|
||||
public long DataPoints => 689388;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -172,7 +172,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0.275"},
|
||||
{"Return Over Maximum Drawdown", "2.603"},
|
||||
{"Return Over Maximum Drawdown", "2.606"},
|
||||
{"Portfolio Turnover", "0.01"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 284403;
|
||||
public long DataPoints => 709638;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -188,7 +188,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0.32"},
|
||||
{"Return Over Maximum Drawdown", "2.573"},
|
||||
{"Return Over Maximum Drawdown", "2.576"},
|
||||
{"Portfolio Turnover", "0.016"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
|
||||
@@ -115,8 +115,8 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Fitness Score", "0.028"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-1.662"},
|
||||
{"Return Over Maximum Drawdown", "-18.253"},
|
||||
{"Sortino Ratio", "-1.666"},
|
||||
{"Return Over Maximum Drawdown", "-18.301"},
|
||||
{"Portfolio Turnover", "0.206"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
|
||||
@@ -169,7 +169,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 284403;
|
||||
public long DataPoints => 709638;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -207,7 +207,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0.32"},
|
||||
{"Return Over Maximum Drawdown", "2.573"},
|
||||
{"Return Over Maximum Drawdown", "2.576"},
|
||||
{"Portfolio Turnover", "0.016"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
|
||||
168
Algorithm.CSharp/ContinuousFuturesDailyRegressionAlgorithm.cs
Normal file
168
Algorithm.CSharp/ContinuousFuturesDailyRegressionAlgorithm.cs
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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 QuantConnect.Securities;
|
||||
using QuantConnect.Data.Market;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Securities.Future;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Continuous Futures Regression algorithm asserting bug fix for GH issue #6840
|
||||
/// </summary>
|
||||
public class ContinuousFuturesDailyRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private SymbolChangedEvent _symbolChangedEvent;
|
||||
private Future _continuousContract;
|
||||
private decimal _previousFactor;
|
||||
|
||||
/// <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);
|
||||
SetEndDate(2013, 12, 25);
|
||||
|
||||
_continuousContract = AddFuture(Futures.Indices.SP500EMini,
|
||||
dataNormalizationMode: DataNormalizationMode.ForwardPanamaCanal,
|
||||
dataMappingMode: DataMappingMode.LastTradingDay,
|
||||
contractDepthOffset: 0,
|
||||
resolution: 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 data)
|
||||
{
|
||||
foreach (var changedEvent in data.SymbolChangedEvents.Values)
|
||||
{
|
||||
if (changedEvent.Symbol == _continuousContract.Symbol)
|
||||
{
|
||||
_symbolChangedEvent = changedEvent;
|
||||
Log($"{Time} - SymbolChanged event: {changedEvent}. New expiration {_continuousContract.Mapped.ID.Date}");
|
||||
}
|
||||
}
|
||||
|
||||
if (!data.Bars.TryGetValue(_continuousContract.Symbol, out var continuousBar))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var mappedBar = Securities[_continuousContract.Mapped].Cache.GetData<TradeBar>();
|
||||
if (mappedBar == null || continuousBar.EndTime != mappedBar.EndTime)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var priceFactor = continuousBar.Close - mappedBar.Close;
|
||||
Debug($"{Time} - Price factor {priceFactor}");
|
||||
|
||||
if(_symbolChangedEvent != null)
|
||||
{
|
||||
if(_previousFactor == priceFactor)
|
||||
{
|
||||
throw new Exception($"Price factor did not change after symbol changed! {Time} {priceFactor}");
|
||||
}
|
||||
|
||||
Quit("We asserted what we wanted");
|
||||
}
|
||||
_previousFactor = priceFactor;
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (_symbolChangedEvent == null)
|
||||
{
|
||||
throw new Exception("Unexpected a symbol changed event but got none!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 1395;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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", "-4.63"},
|
||||
{"Tracking Error", "0.088"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"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", "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;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm asserting that consolidated bars are of type <see cref="QuoteBar"/>
|
||||
/// when <see cref="QCAlgorithm.Consolidate()"/> is called with <see cref="TickType.Quote"/>
|
||||
/// </summary>
|
||||
public class CorrectConsolidatedBarTypeForTickTypesAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private bool _quoteTickConsolidatorCalled;
|
||||
private bool _tradeTickConsolidatorCalled;
|
||||
private bool _openInterestTickConsolidatorCalled;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 7);
|
||||
SetEndDate(2013, 10, 7);
|
||||
|
||||
var symbol = AddEquity("SPY", Resolution.Tick).Symbol;
|
||||
|
||||
Consolidate<QuoteBar>(symbol, TimeSpan.FromMinutes(1), TickType.Quote, QuoteTickConsolidationHandler);
|
||||
Consolidate<TradeBar>(symbol, TimeSpan.FromMinutes(1), TickType.Trade, TradeTickConsolidationHandler);
|
||||
Consolidate<TradeBar>(symbol, TimeSpan.FromMinutes(1), TickType.OpenInterest, OpenInterestTickConsolidationHandler);
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (Time.Hour > 9)
|
||||
{
|
||||
Quit("Early quit to save time");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_quoteTickConsolidatorCalled)
|
||||
{
|
||||
throw new Exception("QuoteTickConsolidationHandler was not called");
|
||||
}
|
||||
|
||||
if (!_tradeTickConsolidatorCalled)
|
||||
{
|
||||
throw new Exception("TradeTickConsolidationHandler was not called");
|
||||
}
|
||||
|
||||
if (!_openInterestTickConsolidatorCalled)
|
||||
{
|
||||
throw new Exception("OpenInterestTickConsolidationHandler was not called");
|
||||
}
|
||||
}
|
||||
|
||||
private void QuoteTickConsolidationHandler(QuoteBar consolidatedBar)
|
||||
{
|
||||
_quoteTickConsolidatorCalled = true;
|
||||
}
|
||||
|
||||
private void TradeTickConsolidationHandler(TradeBar consolidatedBar)
|
||||
{
|
||||
_tradeTickConsolidatorCalled = true;
|
||||
}
|
||||
|
||||
private void OpenInterestTickConsolidationHandler(TradeBar consolidatedBar)
|
||||
{
|
||||
_openInterestTickConsolidatorCalled = true;
|
||||
}
|
||||
|
||||
/// <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 Language[] Languages { get; } = { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 393736;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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", ""},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Return Over Maximum Drawdown", "0"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"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", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
165
Algorithm.CSharp/CoveredCallComboLimitOrderAlgorithm.cs
Normal file
165
Algorithm.CSharp/CoveredCallComboLimitOrderAlgorithm.cs
Normal file
@@ -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.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Data.Market;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm tarding an equity Covered Call option strategy using a combo limit order
|
||||
/// </summary>
|
||||
public class CoveredCallComboLimitOrderAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private DateTime _submittionTime;
|
||||
private Symbol _optionSymbol;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2015, 12, 24);
|
||||
SetEndDate(2015, 12, 24);
|
||||
SetCash(200000);
|
||||
|
||||
var equity = AddEquity("GOOG", leverage: 4);
|
||||
var option = AddOption(equity.Symbol);
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(u => u.Strikes(-1, +1).Expiration(0, 30));
|
||||
}
|
||||
/// <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 && Transactions.OrdersCount == 0)
|
||||
{
|
||||
OptionChain chain;
|
||||
if (IsMarketOpen(_optionSymbol) && slice.OptionChains.TryGetValue(_optionSymbol, out chain))
|
||||
{
|
||||
// we find at the money (ATM) call contract with closest expiration
|
||||
var atmContract = chain
|
||||
.OrderBy(x => x.Expiry)
|
||||
.Where(contract => contract.Right == OptionRight.Call && chain.Underlying.Price > contract.Strike - 10)
|
||||
.OrderBy(x => x.Strike)
|
||||
.First();
|
||||
|
||||
var optionPrice = Securities[atmContract.Symbol].AskPrice;
|
||||
var underlyingPrice = Securities["GOOG"].AskPrice;
|
||||
|
||||
// covered call
|
||||
var legs = new List<Leg> { Leg.Create(atmContract.Symbol, -1), Leg.Create(atmContract.Symbol.Underlying, 100) };
|
||||
|
||||
var comboPrice = underlyingPrice - optionPrice;
|
||||
if(comboPrice < 734m)
|
||||
{
|
||||
// just to make sure the price makes sense
|
||||
throw new Exception($"Unexpected combo price {comboPrice}");
|
||||
}
|
||||
// place order slightly bellow price
|
||||
ComboLimitOrder(legs, 6, comboPrice - 0.5m);
|
||||
|
||||
_submittionTime = Time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Debug(orderEvent.ToString());
|
||||
if (orderEvent.Status.IsFill() && (Time - _submittionTime) < TimeSpan.FromMinutes(10))
|
||||
{
|
||||
// we want to make sure we fill because the price moved and hit our limit price
|
||||
throw new Exception($"Unexpected fill time {Time} submittion time {_submittionTime}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 465320;
|
||||
|
||||
/// </summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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", "$8000.00"},
|
||||
{"Lowest Capacity Asset", "GOOCV W78ZFMEBBB2E|GOOCV VP83T1ZUHROL"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Return Over Maximum Drawdown", "0"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"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", "addfbee330e5b80a186acf3c2d776982"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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 System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Daily regression algorithm trading ADAUSDT binance futures long and short asserting the behavior
|
||||
/// </summary>
|
||||
public class CryptoFutureDailyMarginInterestRegressionAlgorithm : CryptoFutureHourlyMarginInterestRegressionAlgorithm
|
||||
{
|
||||
/// <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()
|
||||
{
|
||||
Initialize(Resolution.Daily);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 8;
|
||||
|
||||
/// <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 Trades", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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.15"},
|
||||
{"Estimated Strategy Capacity", "$3400000000.00"},
|
||||
{"Lowest Capacity Asset", "ADAUSDT 18R"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "1287.681"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"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", "2000bf26738e407192574b27086338a6"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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 QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Brokerages;
|
||||
using QuantConnect.Data.Market;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Securities.CryptoFuture;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Daily regression algorithm trading ADAUSDT binance futures long and short asserting the behavior
|
||||
/// </summary>
|
||||
public class CryptoFutureHourlyMarginInterestRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Dictionary<Symbol, int> _interestPerSymbol = new();
|
||||
private decimal _amountAfterTrade;
|
||||
|
||||
protected CryptoFuture AdaUsdt;
|
||||
|
||||
/// <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()
|
||||
{
|
||||
Initialize(Resolution.Hour);
|
||||
}
|
||||
|
||||
protected virtual void Initialize(Resolution resolution)
|
||||
{
|
||||
SetStartDate(2022, 12, 12);
|
||||
SetEndDate(2022, 12, 13);
|
||||
|
||||
SetTimeZone(NodaTime.DateTimeZone.Utc);
|
||||
SetBrokerageModel(BrokerageName.BinanceCoinFutures, AccountType.Margin);
|
||||
|
||||
AdaUsdt = AddCryptoFuture("ADAUSDT", resolution);
|
||||
|
||||
// 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 data)
|
||||
{
|
||||
var interestRates = data.Get<MarginInterestRate>();
|
||||
foreach (var interestRate in interestRates)
|
||||
{
|
||||
_interestPerSymbol.TryGetValue(interestRate.Key, out var count);
|
||||
_interestPerSymbol[interestRate.Key] = ++count;
|
||||
|
||||
var cachedInterestRate = Securities[interestRate.Key].Cache.GetData<MarginInterestRate>();
|
||||
if (cachedInterestRate != interestRate.Value)
|
||||
{
|
||||
throw new Exception($"Unexpected cached margin interest rate for {interestRate.Key}!");
|
||||
}
|
||||
}
|
||||
|
||||
if(interestRates.Count != data.MarginInterestRates.Count)
|
||||
{
|
||||
throw new Exception($"Unexpected cached margin interest rate data!");
|
||||
}
|
||||
|
||||
if (Portfolio.Invested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Buy(AdaUsdt.Symbol, 1000);
|
||||
|
||||
_amountAfterTrade = Portfolio.CashBook["USDT"].Amount;
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_interestPerSymbol.TryGetValue(AdaUsdt.Symbol, out var count) || count != 1)
|
||||
{
|
||||
throw new Exception($"Unexpected interest rate count {count}");
|
||||
}
|
||||
|
||||
// negative because we are long. Rate * Value * Application Count
|
||||
var expectedFundingRateDifference = - (0.0001m * AdaUsdt.Holdings.HoldingsValue * 3);
|
||||
var finalCash = Portfolio.CashBook["USDT"].Amount;
|
||||
if (Math.Abs(finalCash - (_amountAfterTrade + expectedFundingRateDifference)) > Math.Abs(expectedFundingRateDifference * 0.05m))
|
||||
{
|
||||
throw new Exception($"Unexpected interest rate count {Portfolio.CashBook["USDT"].Amount}");
|
||||
}
|
||||
}
|
||||
|
||||
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 Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 50;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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.15"},
|
||||
{"Estimated Strategy Capacity", "$330000000.00"},
|
||||
{"Lowest Capacity Asset", "ADAUSDT 18R"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"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", "bc23ede7bb4af4d941723ed225768fcb"}
|
||||
};
|
||||
}
|
||||
}
|
||||
170
Algorithm.CSharp/CustomDataTypeHistoryAlgorithm.cs
Normal file
170
Algorithm.CSharp/CustomDataTypeHistoryAlgorithm.cs
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm asserting that
|
||||
/// </summary>
|
||||
public class CustomDataTypeHistoryAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _symbol;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2017, 8, 20);
|
||||
SetEndDate(2017, 8, 20);
|
||||
|
||||
_symbol = AddData<CustomDataType>("CustomDataType", Resolution.Hour).Symbol;
|
||||
|
||||
var history = History<CustomDataType>(_symbol, 48, Resolution.Hour).ToList();
|
||||
|
||||
Log($"History count: {history.Count}");
|
||||
|
||||
if (history.Count == 0)
|
||||
{
|
||||
throw new Exception("History request returned no data");
|
||||
}
|
||||
|
||||
var history2 = History<CustomDataType>(new[] { _symbol }, 48, Resolution.Hour).ToList();
|
||||
|
||||
if (history2.Count != history.Count)
|
||||
{
|
||||
throw new Exception("History requests returned different data");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class CustomDataType : DynamicData
|
||||
{
|
||||
public decimal Open;
|
||||
public decimal High;
|
||||
public decimal Low;
|
||||
public decimal Close;
|
||||
|
||||
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
|
||||
{
|
||||
var source = "https://www.dl.dropboxusercontent.com/s/d83xvd7mm9fzpk0/path_to_my_csv_data.csv?dl=0";
|
||||
return new SubscriptionDataSource(source, SubscriptionTransportMedium.RemoteFile);
|
||||
}
|
||||
|
||||
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(line.Trim()))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var csv = line.Split(",");
|
||||
var data = new CustomDataType()
|
||||
{
|
||||
Symbol = config.Symbol,
|
||||
Time = DateTime.ParseExact(csv[0], DateFormat.DB, CultureInfo.InvariantCulture).AddHours(20),
|
||||
Value = csv[4].ToDecimal(),
|
||||
Open = csv[1].ToDecimal(),
|
||||
High = csv[2].ToDecimal(),
|
||||
Low = csv[3].ToDecimal(),
|
||||
Close = csv[4].ToDecimal()
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 Language[] Languages { get; } = { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 28;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 54;
|
||||
|
||||
/// <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 Trades", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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", ""},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Return Over Maximum Drawdown", "0"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"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", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
175
Algorithm.CSharp/CustomMarginInterestRateModelAlgorithm.cs
Normal file
175
Algorithm.CSharp/CustomMarginInterestRateModelAlgorithm.cs
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 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.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using System;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Demonstration of using custom margin interest rate model in backtesting.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="custom margin interest rate models" />
|
||||
public class CustomMarginInterestRateModelAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _spy;
|
||||
|
||||
private decimal _cashAfterOrder;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 01);
|
||||
SetEndDate(2013, 10, 31);
|
||||
|
||||
var security = AddEquity("SPY", Resolution.Hour);
|
||||
_spy = security.Symbol;
|
||||
|
||||
// set the margin interest rate model
|
||||
security.SetMarginInterestRateModel(new CustomMarginInterestRateModel());
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings(_spy, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
if (orderEvent.Status == OrderStatus.Filled)
|
||||
{
|
||||
_cashAfterOrder = Portfolio.Cash;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
var security = Securities[_spy];
|
||||
var marginInterestRateModel = security.MarginInterestRateModel as CustomMarginInterestRateModel;
|
||||
|
||||
if (marginInterestRateModel == null)
|
||||
{
|
||||
throw new Exception("CustomMarginInterestRateModel was not set");
|
||||
}
|
||||
|
||||
if (marginInterestRateModel.CallCount == 0)
|
||||
{
|
||||
throw new Exception("CustomMarginInterestRateModel was not called");
|
||||
}
|
||||
|
||||
var expectedCash = _cashAfterOrder * (decimal)Math.Pow(1 + (double)marginInterestRateModel.InterestRate, marginInterestRateModel.CallCount);
|
||||
|
||||
// add a tolerance since using Math.Pow(double, double) given the lack of a decimal overload
|
||||
if (Math.Abs(Portfolio.Cash - expectedCash) > 1e-10m)
|
||||
{
|
||||
throw new Exception($"Expected cash {expectedCash} but got {Portfolio.Cash}");
|
||||
}
|
||||
}
|
||||
|
||||
public class CustomMarginInterestRateModel : IMarginInterestRateModel
|
||||
{
|
||||
public decimal InterestRate { get; } = 0.01m;
|
||||
|
||||
public int CallCount { get; private set; }
|
||||
|
||||
public void ApplyMarginInterestRate(MarginInterestRateParameters parameters)
|
||||
{
|
||||
var security = parameters.Security;
|
||||
var positionValue = security.Holdings.GetQuantityValue(security.Holdings.Quantity);
|
||||
|
||||
if (positionValue.Amount > 0)
|
||||
{
|
||||
positionValue.Cash.AddAmount(InterestRate * positionValue.Cash.Amount);
|
||||
CallCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 Language[] Languages { get; } = { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 330;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "93.409%"},
|
||||
{"Drawdown", "2.400%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "5.699%"},
|
||||
{"Sharpe Ratio", "4.771"},
|
||||
{"Probabilistic Sharpe Ratio", "85.653%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.145"},
|
||||
{"Beta", "0.998"},
|
||||
{"Annual Standard Deviation", "0.108"},
|
||||
{"Annual Variance", "0.012"},
|
||||
{"Information Ratio", "28.436"},
|
||||
{"Tracking Error", "0.005"},
|
||||
{"Treynor Ratio", "0.514"},
|
||||
{"Total Fees", "$3.43"},
|
||||
{"Estimated Strategy Capacity", "$150000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Fitness Score", "0.045"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "14.855"},
|
||||
{"Return Over Maximum Drawdown", "63.683"},
|
||||
{"Portfolio Turnover", "0.045"},
|
||||
{"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", "701d5dfbbd5ffd8b60a76d61f15bae17"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -96,12 +96,12 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 29609;
|
||||
public long DataPoints => 29579;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 42688;
|
||||
public int AlgorithmHistoryDataPoints => 42660;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
|
||||
121
Algorithm.CSharp/DefaultFutureChainRegressionAlgorithm.cs
Normal file
121
Algorithm.CSharp/DefaultFutureChainRegressionAlgorithm.cs
Normal file
@@ -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 System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm reproducing GH issue #6829 where the default future chain selection would let some contracts through
|
||||
/// </summary>
|
||||
public class DefaultFutureChainRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize your algorithm and add desired assets.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 08);
|
||||
SetEndDate(2013, 12, 10);
|
||||
|
||||
AddFuture(Futures.Metals.Gold);
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
foreach (var addedSecurity in changes.AddedSecurities.Where(added => !added.Symbol.IsCanonical()))
|
||||
{
|
||||
// With no future chain filters specified, it should return no contracts in security changes event.
|
||||
// The canonical continuous future will get mapped and emit symbol changed events, while it's current mapped security is an internal feed
|
||||
throw new Exception($"We expect no non canonical security to be added: {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 Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 473924;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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", "-5.145"},
|
||||
{"Tracking Error", "0.083"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"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", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
123
Algorithm.CSharp/DefaultOptionPriceModelRegressionAlgorithm.cs
Normal file
123
Algorithm.CSharp/DefaultOptionPriceModelRegressionAlgorithm.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm which tests the default option price model
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="options" />
|
||||
public class DefaultOptionPriceModelRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2021, 1, 4);
|
||||
SetEndDate(2021, 1, 4);
|
||||
SetCash(100000);
|
||||
|
||||
AddIndex("SPX");
|
||||
AddIndexOption("SPX");
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (slice.OptionChains.Any(kvp => kvp.Value.Any(
|
||||
contract => contract.Greeks.Delta == 0 &&
|
||||
contract.Greeks.Gamma == 0 &&
|
||||
contract.Greeks.Theta == 0 &&
|
||||
contract.Greeks.Vega == 0 &&
|
||||
contract.Greeks.Rho == 0)))
|
||||
{
|
||||
throw new Exception("All Greeks are zero - Pricing Model is 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 bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 7488;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe 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", ""},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Return Over Maximum Drawdown", "0"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"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", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 1450;
|
||||
public override long DataPoints => 1850;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 398985;
|
||||
public virtual long DataPoints => 517960;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -130,7 +130,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "5.652"},
|
||||
{"Return Over Maximum Drawdown", "5.667"},
|
||||
{"Portfolio Turnover", "0.023"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 17600;
|
||||
public long DataPoints => 16919;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -137,32 +137,32 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-26.40%"},
|
||||
{"Compounding Annual Return", "-99.821%"},
|
||||
{"Drawdown", "45.600%"},
|
||||
{"Average Loss", "-26.02%"},
|
||||
{"Compounding Annual Return", "-99.802%"},
|
||||
{"Drawdown", "46.200%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-26.400%"},
|
||||
{"Sharpe Ratio", "-0.602"},
|
||||
{"Probabilistic Sharpe Ratio", "19.127%"},
|
||||
{"Net Profit", "-26.015%"},
|
||||
{"Sharpe Ratio", "-0.603"},
|
||||
{"Probabilistic Sharpe Ratio", "19.498%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.559"},
|
||||
{"Beta", "-0.807"},
|
||||
{"Annual Standard Deviation", "1.582"},
|
||||
{"Annual Variance", "2.502"},
|
||||
{"Information Ratio", "-0.905"},
|
||||
{"Tracking Error", "1.593"},
|
||||
{"Treynor Ratio", "1.181"},
|
||||
{"Alpha", "-0.536"},
|
||||
{"Beta", "-0.847"},
|
||||
{"Annual Standard Deviation", "1.575"},
|
||||
{"Annual Variance", "2.481"},
|
||||
{"Information Ratio", "-0.907"},
|
||||
{"Tracking Error", "1.587"},
|
||||
{"Treynor Ratio", "1.122"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$1000000.00"},
|
||||
{"Lowest Capacity Asset", "SPX 31KC0UJFONTBI|SPX 31"},
|
||||
{"Fitness Score", "0.005"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-0.249"},
|
||||
{"Return Over Maximum Drawdown", "-2.699"},
|
||||
{"Portfolio Turnover", "0.016"},
|
||||
{"Sortino Ratio", "-0.251"},
|
||||
{"Return Over Maximum Drawdown", "-2.717"},
|
||||
{"Portfolio Turnover", "0.017"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
@@ -176,7 +176,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "721fddfd1327f7adcc2883d1412708c9"}
|
||||
{"OrderListHash", "4e95ccd00ceefd18628c304fba443199"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 13223;
|
||||
public override long DataPoints => 13676;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
@@ -56,13 +56,13 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Tracking Error", "0.107"},
|
||||
{"Treynor Ratio", "1.338"},
|
||||
{"Total Fees", "$19.76"},
|
||||
{"Estimated Strategy Capacity", "$2300000.00"},
|
||||
{"Estimated Strategy Capacity", "$2400000.00"},
|
||||
{"Lowest Capacity Asset", "DC V5E8PHPRCHJ8|DC V5E8P9SH0U0X"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-0.126"},
|
||||
{"Return Over Maximum Drawdown", "-0.995"},
|
||||
{"Return Over Maximum Drawdown", "-0.997"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
@@ -77,7 +77,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "2152bd1d4f1770068595a4c3bc8585ee"}
|
||||
{"OrderListHash", "19ecd0218cb70c5d7fefcb5741a7d82b"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>0
|
||||
public virtual long DataPoints => 5117455;
|
||||
public virtual long DataPoints => 4900229;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -160,7 +160,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "d10e8665214344369e3e8f1c49dbdd67"}
|
||||
{"OrderListHash", "b3674f70c87c91669dc25170e43e6af8"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
162
Algorithm.CSharp/DividendRegressionAlgorithm.cs
Normal file
162
Algorithm.CSharp/DividendRegressionAlgorithm.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* 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.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Demonstration of payments for cash dividends in backtesting. When data normalization mode is set
|
||||
/// to "Raw" the dividends are paid as cash directly into your portfolio.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="data event handlers" />
|
||||
/// <meta name="tag" content="dividend event" />
|
||||
public class DividendRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private decimal _sumOfDividends;
|
||||
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(1998, 01, 01); //Set Start Date
|
||||
SetEndDate(2006, 01, 01); //Set End Date
|
||||
SetCash(100000); //Set Strategy Cash
|
||||
// Find more symbols here: http://quantconnect.com/data
|
||||
_symbol = AddEquity("SPY", Resolution.Daily,
|
||||
dataNormalizationMode: DataNormalizationMode.Raw).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">TradeBars IDictionary object with your stock data</param>
|
||||
public void OnData(TradeBars data)
|
||||
{
|
||||
if (Portfolio.Invested) return;
|
||||
SetHoldings(_symbol, .5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the data event.
|
||||
/// </summary>
|
||||
/// <param name="data">Data.</param>
|
||||
public void OnData(Dividends data) // update this to Dividends dictionary
|
||||
{
|
||||
var dividend = data[_symbol];
|
||||
var holdings = Portfolio[_symbol];
|
||||
Debug($"{dividend.Time.ToStringInvariant("o")} >> DIVIDEND >> {dividend.Symbol} - " +
|
||||
$"{dividend.Distribution.ToStringInvariant("C")} - {Portfolio.Cash} - " +
|
||||
$"{holdings.Price.ToStringInvariant("C")}"
|
||||
);
|
||||
_sumOfDividends += dividend.Distribution * holdings.Quantity;
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
// The expected value refers to sum of dividend payments
|
||||
if (Portfolio.TotalProfit != _sumOfDividends)
|
||||
{
|
||||
throw new Exception($"Total Profit: Expected {_sumOfDividends}. Actual {Portfolio.TotalProfit}");
|
||||
}
|
||||
|
||||
var expectNetProfit = _sumOfDividends - Portfolio.TotalFees;
|
||||
if (Portfolio.TotalNetProfit != expectNetProfit)
|
||||
{
|
||||
throw new Exception($"Total Net Profit: Expected {expectNetProfit}. Actual {Portfolio.TotalNetProfit}");
|
||||
}
|
||||
|
||||
if (Portfolio[_symbol].TotalDividends != _sumOfDividends)
|
||||
{
|
||||
throw new Exception($"{_symbol} Total Dividends: Expected {_sumOfDividends}. Actual {Portfolio[_symbol].TotalDividends}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 16077;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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()
|
||||
{
|
||||
{ "Total Trades", "1" },
|
||||
{ "Average Win", "0%" },
|
||||
{ "Average Loss", "0%" },
|
||||
{ "Compounding Annual Return", "2.354%" },
|
||||
{ "Drawdown", "28.200%" },
|
||||
{ "Expectancy", "0" },
|
||||
{ "Net Profit", "20.462%" },
|
||||
{ "Sharpe Ratio", "0.238" },
|
||||
{ "Probabilistic Sharpe Ratio", "0.462%" },
|
||||
{ "Loss Rate", "0%" },
|
||||
{ "Win Rate", "0%" },
|
||||
{ "Profit-Loss Ratio", "0" },
|
||||
{ "Alpha", "-0.004" },
|
||||
{ "Beta", "0.521" },
|
||||
{ "Annual Standard Deviation", "0.083" },
|
||||
{ "Annual Variance", "0.007" },
|
||||
{ "Information Ratio", "-0.328" },
|
||||
{ "Tracking Error", "0.076" },
|
||||
{ "Treynor Ratio", "0.038" },
|
||||
{ "Total Fees", "$2.56" },
|
||||
{ "Estimated Strategy Capacity", "$24000000.00" },
|
||||
{ "Lowest Capacity Asset", "SPY R735QTJ8XC9X" },
|
||||
{ "Fitness Score", "0" },
|
||||
{ "Kelly Criterion Estimate", "0" },
|
||||
{ "Kelly Criterion Probability Value", "0" },
|
||||
{ "Sortino Ratio", "0.355" },
|
||||
{ "Return Over Maximum Drawdown", "0.083" },
|
||||
{ "Portfolio Turnover", "0" },
|
||||
{ "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", "e60d1af5917a9a4d7b41197ce665b296" }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 4324;
|
||||
public long DataPoints => 4319;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -168,7 +168,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Kelly Criterion Estimate", "-24.978"},
|
||||
{"Kelly Criterion Probability Value", "0.773"},
|
||||
{"Sortino Ratio", "-0.966"},
|
||||
{"Return Over Maximum Drawdown", "-5.15"},
|
||||
{"Return Over Maximum Drawdown", "-5.151"},
|
||||
{"Portfolio Turnover", "5.36"},
|
||||
{"Total Insights Generated", "10"},
|
||||
{"Total Insights Closed", "8"},
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* 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>
|
||||
/// Regression algorithm asserting that European options cannot be exercised before expiry
|
||||
/// </summary>
|
||||
public class EuropeanOptionsCannotBeExercisedBeforeExpiryRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Option _option;
|
||||
|
||||
private OptionContract _contract;
|
||||
|
||||
private bool _marketOrderDone;
|
||||
|
||||
private bool _exerciseBeforeExpiryDone;
|
||||
|
||||
private bool _exerciseOnExpiryDone;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2021, 1, 4);
|
||||
SetEndDate(2021, 2, 1);
|
||||
SetCash(200000);
|
||||
|
||||
var index = AddIndex("SPX", Resolution.Hour, fillDataForward: true);
|
||||
var indexOption = AddIndexOption(index.Symbol, Resolution.Hour, fillDataForward: true);
|
||||
indexOption.SetFilter(filterFunc => filterFunc);
|
||||
|
||||
_option = indexOption;
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if ((_exerciseBeforeExpiryDone && _exerciseOnExpiryDone) || !_option.Exchange.ExchangeOpen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_contract == null)
|
||||
{
|
||||
OptionChain contracts;
|
||||
if (!slice.OptionChains.TryGetValue(_option.Symbol, out contracts) || !contracts.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_contract = contracts.First();
|
||||
}
|
||||
|
||||
var expiry = _contract.Expiry.ConvertToUtc(_option.Exchange.TimeZone).Date;
|
||||
|
||||
if (!_exerciseBeforeExpiryDone && UtcTime.Date < expiry)
|
||||
{
|
||||
if (!_marketOrderDone)
|
||||
{
|
||||
if (MarketOrder(_contract.Symbol, 1).Status != OrderStatus.Filled)
|
||||
{
|
||||
throw new Exception("Expected market order to fill immediately");
|
||||
}
|
||||
|
||||
_marketOrderDone = true;
|
||||
}
|
||||
|
||||
if (ExerciseOption(_contract.Symbol, 1).Status == OrderStatus.Filled)
|
||||
{
|
||||
throw new Exception($"Expected European option to not be exercisable before its expiration date. " +
|
||||
$"Time: {UtcTime}. Expiry: {_contract.Expiry.ConvertToUtc(_option.Exchange.TimeZone)}");
|
||||
}
|
||||
|
||||
_exerciseBeforeExpiryDone = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_exerciseOnExpiryDone && UtcTime.Date == expiry)
|
||||
{
|
||||
if (ExerciseOption(_contract.Symbol, 1).Status != OrderStatus.Filled)
|
||||
{
|
||||
throw new Exception($"Expected European option to be exercisable on its expiration date. " +
|
||||
$"Time: {UtcTime}. Expiry: {_contract.Expiry.ConvertToUtc(_option.Exchange.TimeZone)}");
|
||||
}
|
||||
|
||||
_exerciseOnExpiryDone = true;
|
||||
|
||||
// We already tested everything, so we can stop the algorithm
|
||||
Quit();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_exerciseBeforeExpiryDone || !_exerciseOnExpiryDone)
|
||||
{
|
||||
throw new Exception("Expected to try to exercise option before and on expiry");
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all time slices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 1830;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <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 Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-4.10%"},
|
||||
{"Compounding Annual Return", "25.461%"},
|
||||
{"Drawdown", "1.900%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "0.712%"},
|
||||
{"Sharpe Ratio", "5.904"},
|
||||
{"Probabilistic Sharpe Ratio", "90.591%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.967"},
|
||||
{"Beta", "-0.359"},
|
||||
{"Annual Standard Deviation", "0.123"},
|
||||
{"Annual Variance", "0.015"},
|
||||
{"Information Ratio", "0.289"},
|
||||
{"Tracking Error", "0.176"},
|
||||
{"Treynor Ratio", "-2.02"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$1700000.00"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3HB5O6M|SPX 31"},
|
||||
{"Fitness Score", "0.004"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "20.506"},
|
||||
{"Portfolio Turnover", "0.004"},
|
||||
{"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", "3252b25ba9ccfa6d0aa48bc2e0a8501e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -112,34 +112,34 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "4"},
|
||||
{"Total Trades", "5"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "7.848%"},
|
||||
{"Compounding Annual Return", "10.601%"},
|
||||
{"Drawdown", "0.100%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0.100%"},
|
||||
{"Sharpe Ratio", "8.342"},
|
||||
{"Probabilistic Sharpe Ratio", "83.750%"},
|
||||
{"Net Profit", "0.134%"},
|
||||
{"Sharpe Ratio", "9.38"},
|
||||
{"Probabilistic Sharpe Ratio", "89.204%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0.033"},
|
||||
{"Annual Standard Deviation", "0.008"},
|
||||
{"Alpha", "0.011"},
|
||||
{"Beta", "0.039"},
|
||||
{"Annual Standard Deviation", "0.009"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-8.908"},
|
||||
{"Tracking Error", "0.215"},
|
||||
{"Treynor Ratio", "1.992"},
|
||||
{"Total Fees", "$4.00"},
|
||||
{"Estimated Strategy Capacity", "$6000000.00"},
|
||||
{"Information Ratio", "-8.86"},
|
||||
{"Tracking Error", "0.214"},
|
||||
{"Treynor Ratio", "2.254"},
|
||||
{"Total Fees", "$5.00"},
|
||||
{"Estimated Strategy Capacity", "$14000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Fitness Score", "0.011"},
|
||||
{"Fitness Score", "0.014"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "38.493"},
|
||||
{"Return Over Maximum Drawdown", "236.57"},
|
||||
{"Portfolio Turnover", "0.011"},
|
||||
{"Sortino Ratio", "51.994"},
|
||||
{"Return Over Maximum Drawdown", "319.54"},
|
||||
{"Portfolio Turnover", "0.014"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
@@ -153,7 +153,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "65e705bf0e78139c376903d4ff241afc"}
|
||||
{"OrderListHash", "36ead96040ec7274bf3646e99b1206fb"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 7206;
|
||||
public long DataPoints => 7201;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_afterMarketOpenQueue.Any() || !_beforeMarketCloseQueue.Any())
|
||||
if (_afterMarketOpenQueue.Any() || _beforeMarketCloseQueue.Any())
|
||||
{
|
||||
throw new Exception($"_afterMarketOpenQueue and _beforeMarketCloseQueue should be empty");
|
||||
}
|
||||
@@ -100,7 +100,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 7;
|
||||
public virtual long DataPoints => 27067;
|
||||
|
||||
/// </summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 7;
|
||||
public override long DataPoints => 82827;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 29802;
|
||||
public virtual long DataPoints => 32062;
|
||||
|
||||
/// </summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 95102;
|
||||
public override long DataPoints => 103812;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
|
||||
@@ -165,7 +165,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "6ae724ba0dbcbd1ca49dcfcdf94e0319"}
|
||||
{"OrderListHash", "2c6f94edc9eb94b4a52998e8fac83f63"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "02b16807a77a858047996f15597ff145"}
|
||||
{"OrderListHash", "f49b2e88c45554d43b6a36382aa946af"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "c1c4c793696f75c528527334563ae8df"}
|
||||
{"OrderListHash", "3169abd2fe120400ab2da9daa6a51bc7"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "29bb2f59fa2ee3dab8ed2aecf6544189"}
|
||||
{"OrderListHash", "61fc923519bea2059d8094378386ea42"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 24376;
|
||||
public long DataPoints => 59677;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -254,7 +254,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "621491b86f9d0e1a6abf4a882f73a38b"}
|
||||
{"OrderListHash", "d73af39b216690b0877d01ad4e4a654c"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "05dcd0b935d8206ca42ffc325fec4302"}
|
||||
{"OrderListHash", "bea65dc6fb976b0fac2a239310734d91"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "bf5fe7396dd65efe92326817647d2350"}
|
||||
{"OrderListHash", "abe6d3a5ce8cf541d4791cd606f8fb38"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "5c9cb56b3d08ac28a51d146ef6be7669"}
|
||||
{"OrderListHash", "c22c968523508c5d3dc724e7a8ead3e9"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "cdf689416d6e6e04739cbaa7fb2f8b80"}
|
||||
{"OrderListHash", "74ac36f88002d539a07b4270fb000d3a"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "5895d7c6447d4b1487e4705bc32b50a6"}
|
||||
{"OrderListHash", "dcb6f577ec6dd3a732d8fd31279cb703"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,8 +117,8 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Fitness Score", "0.007"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-10.333"},
|
||||
{"Return Over Maximum Drawdown", "-53.15"},
|
||||
{"Sortino Ratio", "-10.433"},
|
||||
{"Return Over Maximum Drawdown", "-53.661"},
|
||||
{"Portfolio Turnover", "0.665"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
|
||||
@@ -231,7 +231,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "271484857fd3dbf4e4a332485bcfa773"}
|
||||
{"OrderListHash", "e36d25e5bf671a594ec4178c5cb2877d"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 136444;
|
||||
public long DataPoints => 266369;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -129,7 +129,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 1187;
|
||||
public long DataPoints => 1602;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 1187;
|
||||
public long DataPoints => 1602;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 1246;
|
||||
public long DataPoints => 1661;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
69
Algorithm.CSharp/IndexOptionBearCallSpreadAlgorithm.cs
Normal file
69
Algorithm.CSharp/IndexOptionBearCallSpreadAlgorithm.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities.Option;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
public class IndexOptionBearCallSpreadAlgorithm : QCAlgorithm
|
||||
{
|
||||
private Symbol _vixw, _spy;
|
||||
private IEnumerable<OrderTicket> _tickets = Enumerable.Empty<OrderTicket>();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2020, 1, 1);
|
||||
SetEndDate(2021, 1, 1);
|
||||
SetCash(100000);
|
||||
|
||||
_spy = AddEquity("SPY", Resolution.Minute).Symbol;
|
||||
|
||||
var index = AddIndex("VIX", Resolution.Minute).Symbol;
|
||||
var option = AddIndexOption(index, "VIXW", Resolution.Minute);
|
||||
option.SetFilter((x) => x.Strikes(-5, 5).Expiration(15, 45));
|
||||
_vixw = option.Symbol;
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio[_spy].Invested)
|
||||
{
|
||||
MarketOrder(_spy, 100);
|
||||
}
|
||||
|
||||
// Return if hedge position presents
|
||||
if (_tickets.Any(x => Portfolio[x.Symbol].Invested)) return;
|
||||
|
||||
// Get the OptionChain
|
||||
if (!slice.OptionChains.TryGetValue(_vixw, out var chain)) return;
|
||||
|
||||
// Get the nearest expiry date of the contracts
|
||||
var expiry = chain.Min(x => x.Expiry);
|
||||
|
||||
// Select the call Option contracts with the nearest expiry and sort by strike price
|
||||
var calls = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Call)
|
||||
.OrderBy(x => x.Strike).ToArray();
|
||||
if (calls.Length < 2) return;
|
||||
|
||||
// Buy the bear call spread
|
||||
var bearCallSpread = OptionStrategies.BearCallSpread(_vixw, calls[0].Strike, calls[^1].Strike, expiry);
|
||||
_tickets = Buy(bearCallSpread, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
63
Algorithm.CSharp/IndexOptionBearPutSpreadAlgorithm.cs
Normal file
63
Algorithm.CSharp/IndexOptionBearPutSpreadAlgorithm.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities.Option;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
public class IndexOptionBearPutSpreadAlgorithm : QCAlgorithm
|
||||
{
|
||||
private Symbol _spxw;
|
||||
private IEnumerable<OrderTicket> _tickets = Enumerable.Empty<OrderTicket>();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2022, 1, 1);
|
||||
SetEndDate(2022, 7, 1);
|
||||
SetCash(100000);
|
||||
|
||||
var index = AddIndex("SPX", Resolution.Minute).Symbol;
|
||||
var option = AddIndexOption(index, "SPXW", Resolution.Minute);
|
||||
option.SetFilter((x) => x.WeeklysOnly().Strikes(5, 10).Expiration(0, 0));
|
||||
|
||||
_spxw = option.Symbol;
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
// Return if open position exists
|
||||
if (_tickets.Any(x => Portfolio[x.Symbol].Invested)) return;
|
||||
|
||||
// Get the OptionChain
|
||||
if (!slice.OptionChains.TryGetValue(_spxw, out var chain)) return;
|
||||
|
||||
// Get the nearest expiry date of the contracts
|
||||
var expiry = chain.Min(x => x.Expiry);
|
||||
|
||||
// Select the put Option contracts with the nearest expiry and sort by strike price
|
||||
var puts = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Put)
|
||||
.OrderBy(x => x.Strike).ToArray();
|
||||
if (puts.Length < 2) return;
|
||||
|
||||
// Buy the bear put spread
|
||||
var optionStrategy = OptionStrategies.BearPutSpread(_spxw, puts[^1].Strike, puts[0].Strike, expiry);
|
||||
_tickets = Buy(optionStrategy, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
69
Algorithm.CSharp/IndexOptionBullCallSpreadAlgorithm.cs
Normal file
69
Algorithm.CSharp/IndexOptionBullCallSpreadAlgorithm.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities.Option;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
public class IndexOptionBullCallSpreadAlgorithm : QCAlgorithm
|
||||
{
|
||||
private Symbol _spxw, _spy;
|
||||
private IEnumerable<OrderTicket> _tickets = Enumerable.Empty<OrderTicket>();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2020, 1, 1);
|
||||
SetEndDate(2021, 1, 1);
|
||||
SetCash(100000);
|
||||
|
||||
_spy = AddEquity("SPY", Resolution.Minute).Symbol;
|
||||
|
||||
var index = AddIndex("SPX", Resolution.Minute).Symbol;
|
||||
var option = AddIndexOption(index, "SPXW", Resolution.Minute);
|
||||
option.SetFilter((x) => x.WeeklysOnly().Strikes(-5, 5).Expiration(40, 60));
|
||||
_spxw = option.Symbol;
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio[_spy].Invested)
|
||||
{
|
||||
MarketOrder(_spy, 100);
|
||||
}
|
||||
|
||||
// Return if hedge position presents
|
||||
if (_tickets.Any(x => Portfolio[x.Symbol].Invested)) return;
|
||||
|
||||
// Get the OptionChain
|
||||
if (!slice.OptionChains.TryGetValue(_spxw, out var chain)) return;
|
||||
|
||||
// Get the nearest expiry date of the contracts
|
||||
var expiry = chain.Min(x => x.Expiry);
|
||||
|
||||
// Select the call Option contracts with the nearest expiry and sort by strike price
|
||||
var calls = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Call)
|
||||
.OrderBy(x => x.Strike).ToArray();
|
||||
if (calls.Length < 2) return;
|
||||
|
||||
// Buy the bull call spread
|
||||
var bullCallSpread = OptionStrategies.BullCallSpread(_spxw, calls[0].Strike, calls[^1].Strike, expiry);
|
||||
_tickets = Buy(bullCallSpread, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
63
Algorithm.CSharp/IndexOptionBullPutSpreadAlgorithm.cs
Normal file
63
Algorithm.CSharp/IndexOptionBullPutSpreadAlgorithm.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities.Option;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
public class IndexOptionBullPutSpreadAlgorithm : QCAlgorithm
|
||||
{
|
||||
private Symbol _spxw;
|
||||
private IEnumerable<OrderTicket> _tickets = Enumerable.Empty<OrderTicket>();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2019, 1, 1);
|
||||
SetEndDate(2020, 1, 1);
|
||||
SetCash(100000);
|
||||
|
||||
var index = AddIndex("SPX", Resolution.Minute).Symbol;
|
||||
var option = AddIndexOption(index, "SPXW", Resolution.Minute);
|
||||
option.SetFilter((x) => x.WeeklysOnly().Strikes(-10, -5).Expiration(0, 0));
|
||||
|
||||
_spxw = option.Symbol;
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
// Return if open position exists
|
||||
if (_tickets.Any(x => Portfolio[x.Symbol].Invested)) return;
|
||||
|
||||
// Get the OptionChain
|
||||
if (!slice.OptionChains.TryGetValue(_spxw, out var chain)) return;
|
||||
|
||||
// Get the nearest expiry date of the contracts
|
||||
var expiry = chain.Min(x => x.Expiry);
|
||||
|
||||
// Select the put Option contracts with the nearest expiry and sort by strike price
|
||||
var puts = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Put)
|
||||
.OrderBy(x => x.Strike).ToArray();
|
||||
if (puts.Length < 2) return;
|
||||
|
||||
// Buy the bull put spread
|
||||
var bullCallSpread = OptionStrategies.BullPutSpread(_spxw, puts[^1].Strike, puts[0].Strike, expiry);
|
||||
_tickets = Buy(bullCallSpread, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 32708;
|
||||
public long DataPoints => 31858;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -132,32 +132,32 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
{"Total Trades", "4"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.06%"},
|
||||
{"Compounding Annual Return", "-1.552%"},
|
||||
{"Drawdown", "0.100%"},
|
||||
{"Average Loss", "-0.08%"},
|
||||
{"Compounding Annual Return", "-2.251%"},
|
||||
{"Drawdown", "0.200%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-0.110%"},
|
||||
{"Sharpe Ratio", "-3.157"},
|
||||
{"Net Profit", "-0.160%"},
|
||||
{"Sharpe Ratio", "-3.15"},
|
||||
{"Probabilistic Sharpe Ratio", "0.427%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.011"},
|
||||
{"Beta", "-0.004"},
|
||||
{"Annual Standard Deviation", "0.003"},
|
||||
{"Alpha", "-0.016"},
|
||||
{"Beta", "-0.006"},
|
||||
{"Annual Standard Deviation", "0.005"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.405"},
|
||||
{"Tracking Error", "0.138"},
|
||||
{"Treynor Ratio", "2.704"},
|
||||
{"Information Ratio", "-0.44"},
|
||||
{"Tracking Error", "0.139"},
|
||||
{"Treynor Ratio", "2.697"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3HB5O6M|SPX 31"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-4619.237"},
|
||||
{"Return Over Maximum Drawdown", "-14.266"},
|
||||
{"Portfolio Turnover", "0.005"},
|
||||
{"Sortino Ratio", "-3164.357"},
|
||||
{"Return Over Maximum Drawdown", "-14.219"},
|
||||
{"Portfolio Turnover", "0.006"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
@@ -171,7 +171,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "7d15f56731d38768ea81afac627f0657"}
|
||||
{"OrderListHash", "ef50e9cfe22e6ad96ed1c68c81470b01"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
88
Algorithm.CSharp/IndexOptionCallButterflyAlgorithm.cs
Normal file
88
Algorithm.CSharp/IndexOptionCallButterflyAlgorithm.cs
Normal file
@@ -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;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities.Option;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
public class IndexOptionCallButterflyAlgorithm : QCAlgorithm
|
||||
{
|
||||
private Symbol _spxw, _vxz;
|
||||
private decimal _multiplier;
|
||||
private IEnumerable<OrderTicket> _tickets = Enumerable.Empty<OrderTicket>();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2020, 1, 1);
|
||||
SetEndDate(2021, 1, 1);
|
||||
SetCash(1000000);
|
||||
|
||||
_vxz = AddEquity("VXZ", Resolution.Minute).Symbol;
|
||||
|
||||
var index = AddIndex("SPX", Resolution.Minute).Symbol;
|
||||
var option = AddIndexOption(index, "SPXW", Resolution.Minute);
|
||||
option.SetFilter((x) => x.IncludeWeeklys().Strikes(-3, 3).Expiration(15, 45));
|
||||
|
||||
_spxw = option.Symbol;
|
||||
_multiplier = option.SymbolProperties.ContractMultiplier;
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
// The order of magnitude per SPXW order's value is 10000 times of VXZ
|
||||
if (!Portfolio[_vxz].Invested)
|
||||
{
|
||||
MarketOrder(_vxz, 10000);
|
||||
}
|
||||
|
||||
// Return if any opening index option position
|
||||
if (_tickets.Any(x => Portfolio[x.Symbol].Invested)) return;
|
||||
|
||||
// Get the OptionChain
|
||||
if (!slice.OptionChains.TryGetValue(_spxw, out var chain)) return;
|
||||
|
||||
// Get nearest expiry date
|
||||
var expiry = chain.Min(x => x.Expiry);
|
||||
|
||||
// Select the call Option contracts with nearest expiry and sort by strike price
|
||||
var calls = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Call).ToList();
|
||||
if (calls.Count < 3) return;
|
||||
var sortedCallStrikes = calls.Select(x => x.Strike).OrderBy(x => x).ToArray();
|
||||
|
||||
// Select ATM call
|
||||
var atmStrike = calls.MinBy(x => Math.Abs(x.Strike - chain.Underlying.Value)).Strike;
|
||||
|
||||
// Get the strike prices for the ITM & OTM contracts, make sure they're in equidistance
|
||||
var spread = Math.Min(atmStrike - sortedCallStrikes[0], sortedCallStrikes[^1] - atmStrike);
|
||||
var itmStrike = atmStrike - spread;
|
||||
var otmStrike = atmStrike + spread;
|
||||
if (!sortedCallStrikes.Contains(otmStrike) || !sortedCallStrikes.Contains(itmStrike)) return;
|
||||
|
||||
// Buy the call butterfly
|
||||
var callButterfly = OptionStrategies.CallButterfly(_spxw, otmStrike, atmStrike, itmStrike, expiry);
|
||||
var price = callButterfly.UnderlyingLegs.Sum(x => Math.Abs(Securities[x.Symbol].Price * x.Quantity) * _multiplier);
|
||||
if (price > 0)
|
||||
{
|
||||
var quantity = Portfolio.TotalPortfolioValue / price;
|
||||
_tickets = Buy(callButterfly, (int)Math.Floor(quantity), asynchronous: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
91
Algorithm.CSharp/IndexOptionCallCalendarSpreadAlgorithm.cs
Normal file
91
Algorithm.CSharp/IndexOptionCallCalendarSpreadAlgorithm.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
public class IndexOptionCallCalendarSpreadAlgorithm : QCAlgorithm
|
||||
{
|
||||
private Symbol _vixw, _vxz, _spy;
|
||||
private decimal _multiplier;
|
||||
private List<Leg> _legs = new();
|
||||
private DateTime _firstExpiry = DateTime.MaxValue;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2020, 1, 1);
|
||||
SetEndDate(2021, 1, 1);
|
||||
SetCash(50000);
|
||||
|
||||
_vxz = AddEquity("VXZ", Resolution.Minute).Symbol;
|
||||
_spy = AddEquity("SPY", Resolution.Minute).Symbol;
|
||||
|
||||
var index = AddIndex("VIX", Resolution.Minute).Symbol;
|
||||
var option = AddIndexOption(index, "VIXW", Resolution.Minute);
|
||||
option.SetFilter((x) => x.Strikes(-2, 2).Expiration(15, 45));
|
||||
|
||||
_vixw = option.Symbol;
|
||||
_multiplier = option.SymbolProperties.ContractMultiplier;
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
// Liquidate if the shorter term option is about to expire
|
||||
if (_firstExpiry < Time.AddDays(2) && _legs.All(x => slice.ContainsKey(x.Symbol)))
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
// Return if there is any opening position
|
||||
else if (_legs.Any(x => Portfolio[x.Symbol].Invested))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the OptionChain
|
||||
if (!slice.OptionChains.TryGetValue(_vixw, out var chain)) return;
|
||||
|
||||
// Get ATM strike price
|
||||
var strike = chain.MinBy(x => Math.Abs(x.Strike - chain.Underlying.Value)).Strike;
|
||||
|
||||
// Select the ATM call Option contracts and sort by expiration date
|
||||
var calls = chain.Where(x => x.Strike == strike && x.Right == OptionRight.Call)
|
||||
.OrderBy(x => x.Expiry).ToArray();
|
||||
if (calls.Length < 2) return;
|
||||
_firstExpiry = calls[0].Expiry;
|
||||
|
||||
// Create combo order legs
|
||||
_legs = new List<Leg>
|
||||
{
|
||||
Leg.Create(calls[0].Symbol, -1),
|
||||
Leg.Create(calls[^1].Symbol, 1),
|
||||
Leg.Create(_vxz, -100),
|
||||
Leg.Create(_spy, -10)
|
||||
};
|
||||
var quantity = Portfolio.TotalPortfolioValue / _legs.Sum(x =>
|
||||
{
|
||||
var value = Math.Abs(Securities[x.Symbol].Price * x.Quantity);
|
||||
return x.Symbol.ID.SecurityType == SecurityType.IndexOption
|
||||
? value * _multiplier
|
||||
: value;
|
||||
});
|
||||
ComboMarketOrder(_legs, -(int)Math.Floor(quantity), asynchronous: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,7 +180,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 20443;
|
||||
public long DataPoints => 19623;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -194,32 +194,32 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-49.28%"},
|
||||
{"Compounding Annual Return", "301.490%"},
|
||||
{"Drawdown", "2.300%"},
|
||||
{"Average Loss", "-50.48%"},
|
||||
{"Compounding Annual Return", "247.047%"},
|
||||
{"Drawdown", "2.500%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "10.274%"},
|
||||
{"Sharpe Ratio", "5.298"},
|
||||
{"Probabilistic Sharpe Ratio", "88.621%"},
|
||||
{"Net Profit", "9.144%"},
|
||||
{"Sharpe Ratio", "4.94"},
|
||||
{"Probabilistic Sharpe Ratio", "88.394%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "1.836"},
|
||||
{"Beta", "-0.228"},
|
||||
{"Annual Standard Deviation", "0.345"},
|
||||
{"Annual Variance", "0.119"},
|
||||
{"Information Ratio", "4.653"},
|
||||
{"Tracking Error", "0.383"},
|
||||
{"Treynor Ratio", "-8.001"},
|
||||
{"Alpha", "1.53"},
|
||||
{"Beta", "-0.205"},
|
||||
{"Annual Standard Deviation", "0.308"},
|
||||
{"Annual Variance", "0.095"},
|
||||
{"Information Ratio", "4.233"},
|
||||
{"Tracking Error", "0.349"},
|
||||
{"Treynor Ratio", "-7.436"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
|
||||
{"Fitness Score", "0.024"},
|
||||
{"Fitness Score", "0.026"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "649.537"},
|
||||
{"Return Over Maximum Drawdown", "1130.655"},
|
||||
{"Portfolio Turnover", "0.024"},
|
||||
{"Sortino Ratio", "705.118"},
|
||||
{"Return Over Maximum Drawdown", "980.036"},
|
||||
{"Portfolio Turnover", "0.026"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
@@ -233,7 +233,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "25cc4301125ffaa12dd8d8f4387adf06"}
|
||||
{"OrderListHash", "59223250839c411c4686a43d248ad0d7"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,16 +13,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Option;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Option;
|
||||
using QuantConnect.Securities.Volatility;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
@@ -90,6 +87,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var lambda = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.Greeks.Lambda).ToList();
|
||||
var rho = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.Greeks.Rho).ToList();
|
||||
var theta = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.Greeks.Theta).ToList();
|
||||
var impliedVol = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.ImpliedVolatility).ToList();
|
||||
var vega = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.Greeks.Vega).ToList();
|
||||
|
||||
// The commented out test cases all return zero.
|
||||
@@ -116,9 +114,8 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
throw new AggregateException("Option contract Theta was equal to zero");
|
||||
}
|
||||
// The strike is far away from the underlying asset's price, and we're very close to expiry.
|
||||
// Zero is an expected value here.
|
||||
if (vega.Any(v => v != 0))
|
||||
// Vega will equal 0 if the quote price and IV are way too off, causing the price is not sensitive to volatility change
|
||||
if (vega.Zip(impliedVol, (v, iv) => (v, iv)).Any(x => x.v == 0 && x.iv < 10))
|
||||
{
|
||||
throw new AggregateException("Option contract Vega was equal to zero");
|
||||
}
|
||||
@@ -159,7 +156,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 20443;
|
||||
public long DataPoints => 19623;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -173,31 +170,31 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-56.91%"},
|
||||
{"Compounding Annual Return", "44.906%"},
|
||||
{"Drawdown", "9.800%"},
|
||||
{"Average Loss", "-54.58%"},
|
||||
{"Compounding Annual Return", "101.333%"},
|
||||
{"Drawdown", "7.600%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "2.644%"},
|
||||
{"Sharpe Ratio", "5.789"},
|
||||
{"Probabilistic Sharpe Ratio", "89.964%"},
|
||||
{"Net Profit", "5.044%"},
|
||||
{"Sharpe Ratio", "5.256"},
|
||||
{"Probabilistic Sharpe Ratio", "89.867%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "2.169"},
|
||||
{"Beta", "-0.238"},
|
||||
{"Annual Standard Deviation", "0.373"},
|
||||
{"Annual Variance", "0.139"},
|
||||
{"Information Ratio", "5.17"},
|
||||
{"Tracking Error", "0.409"},
|
||||
{"Treynor Ratio", "-9.071"},
|
||||
{"Alpha", "1.695"},
|
||||
{"Beta", "-0.205"},
|
||||
{"Annual Standard Deviation", "0.321"},
|
||||
{"Annual Variance", "0.103"},
|
||||
{"Information Ratio", "4.556"},
|
||||
{"Tracking Error", "0.36"},
|
||||
{"Treynor Ratio", "-8.238"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$44000000.00"},
|
||||
{"Estimated Strategy Capacity", "$59000000.00"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
|
||||
{"Fitness Score", "0.023"},
|
||||
{"Fitness Score", "0.026"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0.535"},
|
||||
{"Return Over Maximum Drawdown", "5.789"},
|
||||
{"Sortino Ratio", "2.257"},
|
||||
{"Return Over Maximum Drawdown", "23.777"},
|
||||
{"Portfolio Turnover", "0.03"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
@@ -212,7 +209,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "bd96db56c80107572e8fc13c8794279b"}
|
||||
{"OrderListHash", "6d74cb5ac8ee73a1154088ad97f5ce3d"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 16486;
|
||||
public long DataPoints => 15656;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -223,7 +223,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "e971949fb0d1cc8d034ad7cba97d09cc"}
|
||||
{"OrderListHash", "fc2a346635cf62e08cf0c6f49579bc93"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
81
Algorithm.CSharp/IndexOptionIronCondorAlgorithm.cs
Normal file
81
Algorithm.CSharp/IndexOptionIronCondorAlgorithm.cs
Normal file
@@ -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.Linq;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Orders;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
public class IndexOptionIronCondorAlgorithm : QCAlgorithm
|
||||
{
|
||||
private Symbol _spxw;
|
||||
private BollingerBands _bb;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2019, 9, 1);
|
||||
SetEndDate(2019, 11, 1);
|
||||
SetCash(100000);
|
||||
|
||||
var index = AddIndex("SPX", Resolution.Minute).Symbol;
|
||||
var option = AddIndexOption(index, "SPXW", Resolution.Minute);
|
||||
option.SetFilter((x) => x.WeeklysOnly().Strikes(-5, 5).Expiration(0, 14));
|
||||
_spxw = option.Symbol;
|
||||
|
||||
_bb = BB(index, 10, 2, resolution: Resolution.Daily);
|
||||
WarmUpIndicator(index, _bb);
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (Portfolio.Invested) return;
|
||||
|
||||
// Get the OptionChain
|
||||
if (!slice.OptionChains.TryGetValue(_spxw, out var chain)) return;
|
||||
|
||||
// Get the closest expiry date
|
||||
var expiry = chain.Min(x => x.Expiry);
|
||||
var contracts = chain.Where(x => x.Expiry == expiry).ToList();
|
||||
|
||||
// Separate the call and put contracts and sort by Strike to find OTM contracts
|
||||
var calls = contracts.Where(x => x.Right == OptionRight.Call)
|
||||
.OrderByDescending(x => x.Strike).ToArray();
|
||||
var puts = contracts.Where(x => x.Right == OptionRight.Put)
|
||||
.OrderBy(x => x.Strike).ToArray();
|
||||
|
||||
if (calls.Length < 3 || puts.Length < 3) return;
|
||||
|
||||
// Create combo order legs
|
||||
var price = _bb.Price.Current.Value;
|
||||
var quantity = 1;
|
||||
if (price > _bb.UpperBand.Current.Value || price < _bb.LowerBand.Current.Value)
|
||||
{
|
||||
quantity = -1;
|
||||
}
|
||||
|
||||
var legs = new List<Leg>
|
||||
{
|
||||
Leg.Create(calls[0].Symbol, quantity),
|
||||
Leg.Create(puts[0].Symbol, quantity),
|
||||
Leg.Create(calls[2].Symbol, -quantity),
|
||||
Leg.Create(puts[2].Symbol, -quantity),
|
||||
};
|
||||
ComboMarketOrder(legs, 10, asynchronous: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
88
Algorithm.CSharp/IndexOptionPutButterflyAlgorithm.cs
Normal file
88
Algorithm.CSharp/IndexOptionPutButterflyAlgorithm.cs
Normal file
@@ -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;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities.Option;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
public class IndexOptionPutButterflyAlgorithm : QCAlgorithm
|
||||
{
|
||||
private Symbol _spxw, _vxz;
|
||||
private decimal _multiplier;
|
||||
private IEnumerable<OrderTicket> _tickets = Enumerable.Empty<OrderTicket>();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2020, 1, 1);
|
||||
SetEndDate(2021, 1, 1);
|
||||
SetCash(1000000);
|
||||
|
||||
_vxz = AddEquity("VXZ", Resolution.Minute).Symbol;
|
||||
|
||||
var index = AddIndex("SPX", Resolution.Minute).Symbol;
|
||||
var option = AddIndexOption(index, "SPXW", Resolution.Minute);
|
||||
option.SetFilter((x) => x.IncludeWeeklys().Strikes(-3, 3).Expiration(15, 45));
|
||||
|
||||
_spxw = option.Symbol;
|
||||
_multiplier = option.SymbolProperties.ContractMultiplier;
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
// The order of magnitude per SPXW order's value is 10000 times of VXZ
|
||||
if (!Portfolio[_vxz].Invested)
|
||||
{
|
||||
MarketOrder(_vxz, 10000);
|
||||
}
|
||||
|
||||
// Return if any opening index option position
|
||||
if (_tickets.Any(x => Portfolio[x.Symbol].Invested)) return;
|
||||
|
||||
// Get the OptionChain
|
||||
if (!slice.OptionChains.TryGetValue(_spxw, out var chain)) return;
|
||||
|
||||
// Get nearest expiry date
|
||||
var expiry = chain.Min(x => x.Expiry);
|
||||
|
||||
// Select the put Option contracts with nearest expiry and sort by strike price
|
||||
var puts = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Put).ToList();
|
||||
if (puts.Count < 3) return;
|
||||
var sortedPutStrikes = puts.Select(x => x.Strike).OrderBy(x => x).ToArray();
|
||||
|
||||
// Select ATM put
|
||||
var atmStrike = puts.MinBy(x => Math.Abs(x.Strike - chain.Underlying.Value)).Strike;
|
||||
|
||||
// Get the strike prices for the ITM & OTM contracts, make sure they're in equidistance
|
||||
var spread = Math.Min(atmStrike - sortedPutStrikes[0], sortedPutStrikes[^1] - atmStrike);
|
||||
var otmStrike = atmStrike - spread;
|
||||
var itmStrike = atmStrike + spread;
|
||||
if (!sortedPutStrikes.Contains(otmStrike) || !sortedPutStrikes.Contains(itmStrike)) return;
|
||||
|
||||
// Buy the put butterfly
|
||||
var putButterfly = OptionStrategies.PutButterfly(_spxw, itmStrike, atmStrike, otmStrike, expiry);
|
||||
var price = putButterfly.UnderlyingLegs.Sum(x => Math.Abs(Securities[x.Symbol].Price * x.Quantity) * _multiplier);
|
||||
if (price > 0)
|
||||
{
|
||||
var quantity = Portfolio.TotalPortfolioValue / price;
|
||||
_tickets = Buy(putButterfly, (int)Math.Floor(quantity), asynchronous: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user