Compare commits
105 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
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/')
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all time slices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 3338420;
|
||||
public long DataPoints => 6023980;
|
||||
|
||||
/// <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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
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 => 15929;
|
||||
|
||||
/// <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", "-7.01%"},
|
||||
{"Compounding Annual Return", "-93.456%"},
|
||||
{"Drawdown", "9.300%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-9.915%"},
|
||||
{"Sharpe Ratio", "-3.845"},
|
||||
{"Probabilistic Sharpe Ratio", "0.053%"},
|
||||
{"Net Profit", "-8.354%"},
|
||||
{"Sharpe Ratio", "-4.078"},
|
||||
{"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.377"},
|
||||
{"Beta", "0.178"},
|
||||
{"Annual Standard Deviation", "0.069"},
|
||||
{"Annual Variance", "0.005"},
|
||||
{"Information Ratio", "-7.596"},
|
||||
{"Tracking Error", "0.108"},
|
||||
{"Treynor Ratio", "-1.583"},
|
||||
{"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.051"},
|
||||
{"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", "-1.51"},
|
||||
{"Return Over Maximum Drawdown", "-11.301"},
|
||||
{"Portfolio Turnover", "0.338"},
|
||||
{"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", "7f5f25fafc99bf45774e63bc528f3fc8"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,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 +30,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 +59,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 122;
|
||||
public override long DataPoints => 121;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -71,34 +71,34 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "9"},
|
||||
{"Total Trades", "8"},
|
||||
{"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%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "617.546%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "8.460%"},
|
||||
{"Sharpe Ratio", "9.015"},
|
||||
{"Probabilistic Sharpe Ratio", "93.474%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"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"},
|
||||
{"Alpha", "3.218"},
|
||||
{"Beta", "-1.013"},
|
||||
{"Annual Standard Deviation", "0.347"},
|
||||
{"Annual Variance", "0.12"},
|
||||
{"Information Ratio", "7.709"},
|
||||
{"Tracking Error", "0.394"},
|
||||
{"Treynor Ratio", "-3.087"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
|
||||
{"Fitness Score", "0.027"},
|
||||
{"Fitness Score", "0.03"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "1776.081"},
|
||||
{"Portfolio Turnover", "0.027"},
|
||||
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
|
||||
{"Portfolio Turnover", "0.03"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
@@ -112,7 +112,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "474e8e0e28ee84c869f8c69ec3efe371"}
|
||||
{"OrderListHash", "dfb226b675ed498ecb67a89483a70da2"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 => 389;
|
||||
|
||||
/// <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"},
|
||||
{"Total Trades", "69"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.23%"},
|
||||
{"Compounding Annual Return", "-34.441%"},
|
||||
{"Average Loss", "-0.06%"},
|
||||
{"Compounding Annual Return", "-39.390%"},
|
||||
{"Drawdown", "2.000%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-2.028%"},
|
||||
{"Sharpe Ratio", "-11.139"},
|
||||
{"Net Profit", "-1.998%"},
|
||||
{"Sharpe Ratio", "-12.504"},
|
||||
{"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"},
|
||||
{"Alpha", "-0.313"},
|
||||
{"Beta", "0.088"},
|
||||
{"Annual Standard Deviation", "0.024"},
|
||||
{"Annual Variance", "0.001"},
|
||||
{"Information Ratio", "-3.624"},
|
||||
{"Tracking Error", "0.094"},
|
||||
{"Treynor Ratio", "-3.042"},
|
||||
{"Information Ratio", "-3.871"},
|
||||
{"Tracking Error", "0.104"},
|
||||
{"Treynor Ratio", "-3.459"},
|
||||
{"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"},
|
||||
{"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", "-15.488"},
|
||||
{"Return Over Maximum Drawdown", "-20.691"},
|
||||
{"Portfolio Turnover", "0.316"},
|
||||
{"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", "cbd2e7697a622b2ce3e24b6003db6f7d"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 381;
|
||||
public override long DataPoints => 374;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -121,7 +121,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "5f5df233d68d9115a0d81785de54e71d"}
|
||||
{"OrderListHash", "607d309c5fb52a8b88310720b4a867e1"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 => 2136;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -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", "482414c332d7780590e4a157dff60b85"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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", "0673d23c27fa8dd01da0aace0e866cc3"}
|
||||
{"OrderListHash", "92610619a10e30863020cc84aa30be3b"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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", "c9e110f2122451dabefcfe24287cadcf"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 => 64935;
|
||||
|
||||
/// <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.73%"},
|
||||
{"Compounding Annual Return", "48.896%"},
|
||||
{"Drawdown", "0.500%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "0.511%"},
|
||||
{"Sharpe Ratio", "-12.853"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.582"},
|
||||
{"Beta", "-0.098"},
|
||||
{"Annual Standard Deviation", "0.009"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-95.086"},
|
||||
{"Tracking Error", "0.076"},
|
||||
{"Treynor Ratio", "1.206"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$7800000.00"},
|
||||
{"Lowest Capacity Asset", "SPXW 31K54PVWHUJHQ|SPX 31"},
|
||||
{"Fitness Score", "0.006"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "64.63"},
|
||||
{"Return Over Maximum Drawdown", "508.46"},
|
||||
{"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", "cd76a48553cb87074150374d4652fb64"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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 => 35091;
|
||||
|
||||
/// <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.984"},
|
||||
{"Probabilistic Sharpe Ratio", "95.977%"},
|
||||
{"Loss Rate", "50%"},
|
||||
{"Win Rate", "50%"},
|
||||
{"Profit-Loss Ratio", "231.56"},
|
||||
{"Alpha", "0.046"},
|
||||
{"Beta", "-0.005"},
|
||||
{"Annual Standard Deviation", "0.001"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-102.372"},
|
||||
{"Tracking Error", "0.07"},
|
||||
{"Treynor Ratio", "-2.467"},
|
||||
{"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", "3571ecc4b2274878146f15167fcc683c"}
|
||||
};
|
||||
}
|
||||
}
|
||||
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 => 884208;
|
||||
|
||||
/// <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 => 884208;
|
||||
|
||||
/// <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 => 884208;
|
||||
|
||||
/// <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 => 884208;
|
||||
|
||||
/// <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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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 => 864200;
|
||||
|
||||
/// </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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
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 => 7008;
|
||||
|
||||
/// <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 => 16800;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -138,31 +138,31 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-26.40%"},
|
||||
{"Compounding Annual Return", "-99.821%"},
|
||||
{"Compounding Annual Return", "-99.822%"},
|
||||
{"Drawdown", "45.600%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-26.400%"},
|
||||
{"Sharpe Ratio", "-0.602"},
|
||||
{"Probabilistic Sharpe Ratio", "19.127%"},
|
||||
{"Sharpe Ratio", "-0.632"},
|
||||
{"Probabilistic Sharpe Ratio", "17.057%"},
|
||||
{"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.692"},
|
||||
{"Beta", "-0.545"},
|
||||
{"Annual Standard Deviation", "1.515"},
|
||||
{"Annual Variance", "2.296"},
|
||||
{"Information Ratio", "-0.949"},
|
||||
{"Tracking Error", "1.524"},
|
||||
{"Treynor Ratio", "1.76"},
|
||||
{"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.256"},
|
||||
{"Return Over Maximum Drawdown", "-2.773"},
|
||||
{"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", "97b069699024898ba02d73e0d9b5c92e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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 => 1819;
|
||||
|
||||
/// <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", "f2313ed7c4a80765c7ac7bb421bf0e19"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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 => 31618;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -133,31 +133,31 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Total Trades", "4"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.06%"},
|
||||
{"Compounding Annual Return", "-1.552%"},
|
||||
{"Compounding Annual Return", "-1.693%"},
|
||||
{"Drawdown", "0.100%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-0.110%"},
|
||||
{"Sharpe Ratio", "-3.157"},
|
||||
{"Net Profit", "-0.120%"},
|
||||
{"Sharpe Ratio", "-3.156"},
|
||||
{"Probabilistic Sharpe Ratio", "0.427%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.011"},
|
||||
{"Alpha", "-0.012"},
|
||||
{"Beta", "-0.004"},
|
||||
{"Annual Standard Deviation", "0.003"},
|
||||
{"Annual Standard Deviation", "0.004"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.405"},
|
||||
{"Tracking Error", "0.138"},
|
||||
{"Treynor Ratio", "2.704"},
|
||||
{"Information Ratio", "-0.412"},
|
||||
{"Tracking Error", "0.139"},
|
||||
{"Treynor Ratio", "2.702"},
|
||||
{"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", "-4231.264"},
|
||||
{"Return Over Maximum Drawdown", "-14.257"},
|
||||
{"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", "a82af2f9ea9f06b920dbbc64c345dce4"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
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 => 19503;
|
||||
|
||||
/// <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%"},
|
||||
{"Average Loss", "-49.72%"},
|
||||
{"Compounding Annual Return", "283.040%"},
|
||||
{"Drawdown", "2.300%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "10.274%"},
|
||||
{"Sharpe Ratio", "5.298"},
|
||||
{"Probabilistic Sharpe Ratio", "88.621%"},
|
||||
{"Net Profit", "9.904%"},
|
||||
{"Sharpe Ratio", "4.871"},
|
||||
{"Probabilistic Sharpe Ratio", "84.534%"},
|
||||
{"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.754"},
|
||||
{"Beta", "-0.237"},
|
||||
{"Annual Standard Deviation", "0.358"},
|
||||
{"Annual Variance", "0.128"},
|
||||
{"Information Ratio", "4.298"},
|
||||
{"Tracking Error", "0.395"},
|
||||
{"Treynor Ratio", "-7.363"},
|
||||
{"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", "43.148"},
|
||||
{"Return Over Maximum Drawdown", "329.485"},
|
||||
{"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", "f8b186afc142a2c7d42a43f2589d0a74"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 => 19503;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -174,31 +171,31 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-56.91%"},
|
||||
{"Compounding Annual Return", "44.906%"},
|
||||
{"Compounding Annual Return", "46.347%"},
|
||||
{"Drawdown", "9.800%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "2.644%"},
|
||||
{"Sharpe Ratio", "5.789"},
|
||||
{"Probabilistic Sharpe Ratio", "89.964%"},
|
||||
{"Net Profit", "2.714%"},
|
||||
{"Sharpe Ratio", "5.348"},
|
||||
{"Probabilistic Sharpe Ratio", "86.253%"},
|
||||
{"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", "2.071"},
|
||||
{"Beta", "-0.244"},
|
||||
{"Annual Standard Deviation", "0.385"},
|
||||
{"Annual Variance", "0.148"},
|
||||
{"Information Ratio", "4.794"},
|
||||
{"Tracking Error", "0.42"},
|
||||
{"Treynor Ratio", "-8.443"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$44000000.00"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
|
||||
{"Fitness Score", "0.023"},
|
||||
{"Fitness Score", "0.025"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0.535"},
|
||||
{"Return Over Maximum Drawdown", "5.789"},
|
||||
{"Portfolio Turnover", "0.03"},
|
||||
{"Sortino Ratio", "0.64"},
|
||||
{"Return Over Maximum Drawdown", "6.283"},
|
||||
{"Portfolio Turnover", "0.032"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "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", "36bf137108b5b6dcdf2a408b252cb03a"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 => 15596;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -184,31 +184,31 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.01%"},
|
||||
{"Compounding Annual Return", "-0.142%"},
|
||||
{"Average Loss", "-0.02%"},
|
||||
{"Compounding Annual Return", "-0.213%"},
|
||||
{"Drawdown", "0.000%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-0.010%"},
|
||||
{"Sharpe Ratio", "-4.584"},
|
||||
{"Net Profit", "-0.015%"},
|
||||
{"Sharpe Ratio", "-4.329"},
|
||||
{"Probabilistic Sharpe Ratio", "0.015%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.001"},
|
||||
{"Alpha", "-0.002"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.334"},
|
||||
{"Information Ratio", "-0.338"},
|
||||
{"Tracking Error", "0.138"},
|
||||
{"Treynor Ratio", "-9.47"},
|
||||
{"Treynor Ratio", "-7.266"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$22000.00"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-51177.748"},
|
||||
{"Return Over Maximum Drawdown", "-14.362"},
|
||||
{"Sortino Ratio", "-3.837"},
|
||||
{"Return Over Maximum Drawdown", "-14.357"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
@@ -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", "75e3d7129bde6f02001043217f283b40"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
84
Algorithm.CSharp/IndexOptionPutCalendarSpreadAlgorithm.cs
Normal file
84
Algorithm.CSharp/IndexOptionPutCalendarSpreadAlgorithm.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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 IndexOptionPutCalendarSpreadAlgorithm : QCAlgorithm
|
||||
{
|
||||
private Symbol _vixw, _vxz;
|
||||
private IEnumerable<OrderTicket> _tickets = Enumerable.Empty<OrderTicket>();
|
||||
private DateTime _firstExpiry = DateTime.MaxValue;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2020, 1, 1);
|
||||
SetEndDate(2023, 1, 1);
|
||||
SetCash(50000);
|
||||
|
||||
_vxz = AddEquity("VXZ", 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;
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio[_vxz].Invested)
|
||||
{
|
||||
MarketOrder(_vxz, 100);
|
||||
}
|
||||
|
||||
var indexOptionsInvested = _tickets.Where(x => Portfolio[x.Symbol].Invested).ToList();
|
||||
// Liquidate if the shorter term option is about to expire
|
||||
if (_firstExpiry < Time.AddDays(2) && _tickets.All(x => slice.ContainsKey(x.Symbol)))
|
||||
{
|
||||
foreach (var holding in indexOptionsInvested)
|
||||
{
|
||||
Liquidate(holding.Symbol);
|
||||
}
|
||||
}
|
||||
// Return if there is any opening index option position
|
||||
else if (indexOptionsInvested.Count > 0)
|
||||
{
|
||||
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 put Option contracts and sort by expiration date
|
||||
var puts = chain.Where(x => x.Strike == strike && x.Right == OptionRight.Put)
|
||||
.OrderBy(x => x.Expiry).ToArray();
|
||||
if (puts.Length < 2) return;
|
||||
_firstExpiry = puts[0].Expiry;
|
||||
|
||||
// Sell the put calendar spread
|
||||
var putCalendarSpread = OptionStrategies.PutCalendarSpread(_vixw, strike, _firstExpiry, puts[^1].Expiry);
|
||||
_tickets = Sell(putCalendarSpread, 1, asynchronous: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,7 +185,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 20425;
|
||||
public long DataPoints => 19485;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -199,32 +199,32 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-51.53%"},
|
||||
{"Compounding Annual Return", "-81.170%"},
|
||||
{"Drawdown", "13.800%"},
|
||||
{"Average Loss", "-51.16%"},
|
||||
{"Compounding Annual Return", "-80.264%"},
|
||||
{"Drawdown", "13.400%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-11.084%"},
|
||||
{"Sharpe Ratio", "-1.893"},
|
||||
{"Probabilistic Sharpe Ratio", "0.513%"},
|
||||
{"Net Profit", "-10.784%"},
|
||||
{"Sharpe Ratio", "-1.791"},
|
||||
{"Probabilistic Sharpe Ratio", "1.276%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.683"},
|
||||
{"Beta", "0.218"},
|
||||
{"Annual Standard Deviation", "0.356"},
|
||||
{"Annual Variance", "0.126"},
|
||||
{"Information Ratio", "-1.94"},
|
||||
{"Tracking Error", "0.37"},
|
||||
{"Treynor Ratio", "-3.083"},
|
||||
{"Alpha", "-0.67"},
|
||||
{"Beta", "0.223"},
|
||||
{"Annual Standard Deviation", "0.369"},
|
||||
{"Annual Variance", "0.136"},
|
||||
{"Information Ratio", "-1.843"},
|
||||
{"Tracking Error", "0.383"},
|
||||
{"Treynor Ratio", "-2.965"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "SPX 31KC0UJHC75TA|SPX 31"},
|
||||
{"Fitness Score", "0.005"},
|
||||
{"Fitness Score", "0.006"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-0.662"},
|
||||
{"Return Over Maximum Drawdown", "-7.157"},
|
||||
{"Portfolio Turnover", "0.025"},
|
||||
{"Sortino Ratio", "-0.638"},
|
||||
{"Return Over Maximum Drawdown", "-6.853"},
|
||||
{"Portfolio Turnover", "0.027"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
@@ -238,7 +238,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "6df8b200489a2f217cd514592ee98663"}
|
||||
{"OrderListHash", "f12712654608a831bf73f3d8747997f9"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 20519;
|
||||
public long DataPoints => 19579;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -183,31 +183,31 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.37%"},
|
||||
{"Compounding Annual Return", "-5.132%"},
|
||||
{"Average Loss", "-0.36%"},
|
||||
{"Compounding Annual Return", "-4.999%"},
|
||||
{"Drawdown", "0.400%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-0.370%"},
|
||||
{"Sharpe Ratio", "-3.253"},
|
||||
{"Probabilistic Sharpe Ratio", "0.221%"},
|
||||
{"Net Profit", "-0.360%"},
|
||||
{"Sharpe Ratio", "-3.306"},
|
||||
{"Probabilistic Sharpe Ratio", "0.170%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.037"},
|
||||
{"Beta", "0.007"},
|
||||
{"Alpha", "-0.036"},
|
||||
{"Beta", "0.006"},
|
||||
{"Annual Standard Deviation", "0.011"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.595"},
|
||||
{"Information Ratio", "-0.588"},
|
||||
{"Tracking Error", "0.137"},
|
||||
{"Treynor Ratio", "-5.349"},
|
||||
{"Treynor Ratio", "-5.609"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "SPX 31KC0UJFONTBI|SPX 31"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-1.628"},
|
||||
{"Return Over Maximum Drawdown", "-14.021"},
|
||||
{"Sortino Ratio", "-1.669"},
|
||||
{"Return Over Maximum Drawdown", "-14.031"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
@@ -222,7 +222,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "b0c50080f0229facd065721f1f5d715e"}
|
||||
{"OrderListHash", "d783bad741a034d6742f0d9b6cfc676d"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 20443;
|
||||
public long DataPoints => 19503;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -184,33 +184,33 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "48.82%"},
|
||||
{"Average Win", "49.16%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "-80.089%"},
|
||||
{"Drawdown", "13.400%"},
|
||||
{"Compounding Annual Return", "-79.233%"},
|
||||
{"Drawdown", "13.000%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "-10.734%"},
|
||||
{"Sharpe Ratio", "-1.921"},
|
||||
{"Probabilistic Sharpe Ratio", "0.511%"},
|
||||
{"Net Profit", "-10.464%"},
|
||||
{"Sharpe Ratio", "-1.813"},
|
||||
{"Probabilistic Sharpe Ratio", "1.295%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.671"},
|
||||
{"Beta", "0.211"},
|
||||
{"Annual Standard Deviation", "0.344"},
|
||||
{"Annual Variance", "0.118"},
|
||||
{"Information Ratio", "-1.963"},
|
||||
{"Tracking Error", "0.36"},
|
||||
{"Treynor Ratio", "-3.133"},
|
||||
{"Alpha", "-0.659"},
|
||||
{"Beta", "0.216"},
|
||||
{"Annual Standard Deviation", "0.358"},
|
||||
{"Annual Variance", "0.128"},
|
||||
{"Information Ratio", "-1.862"},
|
||||
{"Tracking Error", "0.373"},
|
||||
{"Treynor Ratio", "-3.009"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
|
||||
{"Fitness Score", "0.005"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-0.676"},
|
||||
{"Return Over Maximum Drawdown", "-7.289"},
|
||||
{"Portfolio Turnover", "0.024"},
|
||||
{"Sortino Ratio", "-0.65"},
|
||||
{"Return Over Maximum Drawdown", "-6.959"},
|
||||
{"Portfolio Turnover", "0.025"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
@@ -224,7 +224,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "856448f4cbba4fc39af8dba369c054df"}
|
||||
{"OrderListHash", "ea4fe706e695a600d4f8ff65fb336e48"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 16486;
|
||||
public long DataPoints => 15596;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -176,24 +176,24 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0.01%"},
|
||||
{"Average Win", "0.02%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0.142%"},
|
||||
{"Compounding Annual Return", "0.214%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0.010%"},
|
||||
{"Sharpe Ratio", "4.589"},
|
||||
{"Probabilistic Sharpe Ratio", "98.983%"},
|
||||
{"Net Profit", "0.015%"},
|
||||
{"Sharpe Ratio", "4.336"},
|
||||
{"Probabilistic Sharpe Ratio", "98.801%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.001"},
|
||||
{"Alpha", "0.002"},
|
||||
{"Beta", "-0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.32"},
|
||||
{"Information Ratio", "-0.316"},
|
||||
{"Tracking Error", "0.138"},
|
||||
{"Treynor Ratio", "-9.479"},
|
||||
{"Treynor Ratio", "-7.277"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$22000.00"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
|
||||
@@ -216,7 +216,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "76ffdfc100ba7778009e35966bd92cfc"}
|
||||
{"OrderListHash", "d5090abe5701a66559fcd4d1cb254a62"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 20425;
|
||||
public long DataPoints => 19485;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -188,33 +188,33 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "51.07%"},
|
||||
{"Average Win", "50.61%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "319.986%"},
|
||||
{"Drawdown", "2.400%"},
|
||||
{"Compounding Annual Return", "299.724%"},
|
||||
{"Drawdown", "2.300%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "10.624%"},
|
||||
{"Sharpe Ratio", "5.415"},
|
||||
{"Probabilistic Sharpe Ratio", "88.697%"},
|
||||
{"Net Profit", "10.234%"},
|
||||
{"Sharpe Ratio", "4.986"},
|
||||
{"Probabilistic Sharpe Ratio", "84.774%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "1.938"},
|
||||
{"Beta", "-0.235"},
|
||||
{"Annual Standard Deviation", "0.356"},
|
||||
{"Annual Variance", "0.127"},
|
||||
{"Information Ratio", "4.787"},
|
||||
{"Tracking Error", "0.393"},
|
||||
{"Treynor Ratio", "-8.187"},
|
||||
{"Alpha", "1.847"},
|
||||
{"Beta", "-0.243"},
|
||||
{"Annual Standard Deviation", "0.368"},
|
||||
{"Annual Variance", "0.136"},
|
||||
{"Information Ratio", "4.425"},
|
||||
{"Tracking Error", "0.405"},
|
||||
{"Treynor Ratio", "-7.549"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "SPX 31KC0UJHC75TA|SPX 31"},
|
||||
{"Fitness Score", "0.025"},
|
||||
{"Fitness Score", "0.026"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "634.943"},
|
||||
{"Return Over Maximum Drawdown", "1184.633"},
|
||||
{"Portfolio Turnover", "0.025"},
|
||||
{"Sortino Ratio", "45.186"},
|
||||
{"Return Over Maximum Drawdown", "348.282"},
|
||||
{"Portfolio Turnover", "0.026"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
@@ -228,7 +228,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "77d9040316634cb6b9e8cd2e4e192fd5"}
|
||||
{"OrderListHash", "6cdc8adaaa3f02bd674f038d443ffbaf"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 20519;
|
||||
public long DataPoints => 19579;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -175,24 +175,24 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0.35%"},
|
||||
{"Average Win", "0.33%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "5.091%"},
|
||||
{"Compounding Annual Return", "4.797%"},
|
||||
{"Drawdown", "0.000%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0.350%"},
|
||||
{"Sharpe Ratio", "3.182"},
|
||||
{"Probabilistic Sharpe Ratio", "90.575%"},
|
||||
{"Net Profit", "0.330%"},
|
||||
{"Sharpe Ratio", "3.126"},
|
||||
{"Probabilistic Sharpe Ratio", "89.571%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.036"},
|
||||
{"Beta", "-0.008"},
|
||||
{"Alpha", "0.034"},
|
||||
{"Beta", "-0.007"},
|
||||
{"Annual Standard Deviation", "0.011"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.066"},
|
||||
{"Information Ratio", "-0.081"},
|
||||
{"Tracking Error", "0.139"},
|
||||
{"Treynor Ratio", "-4.733"},
|
||||
{"Treynor Ratio", "-4.529"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "SPX 31KC0UJFONTBI|SPX 31"},
|
||||
@@ -200,7 +200,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "514.964"},
|
||||
{"Return Over Maximum Drawdown", "323.257"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
@@ -215,7 +215,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "12861ef440f68994997aeb24c8027748"}
|
||||
{"OrderListHash", "8a9af32decfdffa4a21c04751c69c2df"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm illustrating how to get a security's industry-standard identifier from its <see cref="Symbol"/>
|
||||
/// </summary>
|
||||
public class IndustryStandardSecurityIdentifiersRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07);
|
||||
SetEndDate(2013, 10, 07);
|
||||
|
||||
var spy = AddEquity("SPY").Symbol;
|
||||
|
||||
var spyCusip = spy.CUSIP;
|
||||
var spyCompositeFigi = spy.CompositeFIGI;
|
||||
var spySedol = spy.SEDOL;
|
||||
var spyIsin = spy.ISIN;
|
||||
|
||||
CheckSymbolRepresentation(spyCusip, "CUSIP");
|
||||
CheckSymbolRepresentation(spyCompositeFigi, "Composite FIGI");
|
||||
CheckSymbolRepresentation(spySedol, "SEDOL");
|
||||
CheckSymbolRepresentation(spyIsin, "ISIN");
|
||||
|
||||
// Check Symbol API vs QCAlgorithm API
|
||||
CheckAPIsSymbolRepresentations(spyCusip, CUSIP(spy), "CUSIP");
|
||||
CheckAPIsSymbolRepresentations(spyCompositeFigi, CompositeFIGI(spy), "Composite FIGI");
|
||||
CheckAPIsSymbolRepresentations(spySedol, SEDOL(spy), "SEDOL");
|
||||
CheckAPIsSymbolRepresentations(spyIsin, ISIN(spy), "ISIN");
|
||||
|
||||
Log($"\nSPY CUSIP: {spyCusip}" +
|
||||
$"\nSPY Composite FIGI: {spyCompositeFigi}" +
|
||||
$"\nSPY SEDOL: {spySedol}" +
|
||||
$"\nSPY ISIN: {spyIsin}");
|
||||
}
|
||||
|
||||
private static void CheckSymbolRepresentation(string symbol, string standard)
|
||||
{
|
||||
if (symbol.IsNullOrEmpty())
|
||||
{
|
||||
throw new Exception($"{standard} symbol representation is null or empty");
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckAPIsSymbolRepresentations(string symbolApiSymbol, string algorithmApiSymbol, string standard)
|
||||
{
|
||||
if (symbolApiSymbol != algorithmApiSymbol)
|
||||
{
|
||||
throw new Exception($@"Symbol API {standard} symbol representation ({symbolApiSymbol}) does not match QCAlgorithm API {
|
||||
standard} symbol representation ({algorithmApiSymbol})");
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 => 795;
|
||||
|
||||
/// <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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Brokerages;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities.Option;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm asserting that InteractiveBrokers brokerage model does not support index options exercise
|
||||
/// </summary>
|
||||
public class InteractiveBrokersBrokerageDisablesIndexOptionsExerciseRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Option _option;
|
||||
|
||||
private OptionContract _contract;
|
||||
|
||||
private bool _marketOrderDone;
|
||||
|
||||
private bool _triedExercise;
|
||||
|
||||
private bool _automaticallyExercised;
|
||||
|
||||
private decimal _initialCash = 200000;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2021, 1, 4);
|
||||
SetEndDate(2021, 1, 30);
|
||||
SetCash(_initialCash);
|
||||
|
||||
SetBrokerageModel(new InteractiveBrokersBrokerageModel());
|
||||
|
||||
var index = AddIndex("SPX", Resolution.Hour, fillDataForward: true);
|
||||
var indexOption = AddIndexOption(index.Symbol, Resolution.Hour, fillDataForward: true);
|
||||
indexOption.SetFilter(filterFunc => filterFunc.CallsOnly());
|
||||
|
||||
_option = indexOption;
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (_triedExercise || !_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 (UtcTime.Date < expiry && !_marketOrderDone)
|
||||
{
|
||||
if (MarketOrder(_contract.Symbol, 1).Status != OrderStatus.Filled)
|
||||
{
|
||||
throw new Exception("Expected market order to fill immediately");
|
||||
}
|
||||
|
||||
_marketOrderDone = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_triedExercise && UtcTime.Date == expiry)
|
||||
{
|
||||
if (ExerciseOption(_contract.Symbol, 1).Status == OrderStatus.Filled)
|
||||
{
|
||||
throw new Exception($"Expected index option to not be exercisable on its expiration date. " +
|
||||
$"Time: {UtcTime}. Expiry: {_contract.Expiry.ConvertToUtc(_option.Exchange.TimeZone)}");
|
||||
}
|
||||
|
||||
_triedExercise = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
// The manual exercise failed and we are not placing any other orders, so this is the automatic exercise
|
||||
if (orderEvent.Status == OrderStatus.Filled &&
|
||||
_marketOrderDone &&
|
||||
_triedExercise &&
|
||||
UtcTime.Date >= _contract.Expiry.ConvertToUtc(_option.Exchange.TimeZone).Date)
|
||||
{
|
||||
var profit = Portfolio.TotalPortfolioValue - _initialCash;
|
||||
if (profit < 0)
|
||||
{
|
||||
throw new Exception($"Expected profit to be positive. Actual: {profit}");
|
||||
}
|
||||
|
||||
_automaticallyExercised = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_triedExercise)
|
||||
{
|
||||
throw new Exception("Expected to try to exercise index option before and on expiry");
|
||||
}
|
||||
|
||||
if (!_automaticallyExercised || Portfolio.Cash <= _initialCash)
|
||||
{
|
||||
throw new Exception("Expected index option to have ben automatically exercised on expiry and to have received cash");
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 => 1934;
|
||||
|
||||
/// <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", "10.590%"},
|
||||
{"Drawdown", "1.900%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "0.712%"},
|
||||
{"Sharpe Ratio", "3.343"},
|
||||
{"Probabilistic Sharpe Ratio", "87.312%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0.081"},
|
||||
{"Annual Variance", "0.007"},
|
||||
{"Information Ratio", "3.343"},
|
||||
{"Tracking Error", "0.081"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$1.00"},
|
||||
{"Estimated Strategy Capacity", "$1700000.00"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3HB5O6M|SPX 31"},
|
||||
{"Fitness Score", "0.001"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0.651"},
|
||||
{"Return Over Maximum Drawdown", "6.583"},
|
||||
{"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", "b9dfd17bb95246e5d04d9e6c4b959d71"}
|
||||
};
|
||||
}
|
||||
}
|
||||
165
Algorithm.CSharp/LargeQuantityOptionStrategyAlgorithm.cs
Normal file
165
Algorithm.CSharp/LargeQuantityOptionStrategyAlgorithm.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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities.Option;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm asserting that orders for option strategies can be placed with large quantities as long as there is margin available.
|
||||
/// This asserts the expected behavior in GH issue #5693
|
||||
/// </summary>
|
||||
public class LargeQuantityOptionStrategyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _optionSymbol;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2015, 12, 24);
|
||||
SetEndDate(2015, 12, 24);
|
||||
SetCash(100000);
|
||||
|
||||
SetSecurityInitializer(x => x.SetMarketPrice(GetLastKnownPrice(x)));
|
||||
|
||||
var equity = AddEquity("GOOG");
|
||||
var option = AddOption("GOOG");
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(-2, +2, 0, 180);
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (Portfolio.Invested || !slice.OptionChains.TryGetValue(_optionSymbol, out var chain))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var putContractsWithLatestExpiry = chain
|
||||
// puts only
|
||||
.Where(x => x.Right == OptionRight.Put)
|
||||
// contracts with latest expiry
|
||||
.GroupBy(x => x.Expiry)
|
||||
.OrderBy(x => x.Key)
|
||||
.Last()
|
||||
// ordered by strike
|
||||
.OrderBy(x => x.Strike)
|
||||
.ToList();
|
||||
|
||||
if (putContractsWithLatestExpiry.Count < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var longContract = putContractsWithLatestExpiry[0];
|
||||
var shortContract = putContractsWithLatestExpiry[1];
|
||||
|
||||
var strategy = OptionStrategies.BearPutSpread(_optionSymbol, shortContract.Strike, longContract.Strike, shortContract.Expiry);
|
||||
|
||||
// Before option strategies orders were place as combo orders, only a quantity up to 18 could be used in this case,
|
||||
// even though the remaining margin was enough to support a larger quantity. See GH issue #5693.
|
||||
// We want to assert that with combo orders, large quantities can be used on option strategies
|
||||
Order(strategy, 19);
|
||||
|
||||
Quit($"Margin used: {Portfolio.TotalMarginUsed}; Remaining: {Portfolio.MarginRemaining}");
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
var filledOrders = Transactions.GetOrders(x => x.Status == OrderStatus.Filled).ToList();
|
||||
|
||||
if (filledOrders.Count != 2)
|
||||
{
|
||||
throw new Exception($"Expected 2 filled orders but found {filledOrders.Count}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 => 2262;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 25;
|
||||
|
||||
/// <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", "$9.50"},
|
||||
{"Estimated Strategy Capacity", "$6000.00"},
|
||||
{"Lowest Capacity Asset", "GOOCV 30AKMELSHQVZA|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", "f063bcbcfbf501dab9c573bd493363b1"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This regression test is a version of <see cref="MarketOnCloseOrderBufferRegressionAlgorithm"/>
|
||||
/// where we test market-on-close modeling with data from the post market.
|
||||
/// </summary>
|
||||
public class MarketOnCloseOrderBufferExtendedMarketHoursRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private OrderTicket _validOrderTicket;
|
||||
private OrderTicket _invalidOrderTicket;
|
||||
private OrderTicket _validOrderTicketAtMidnight;
|
||||
private OrderTicket _validOrderTicketExtendedMarketHours;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 7); //Set Start Date
|
||||
SetEndDate(2013, 10, 8); //Set End Date
|
||||
|
||||
var ticker = "SPY";
|
||||
AddEquity(ticker, Resolution.Minute, extendedMarketHours: true);
|
||||
|
||||
Schedule.On(DateRules.Tomorrow, TimeRules.Midnight, () =>
|
||||
{
|
||||
_validOrderTicketAtMidnight = MarketOnCloseOrder("SPY", 2);
|
||||
});
|
||||
|
||||
// Modify our submission buffer time to 10 minutes
|
||||
Orders.MarketOnCloseOrder.SubmissionTimeBuffer = TimeSpan.FromMinutes(10);
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
// Test our ability to submit MarketOnCloseOrders
|
||||
// Because we set our buffer to 10 minutes, any order placed
|
||||
// before 3:50PM should be accepted, any after marked invalid
|
||||
if (Time.Hour == 15 && Time.Minute == 49 && _validOrderTicket == null)
|
||||
{
|
||||
// Will not throw an order error and execute
|
||||
_validOrderTicket = MarketOnCloseOrder("SPY", 2);
|
||||
}
|
||||
|
||||
if (Time.Hour == 15 && Time.Minute == 51 && _invalidOrderTicket == null)
|
||||
{
|
||||
// Will throw an order error and be marked invalid
|
||||
_invalidOrderTicket = MarketOnCloseOrder("SPY", 2);
|
||||
}
|
||||
|
||||
if (Time.Hour == 16 && Time.Minute == 48 && _validOrderTicketExtendedMarketHours == null)
|
||||
{
|
||||
// Will not throw an order error and execute
|
||||
_validOrderTicketExtendedMarketHours = MarketOnCloseOrder("SPY", 2);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
// Set it back to default for other regressions
|
||||
Orders.MarketOnCloseOrder.SubmissionTimeBuffer = Orders.MarketOnCloseOrder.DefaultSubmissionTimeBuffer;
|
||||
|
||||
// Verify that our good order filled
|
||||
if (_validOrderTicket.Status != OrderStatus.Filled)
|
||||
{
|
||||
throw new Exception("Valid order failed to fill");
|
||||
}
|
||||
|
||||
// Verify our order was marked invalid
|
||||
if (_invalidOrderTicket.Status != OrderStatus.Invalid)
|
||||
{
|
||||
throw new Exception("Invalid order was not rejected");
|
||||
}
|
||||
|
||||
// Verify that our second good order filled
|
||||
if (_validOrderTicketExtendedMarketHours.Status != OrderStatus.Filled)
|
||||
{
|
||||
throw new Exception("Valid order during extended market hours failed to fill");
|
||||
}
|
||||
|
||||
// Verify that our third good order filled
|
||||
if (_validOrderTicketAtMidnight.Status != OrderStatus.Filled)
|
||||
{
|
||||
throw new Exception("Valid order at midnight failed to fill");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public Language[] Languages { get; } = { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 3862;
|
||||
|
||||
/// <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", "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", "$3.00"},
|
||||
{"Estimated Strategy Capacity", "$910000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-46.084"},
|
||||
{"Return Over Maximum Drawdown", "-198.32"},
|
||||
{"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", "21a9fc316b33b82d2d99c508040649cd"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -26,15 +26,21 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
private OrderTicket _validOrderTicket;
|
||||
private OrderTicket _invalidOrderTicket;
|
||||
private OrderTicket _validOrderTicketExtendedMarketHours;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 4); //Set Start Date
|
||||
SetEndDate(2013, 10, 4); //Set End Date
|
||||
SetStartDate(2013, 10, 7); //Set Start Date
|
||||
SetEndDate(2013, 10, 8); //Set End Date
|
||||
|
||||
var ticker = "SPY";
|
||||
AddEquity(ticker, Resolution.Minute);
|
||||
|
||||
Schedule.On(DateRules.Today, TimeRules.At(17,00), () =>
|
||||
{
|
||||
_validOrderTicketExtendedMarketHours = MarketOnCloseOrder("SPY", 2);
|
||||
});
|
||||
|
||||
// Modify our submission buffer time to 10 minutes
|
||||
Orders.MarketOnCloseOrder.SubmissionTimeBuffer = TimeSpan.FromMinutes(10);
|
||||
}
|
||||
@@ -44,14 +50,13 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
// Test our ability to submit MarketOnCloseOrders
|
||||
// Because we set our buffer to 10 minutes, any order placed
|
||||
// before 3:50PM should be accepted, any after marked invalid
|
||||
|
||||
if (Time.Hour == 15 && Time.Minute == 49)
|
||||
if (Time.Hour == 15 && Time.Minute == 49 && _validOrderTicket == null)
|
||||
{
|
||||
// Will not throw an order error and execute
|
||||
_validOrderTicket = MarketOnCloseOrder("SPY", 2);
|
||||
}
|
||||
|
||||
if (Time.Hour == 15 && Time.Minute == 51)
|
||||
if (Time.Hour == 15 && Time.Minute == 51 && _invalidOrderTicket == null)
|
||||
{
|
||||
// Will throw an order error and be marked invalid
|
||||
_invalidOrderTicket = MarketOnCloseOrder("SPY", 2);
|
||||
@@ -74,6 +79,12 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
throw new Exception("Invalid order was not rejected");
|
||||
}
|
||||
|
||||
// Verify that our second good order filled
|
||||
if (_validOrderTicketExtendedMarketHours.Status != OrderStatus.Filled)
|
||||
{
|
||||
throw new Exception("Valid order during extended market hours failed to fill");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -89,7 +100,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 795;
|
||||
public long DataPoints => 1582;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -99,9 +110,9 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <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>
|
||||
public Dictionary<string, string> ExpectedStatistics => new()
|
||||
{
|
||||
{"Total Trades", "1"},
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
@@ -120,15 +131,15 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Information Ratio", "0"},
|
||||
{"Tracking Error", "0"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$1.00"},
|
||||
{"Estimated Strategy Capacity", "$23000000000.00"},
|
||||
{"Total Fees", "$2.00"},
|
||||
{"Estimated Strategy Capacity", "$18000000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Fitness Score", "0.001"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Return Over Maximum Drawdown", "0"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "-261.069"},
|
||||
{"Portfolio Turnover", "0.002"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
@@ -142,7 +153,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "8c2178d2b47a3773c217e9d0e3eaa179"}
|
||||
{"OrderListHash", "1a356e0edb136b31a7f12c661cf5de74"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
121
Algorithm.CSharp/MissingTickDataAlgorithm.cs
Normal file
121
Algorithm.CSharp/MissingTickDataAlgorithm.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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
public class MissingTickDataAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 08);
|
||||
SetEndDate(2013, 10, 08);
|
||||
|
||||
var spy = AddEquity("SPY", Resolution.Tick).Symbol;
|
||||
|
||||
var start = new DateTime(2013, 10, 07, 15, 0, 0);
|
||||
|
||||
var slices = History(new[] { spy }, start, start.AddSeconds(10), Resolution.Tick).ToList();
|
||||
var tickCountInSliceHistoryCall = slices.Sum(x => x.Ticks[spy].Count);
|
||||
|
||||
var ticks = History<Tick>(spy, start, start.AddSeconds(10), Resolution.Tick).ToList();
|
||||
var tickCountInTickHistoryCall = ticks.Count;
|
||||
|
||||
if (tickCountInSliceHistoryCall != tickCountInTickHistoryCall)
|
||||
{
|
||||
throw new Exception($@"Tick count mismatch in Slice and Tick history calls: History() returned {
|
||||
tickCountInSliceHistoryCall} ticks, while History<Tick>() returned {tickCountInTickHistoryCall} ticks");
|
||||
}
|
||||
|
||||
// Early quit, we already tested what we wanted
|
||||
Quit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 1610;
|
||||
|
||||
/// <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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user