Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26584c2fd0 | ||
|
|
48fd4eccff | ||
|
|
75d5cbcf2a | ||
|
|
d702587ad8 | ||
|
|
c99a9dab32 | ||
|
|
8196d0b557 | ||
|
|
3ee941f329 | ||
|
|
286353b763 | ||
|
|
d5f298c235 | ||
|
|
f2c5551b1e | ||
|
|
f86a51ac3f | ||
|
|
1253cc73bd | ||
|
|
6506ff53a3 | ||
|
|
713785157e | ||
|
|
fd7048d2d1 | ||
|
|
1b66aeede1 | ||
|
|
2f80a2a6b9 | ||
|
|
68d4da8e76 | ||
|
|
538405d152 | ||
|
|
1f3fd6edbb | ||
|
|
e3783ed477 | ||
|
|
1171e4fe52 | ||
|
|
a66f279852 | ||
|
|
6575b57146 | ||
|
|
3fa700e450 | ||
|
|
7735917c83 | ||
|
|
67489eef57 | ||
|
|
241306275a | ||
|
|
773bd53525 | ||
|
|
0854ab82da | ||
|
|
2c0390fde3 | ||
|
|
32fcd94abc | ||
|
|
090ffebd03 | ||
|
|
914d0810af | ||
|
|
10902f95dd | ||
|
|
2e67b9ad4f | ||
|
|
7adf27aa61 | ||
|
|
7ea0f60905 | ||
|
|
d9c71e3d34 | ||
|
|
b040518d52 | ||
|
|
725737610a | ||
|
|
37ccee4937 | ||
|
|
0ab0abd1ca | ||
|
|
c565f4cfd0 | ||
|
|
f804b8f0ca | ||
|
|
ef1cf8e4df | ||
|
|
661356e33e | ||
|
|
5842f50b03 | ||
|
|
0f80591f51 | ||
|
|
0622f43a0f | ||
|
|
8f0224feb6 | ||
|
|
781897984e | ||
|
|
340b40c6ce | ||
|
|
58ce899b5d | ||
|
|
ead8335c84 | ||
|
|
84ee81b35b | ||
|
|
03be232f31 | ||
|
|
e568162bff | ||
|
|
e395892b8e | ||
|
|
3483fee766 | ||
|
|
6cba915950 | ||
|
|
046df38be8 | ||
|
|
c7e96b837d | ||
|
|
2f23c89307 | ||
|
|
67d19d88d7 | ||
|
|
b4401db512 | ||
|
|
bc646c974a | ||
|
|
857a950e23 | ||
|
|
888752fa0a | ||
|
|
14427129c7 | ||
|
|
683bfe007a | ||
|
|
263a9099ed | ||
|
|
a78004a1e6 | ||
|
|
9acd30c355 | ||
|
|
441ba1a7b5 | ||
|
|
52b788d9de | ||
|
|
16fdf61903 | ||
|
|
59990573c2 | ||
|
|
acb787e8f6 | ||
|
|
6260b2f7e0 |
@@ -28,9 +28,9 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
# install dependencies
|
||||
pip3 install papermill==2.4.0 clr-loader==0.1.6
|
||||
pip3 install papermill==2.4.0 clr-loader==0.2.9
|
||||
# install kernel
|
||||
dotnet tool install --global Microsoft.dotnet-interactive --version 1.0.607001
|
||||
dotnet tool install -g --no-cache --version 1.0.661703 --add-source "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" Microsoft.dotnet-interactive
|
||||
# Add dotnet tools to Path
|
||||
export PATH="$HOME/.dotnet/tools:$PATH"
|
||||
# activate kernel for jupyter
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 62;
|
||||
public long DataPoints => 61;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -132,34 +132,34 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "3"},
|
||||
{"Total Orders", "4"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.03%"},
|
||||
{"Compounding Annual Return", "-2.594%"},
|
||||
{"Drawdown", "0.000%"},
|
||||
{"Average Loss", "-0.10%"},
|
||||
{"Compounding Annual Return", "-14.232%"},
|
||||
{"Drawdown", "0.200%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "99966.4"},
|
||||
{"Net Profit", "-0.034%"},
|
||||
{"Sharpe Ratio", "-10.666"},
|
||||
{"End Equity", "99803.9"},
|
||||
{"Net Profit", "-0.196%"},
|
||||
{"Sharpe Ratio", "-7.95"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "1.216%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.029"},
|
||||
{"Beta", "0.004"},
|
||||
{"Annual Standard Deviation", "0.003"},
|
||||
{"Alpha", "-0.128"},
|
||||
{"Beta", "0.026"},
|
||||
{"Annual Standard Deviation", "0.016"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.768"},
|
||||
{"Tracking Error", "0.241"},
|
||||
{"Treynor Ratio", "-6.368"},
|
||||
{"Information Ratio", "-1.186"},
|
||||
{"Tracking Error", "0.237"},
|
||||
{"Treynor Ratio", "-4.747"},
|
||||
{"Total Fees", "$8.60"},
|
||||
{"Estimated Strategy Capacity", "$5500000.00"},
|
||||
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
|
||||
{"Portfolio Turnover", "66.80%"},
|
||||
{"Estimated Strategy Capacity", "$2000.00"},
|
||||
{"Lowest Capacity Asset", "ES VU1EHIDJYLMP"},
|
||||
{"Portfolio Turnover", "66.50%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "39f1e15c27212d8fdd58aeb7fb2b93cc"}
|
||||
{"OrderListHash", "4720516462fcabb4db1aead46051cb4a"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Lowest Capacity Asset", "ES 31C3JQS9DCF1G|ES XCZJLC9NOB29"},
|
||||
{"Portfolio Turnover", "495.15%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "3f6016b4879428eaef0b7057d4b86f18"}
|
||||
{"OrderListHash", "af830085995d0b8fa0d33a6e80dd1241"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,31 +240,31 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "309.669%"},
|
||||
{"Drawdown", "0.900%"},
|
||||
{"Compounding Annual Return", "430.834%"},
|
||||
{"Drawdown", "4.200%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "101950.53"},
|
||||
{"Net Profit", "1.951%"},
|
||||
{"Sharpe Ratio", "15.402"},
|
||||
{"End Equity", "102313.03"},
|
||||
{"Net Profit", "2.313%"},
|
||||
{"Sharpe Ratio", "17.721"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "95.977%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "1.886"},
|
||||
{"Beta", "1.066"},
|
||||
{"Annual Standard Deviation", "0.155"},
|
||||
{"Annual Variance", "0.024"},
|
||||
{"Information Ratio", "13.528"},
|
||||
{"Tracking Error", "0.142"},
|
||||
{"Treynor Ratio", "2.237"},
|
||||
{"Alpha", "2.663"},
|
||||
{"Beta", "1.264"},
|
||||
{"Annual Standard Deviation", "0.184"},
|
||||
{"Annual Variance", "0.034"},
|
||||
{"Information Ratio", "16.514"},
|
||||
{"Tracking Error", "0.169"},
|
||||
{"Treynor Ratio", "2.574"},
|
||||
{"Total Fees", "$3.57"},
|
||||
{"Estimated Strategy Capacity", "$760000.00"},
|
||||
{"Lowest Capacity Asset", "ES XCZJLDQX7338|ES XCZJLC9NOB29"},
|
||||
{"Portfolio Turnover", "32.31%"},
|
||||
{"Estimated Strategy Capacity", "$28000000.00"},
|
||||
{"Lowest Capacity Asset", "ES XCZJLCA62LNO|ES XCZJLC9NOB29"},
|
||||
{"Portfolio Turnover", "33.84%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "9179c6e6a693a6593c97bfa825d53170"}
|
||||
{"OrderListHash", "7c82013ecabca41591e0253a477025dd"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 1658168;
|
||||
public long DataPoints => 2349547;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
SetEndDate(2013, 10, 10);
|
||||
|
||||
var SP500 = QuantConnect.Symbol.Create(Futures.Indices.SP500EMini, SecurityType.Future, Market.CME);
|
||||
_symbol = FuturesChain(SP500).First();
|
||||
_symbol = FuturesChain(SP500).OrderBy(x => x.Symbol.ID.Date).First();
|
||||
|
||||
// Test case: custom IndicatorBase<QuoteBar> indicator using Future unsubscribed symbol
|
||||
var indicator1 = new CustomIndicator();
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 5861;
|
||||
public virtual long DataPoints => 5867;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -144,34 +144,34 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// </summary>
|
||||
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "34"},
|
||||
{"Total Orders", "38"},
|
||||
{"Average Win", "0.33%"},
|
||||
{"Average Loss", "-0.04%"},
|
||||
{"Compounding Annual Return", "0.106%"},
|
||||
{"Average Loss", "-0.03%"},
|
||||
{"Compounding Annual Return", "0.098%"},
|
||||
{"Drawdown", "0.300%"},
|
||||
{"Expectancy", "0.178"},
|
||||
{"Expectancy", "0.165"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "1001066.2"},
|
||||
{"Net Profit", "0.107%"},
|
||||
{"Sharpe Ratio", "-1.695"},
|
||||
{"Sortino Ratio", "-0.804"},
|
||||
{"Probabilistic Sharpe Ratio", "14.797%"},
|
||||
{"Loss Rate", "88%"},
|
||||
{"Win Rate", "12%"},
|
||||
{"Profit-Loss Ratio", "9.01"},
|
||||
{"End Equity", "1000991.96"},
|
||||
{"Net Profit", "0.099%"},
|
||||
{"Sharpe Ratio", "-1.708"},
|
||||
{"Sortino Ratio", "-0.84"},
|
||||
{"Probabilistic Sharpe Ratio", "14.542%"},
|
||||
{"Loss Rate", "89%"},
|
||||
{"Win Rate", "11%"},
|
||||
{"Profit-Loss Ratio", "10.07"},
|
||||
{"Alpha", "-0.007"},
|
||||
{"Beta", "0.002"},
|
||||
{"Annual Standard Deviation", "0.004"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-1.353"},
|
||||
{"Information Ratio", "-1.354"},
|
||||
{"Tracking Error", "0.089"},
|
||||
{"Treynor Ratio", "-4.112"},
|
||||
{"Total Fees", "$76.30"},
|
||||
{"Treynor Ratio", "-4.054"},
|
||||
{"Total Fees", "$85.54"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "ES VRJST036ZY0X"},
|
||||
{"Portfolio Turnover", "0.92%"},
|
||||
{"Portfolio Turnover", "1.04%"},
|
||||
{"Drawdown Recovery", "69"},
|
||||
{"OrderListHash", "ddaa9dd20647fdbc4811d6e64bb30a40"}
|
||||
{"OrderListHash", "eafc33ea4dcb219f7aacdbdd0973d5bc"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 25312;
|
||||
public override long DataPoints => 25339;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
@@ -70,7 +70,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Lowest Capacity Asset", "ES VP274HSU1AF5"},
|
||||
{"Portfolio Turnover", "20.14%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "f6482c8757f82cb9f4c058e3ed6bc494"}
|
||||
{"OrderListHash", "c301a0a086f8905b1a555f0257087272"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,41 +36,41 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 5965;
|
||||
public override long DataPoints => 5971;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "32"},
|
||||
{"Total Orders", "36"},
|
||||
{"Average Win", "0.33%"},
|
||||
{"Average Loss", "-0.04%"},
|
||||
{"Compounding Annual Return", "0.110%"},
|
||||
{"Average Loss", "-0.03%"},
|
||||
{"Compounding Annual Return", "0.103%"},
|
||||
{"Drawdown", "0.300%"},
|
||||
{"Expectancy", "0.184"},
|
||||
{"Expectancy", "0.172"},
|
||||
{"Start Equity", "1000000"},
|
||||
{"End Equity", "1001108"},
|
||||
{"Net Profit", "0.111%"},
|
||||
{"Sharpe Ratio", "-1.688"},
|
||||
{"Sortino Ratio", "-0.772"},
|
||||
{"Probabilistic Sharpe Ratio", "14.944%"},
|
||||
{"Loss Rate", "88%"},
|
||||
{"Win Rate", "12%"},
|
||||
{"Profit-Loss Ratio", "8.47"},
|
||||
{"End Equity", "1001033.76"},
|
||||
{"Net Profit", "0.103%"},
|
||||
{"Sharpe Ratio", "-1.701"},
|
||||
{"Sortino Ratio", "-0.809"},
|
||||
{"Probabilistic Sharpe Ratio", "14.685%"},
|
||||
{"Loss Rate", "89%"},
|
||||
{"Win Rate", "11%"},
|
||||
{"Profit-Loss Ratio", "9.55"},
|
||||
{"Alpha", "-0.007"},
|
||||
{"Beta", "0.002"},
|
||||
{"Annual Standard Deviation", "0.004"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-1.353"},
|
||||
{"Tracking Error", "0.089"},
|
||||
{"Treynor Ratio", "-4.099"},
|
||||
{"Total Fees", "$72.00"},
|
||||
{"Treynor Ratio", "-4.042"},
|
||||
{"Total Fees", "$81.24"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "ES VRJST036ZY0X"},
|
||||
{"Portfolio Turnover", "0.87%"},
|
||||
{"Portfolio Turnover", "0.99%"},
|
||||
{"Drawdown Recovery", "69"},
|
||||
{"OrderListHash", "741a26424d2210171ad849d92fc75d23"}
|
||||
{"OrderListHash", "67120ad5c9a6116001dda6c8061e5353"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 67924;
|
||||
public override long DataPoints => 67998;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
// set our strike/expiry filter for this option chain
|
||||
option.SetFilter(u => u.Strikes(-2, +2)
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
|
||||
// Expiration method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
.Expiration(0, 180));
|
||||
@@ -73,7 +73,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var higherStrike = callContracts[2].Strike;
|
||||
|
||||
var optionStrategy = OptionStrategies.CallButterfly(_optionSymbol, higherStrike, middleStrike, lowerStrike, expiry);
|
||||
|
||||
|
||||
Order(optionStrategy, 10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +50,9 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
// set our strike/expiry filter for this option chain
|
||||
// SetFilter method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
option.SetFilter(-2, +2, 0, 180);
|
||||
// option.SetFilter(-2, +2, TimeSpan.Zero, TimeSpan.FromDays(180));
|
||||
option.SetFilter(u => u.StandardsOnly()
|
||||
.Strikes(-2, +2)
|
||||
.Expiration(0, 180));
|
||||
|
||||
// Adding this to reproduce GH issue #2314
|
||||
SetWarmup(TimeSpan.FromMinutes(1));
|
||||
@@ -83,7 +84,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
Liquidate();
|
||||
}
|
||||
|
||||
foreach(var kpv in slice.Bars)
|
||||
foreach (var kpv in slice.Bars)
|
||||
{
|
||||
Log($"---> OnData: {Time}, {kpv.Key.Value}, {kpv.Value.Close:0.00}");
|
||||
}
|
||||
|
||||
@@ -48,11 +48,10 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
// set our strike/expiry filter for this option chain
|
||||
option.SetFilter(u => u.Strikes(-2, +2)
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
|
||||
// Expiration method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
.Expiration(0, 180));
|
||||
// .Expiration(TimeSpan.Zero, TimeSpan.FromDays(180)));
|
||||
.Expiration(0, 180)); // .Expiration(TimeSpan.Zero, TimeSpan.FromDays(180)));
|
||||
|
||||
// use the underlying equity as the benchmark
|
||||
SetBenchmark(equity.Symbol);
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
// set our strike/expiry filter for this option chain
|
||||
option.SetFilter(u => u.Strikes(-2, +2)
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
|
||||
// Expiration method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
.Expiration(0, 180));
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var option = AddOption(equity.Symbol, fillForward: true);
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(u => u.Strikes(-2, +2)
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
|
||||
.Expiration(0, 180));
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var option = AddOption(equity.Symbol, fillForward: true);
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(u => u.Strikes(-2, +2)
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
|
||||
.Expiration(0, 180));
|
||||
}
|
||||
|
||||
@@ -243,8 +243,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
}
|
||||
if (orderEvent.Quantity != order.Quantity)
|
||||
{
|
||||
throw new RegressionTestException($@"OrderEvent quantity should hold the current order Quantity. Got {orderEvent.Quantity
|
||||
}, expected {order.Quantity}");
|
||||
throw new RegressionTestException($@"OrderEvent quantity should hold the current order Quantity. Got {orderEvent.Quantity}, expected {order.Quantity}");
|
||||
}
|
||||
if (order is ComboLegLimitOrder && orderEvent.LimitPrice == 0)
|
||||
{
|
||||
@@ -303,8 +302,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
throw new RegressionTestException(
|
||||
"There were expected 6 filled market orders, 3 filled combo limit orders and 6 filled combo leg limit orders, " +
|
||||
$@"but there were {filledComboMarketOrders.Count} filled market orders, {filledComboLimitOrders.Count
|
||||
} filled combo limit orders and {filledComboLegLimitOrders.Count} filled combo leg limit orders");
|
||||
$@"but there were {filledComboMarketOrders.Count} filled market orders, {filledComboLimitOrders.Count} filled combo limit orders and {filledComboLegLimitOrders.Count} filled combo leg limit orders");
|
||||
}
|
||||
|
||||
if (openOrders.Count != 0 || openOrderTickets.Count != 0)
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
SetEndDate(2020, 01, 20);
|
||||
|
||||
var SP500 = QuantConnect.Symbol.Create(Futures.Indices.SP500EMini, SecurityType.Future, Market.CME);
|
||||
var symbol = FuturesChain(SP500).First();
|
||||
var symbol = FuturesChain(SP500).OrderBy(x => x.Symbol.ID.Date).First();
|
||||
_future = AddFutureContract(symbol);
|
||||
|
||||
var tradableDatesCount = QuantConnect.Time.EachTradeableDayInTimeZone(_future.Exchange.Hours,
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var option = AddOption(equity.Symbol);
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(u => u.Strikes(-1, +1).Expiration(0, 30));
|
||||
option.SetFilter(u => u.StandardsOnly().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.
|
||||
@@ -70,7 +70,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var legs = new List<Leg> { Leg.Create(atmContract.Symbol, -1), Leg.Create(atmContract.Symbol.Underlying, 100) };
|
||||
|
||||
var comboPrice = underlyingPrice - optionPrice;
|
||||
if(comboPrice < 734m)
|
||||
if (comboPrice < 734m)
|
||||
{
|
||||
// just to make sure the price makes sense
|
||||
throw new RegressionTestException($"Unexpected combo price {comboPrice}");
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
SetEndDate(2014, 07, 06);
|
||||
|
||||
var option = AddOption("AAPL", Resolution.Daily);
|
||||
option.SetFilter(-5, +5, 0, 365);
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-5, +5).Expiration(0, 365));
|
||||
|
||||
_symbol = option.Symbol;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 70735;
|
||||
public long DataPoints => 70736;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm asserting that a future contract selected by both the continuous future and
|
||||
/// the future chain universes gets liquidated on delisting and that the algorithm receives the correct
|
||||
/// security addition/removal notifications.
|
||||
///
|
||||
/// This algorithm uses Gold futures with midnight expiry time to reproduce an edge case where
|
||||
/// the delisting data instance and the universe deselection happen in the same loop but without a particular order.
|
||||
///
|
||||
/// This partly reproduces GH issue https://github.com/QuantConnect/Lean/issues/9092
|
||||
/// </summary>
|
||||
public class DelistedFutureLiquidateFromChainAndContinuousMidnightExpiryRegressionAlgorithm : DelistedFutureLiquidateFromChainAndContinuousRegressionAlgorithm
|
||||
{
|
||||
protected override string FutureTicker => Futures.Metals.Gold;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public override long DataPoints => 317492;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-5.18%"},
|
||||
{"Compounding Annual Return", "-20.700%"},
|
||||
{"Drawdown", "6.400%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "94817.53"},
|
||||
{"Net Profit", "-5.182%"},
|
||||
{"Sharpe Ratio", "-2.965"},
|
||||
{"Sortino Ratio", "-3.407"},
|
||||
{"Probabilistic Sharpe Ratio", "0.000%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.064"},
|
||||
{"Beta", "-0.2"},
|
||||
{"Annual Standard Deviation", "0.048"},
|
||||
{"Annual Variance", "0.002"},
|
||||
{"Information Ratio", "-4.899"},
|
||||
{"Tracking Error", "0.11"},
|
||||
{"Treynor Ratio", "0.716"},
|
||||
{"Total Fees", "$2.47"},
|
||||
{"Estimated Strategy Capacity", "$1400000.00"},
|
||||
{"Lowest Capacity Asset", "GC VL5E74HP3EE5"},
|
||||
{"Portfolio Turnover", "3.18%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "c197fe000cd6d7f2fd84860f7086d730"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Future;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm asserting that a future contract selected by both the continuous future and
|
||||
/// the future chain universes gets liquidated on delisting and that the algorithm receives the correct
|
||||
/// security addition/removal notifications.
|
||||
///
|
||||
/// This partly reproduces GH issue https://github.com/QuantConnect/Lean/issues/9092
|
||||
/// </summary>
|
||||
public class DelistedFutureLiquidateFromChainAndContinuousRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _contractSymbol;
|
||||
|
||||
private Future _continuousFuture;
|
||||
|
||||
private DateTime _internalContractRemovalTime;
|
||||
private DateTime _contractRemovalTime;
|
||||
|
||||
protected virtual string FutureTicker => Futures.Indices.SP500EMini;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 08);
|
||||
SetEndDate(2013, 12, 30);
|
||||
|
||||
_continuousFuture = AddFuture(FutureTicker);
|
||||
_continuousFuture.SetFilter(0, 182);
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (_contractSymbol == null)
|
||||
{
|
||||
foreach (var chain in slice.FutureChains)
|
||||
{
|
||||
// Make sure the mapped contract is in the chain, that is, is selected by both universes
|
||||
if (chain.Value.Any(x => x.Symbol == _continuousFuture.Mapped))
|
||||
{
|
||||
_contractSymbol = _continuousFuture.Mapped;
|
||||
var ticket = MarketOrder(_contractSymbol, 1);
|
||||
|
||||
if (ticket.Status != OrderStatus.Filled)
|
||||
{
|
||||
throw new RegressionTestException($"Order should be filled: {ticket}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
if (changes.RemovedSecurities.Any(x => x.Symbol == _contractSymbol))
|
||||
{
|
||||
if (_contractRemovalTime != default)
|
||||
{
|
||||
throw new RegressionTestException($"Contract {_contractSymbol} was removed multiple times");
|
||||
}
|
||||
_contractRemovalTime = Time;
|
||||
}
|
||||
else
|
||||
{
|
||||
changes.FilterInternalSecurities = false;
|
||||
if (changes.RemovedSecurities.Any(x => x.Symbol == _contractSymbol))
|
||||
{
|
||||
if (_internalContractRemovalTime != default)
|
||||
{
|
||||
throw new RegressionTestException($"Contract {_contractSymbol} was removed multiple times as internal subscription");
|
||||
}
|
||||
_internalContractRemovalTime = Time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (_contractSymbol == null)
|
||||
{
|
||||
throw new RegressionTestException("No contract was ever traded");
|
||||
}
|
||||
|
||||
if (_internalContractRemovalTime == default)
|
||||
{
|
||||
throw new RegressionTestException($"Contract {_contractSymbol} was not removed from the algorithm");
|
||||
}
|
||||
|
||||
if (_contractRemovalTime == default)
|
||||
{
|
||||
throw new RegressionTestException($"Contract {_contractSymbol} was not removed from the algorithm as external subscription");
|
||||
}
|
||||
|
||||
// The internal subscription should be removed first (on continuous future mapping),
|
||||
// and the regular subscription later (on delisting)
|
||||
if (_contractRemovalTime < _internalContractRemovalTime)
|
||||
{
|
||||
throw new RegressionTestException($"Contract {_contractSymbol} was removed from the algorithm as aregular subscription before internal subscription");
|
||||
}
|
||||
|
||||
if (Securities[_contractSymbol].Invested)
|
||||
{
|
||||
throw new RegressionTestException($"Position should be closed when {_contractSymbol} got delisted {_contractSymbol.ID.Date}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Log($"{orderEvent}. Delisting on: {_contractSymbol.ID.Date}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public virtual long DataPoints => 288140;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "7.02%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "34.386%"},
|
||||
{"Drawdown", "1.500%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "107016.6"},
|
||||
{"Net Profit", "7.017%"},
|
||||
{"Sharpe Ratio", "3.217"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "99.828%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.228"},
|
||||
{"Beta", "0.108"},
|
||||
{"Annual Standard Deviation", "0.084"},
|
||||
{"Annual Variance", "0.007"},
|
||||
{"Information Ratio", "-1.122"},
|
||||
{"Tracking Error", "0.112"},
|
||||
{"Treynor Ratio", "2.501"},
|
||||
{"Total Fees", "$2.15"},
|
||||
{"Estimated Strategy Capacity", "$1700000000.00"},
|
||||
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
|
||||
{"Portfolio Turnover", "2.01%"},
|
||||
{"Drawdown Recovery", "16"},
|
||||
{"OrderListHash", "640ce720644ff0b580687e80105d0a92"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities;
|
||||
@@ -30,6 +31,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public class DelistedFutureLiquidateRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _contractSymbol;
|
||||
private bool _contractRemoved;
|
||||
protected virtual Resolution Resolution => Resolution.Minute;
|
||||
|
||||
/// <summary>
|
||||
@@ -65,8 +67,21 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
if (changes.RemovedSecurities.Any(x => x.Symbol == _contractSymbol))
|
||||
{
|
||||
_contractRemoved = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_contractRemoved)
|
||||
{
|
||||
throw new RegressionTestException($"Contract {_contractSymbol} was not removed from the algorithm");
|
||||
}
|
||||
|
||||
Log($"{_contractSymbol}: {Securities[_contractSymbol].Invested}");
|
||||
if (Securities[_contractSymbol].Invested)
|
||||
{
|
||||
|
||||
@@ -146,10 +146,10 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Treynor Ratio", "-15.266"},
|
||||
{"Total Fees", "$11.36"},
|
||||
{"Estimated Strategy Capacity", "$65000000.00"},
|
||||
{"Lowest Capacity Asset", "ES XCZJLDQX7338|ES XCZJLC9NOB29"},
|
||||
{"Lowest Capacity Asset", "ES XCZJLDQR8R1G|ES XCZJLC9NOB29"},
|
||||
{"Portfolio Turnover", "0.16%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "48b7918176ec22534969502849fe596b"}
|
||||
{"OrderListHash", "f9210adc1afc4460146528006675e734"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Lowest Capacity Asset", "IBM R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "39.89%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "32f56b0f4e9300ef1a34464e8083c7e7"}
|
||||
{"OrderListHash", "d2af4746a4d01ca4d0ce0b0c44f30451"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,33 +160,33 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0.68%"},
|
||||
{"Average Win", "2.19%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "24.075%"},
|
||||
{"Drawdown", "1.900%"},
|
||||
{"Compounding Annual Return", "100.016%"},
|
||||
{"Drawdown", "3.600%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "200000"},
|
||||
{"End Equity", "201354"},
|
||||
{"Net Profit", "0.677%"},
|
||||
{"Sharpe Ratio", "5.76"},
|
||||
{"End Equity", "204384"},
|
||||
{"Net Profit", "2.192%"},
|
||||
{"Sharpe Ratio", "9.169"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "89.644%"},
|
||||
{"Probabilistic Sharpe Ratio", "92.918%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.946"},
|
||||
{"Beta", "-0.354"},
|
||||
{"Annual Standard Deviation", "0.123"},
|
||||
{"Annual Variance", "0.015"},
|
||||
{"Information Ratio", "0.211"},
|
||||
{"Tracking Error", "0.176"},
|
||||
{"Treynor Ratio", "-2.004"},
|
||||
{"Alpha", "3.002"},
|
||||
{"Beta", "-0.818"},
|
||||
{"Annual Standard Deviation", "0.268"},
|
||||
{"Annual Variance", "0.072"},
|
||||
{"Information Ratio", "5.749"},
|
||||
{"Tracking Error", "0.31"},
|
||||
{"Treynor Ratio", "-2.999"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$1700000.00"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3HB9YI6|SPX 31"},
|
||||
{"Portfolio Turnover", "0.35%"},
|
||||
{"Estimated Strategy Capacity", "$420000.00"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
|
||||
{"Portfolio Turnover", "2.37%"},
|
||||
{"Drawdown Recovery", "10"},
|
||||
{"OrderListHash", "d671fe71272a6c1b489d09071967a5de"}
|
||||
{"OrderListHash", "0d2ccc2fdfa2b81bf71361c8248c4a59"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "0.07%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "098dfba7feaa7389ceb7630aa7da2cfa"}
|
||||
{"OrderListHash", "baab871855df123de17fb010951f55da"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 454078;
|
||||
public long DataPoints => 455371;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
|
||||
@@ -163,33 +163,33 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "3"},
|
||||
{"Average Win", "0.68%"},
|
||||
{"Average Win", "2.19%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "10.046%"},
|
||||
{"Drawdown", "1.900%"},
|
||||
{"Compounding Annual Return", "36.041%"},
|
||||
{"Drawdown", "3.600%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "200000"},
|
||||
{"End Equity", "201353"},
|
||||
{"Net Profit", "0.676%"},
|
||||
{"Sharpe Ratio", "3.253"},
|
||||
{"End Equity", "204383"},
|
||||
{"Net Profit", "2.192%"},
|
||||
{"Sharpe Ratio", "4.088"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "86.292%"},
|
||||
{"Probabilistic Sharpe Ratio", "89.872%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0.081"},
|
||||
{"Annual Variance", "0.007"},
|
||||
{"Information Ratio", "3.284"},
|
||||
{"Tracking Error", "0.081"},
|
||||
{"Annual Standard Deviation", "0.177"},
|
||||
{"Annual Variance", "0.031"},
|
||||
{"Information Ratio", "4.102"},
|
||||
{"Tracking Error", "0.177"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$1.00"},
|
||||
{"Estimated Strategy Capacity", "$1700000.00"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3HB9YI6|SPX 31"},
|
||||
{"Portfolio Turnover", "0.16%"},
|
||||
{"Estimated Strategy Capacity", "$420000.00"},
|
||||
{"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"},
|
||||
{"Portfolio Turnover", "1.09%"},
|
||||
{"Drawdown Recovery", "10"},
|
||||
{"OrderListHash", "be2eef3af814d254879e4c6902d9eb9c"}
|
||||
{"OrderListHash", "e913c917ccb2641d70e8fffb47df4f02"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var option = AddOption("GOOG");
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(-2, +2, 0, 180);
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 52987;
|
||||
public long DataPoints => 50978;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -133,31 +133,31 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "120.870%"},
|
||||
{"Drawdown", "3.700%"},
|
||||
{"Compounding Annual Return", "-9.298%"},
|
||||
{"Drawdown", "2.500%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "101091.4"},
|
||||
{"Net Profit", "1.091%"},
|
||||
{"Sharpe Ratio", "4.261"},
|
||||
{"Sortino Ratio", "29.094"},
|
||||
{"Probabilistic Sharpe Ratio", "58.720%"},
|
||||
{"End Equity", "99866.4"},
|
||||
{"Net Profit", "-0.134%"},
|
||||
{"Sharpe Ratio", "1.959"},
|
||||
{"Sortino Ratio", "4.863"},
|
||||
{"Probabilistic Sharpe Ratio", "53.257%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "1.134"},
|
||||
{"Beta", "1.285"},
|
||||
{"Annual Standard Deviation", "0.314"},
|
||||
{"Annual Variance", "0.098"},
|
||||
{"Information Ratio", "15.222"},
|
||||
{"Tracking Error", "0.077"},
|
||||
{"Treynor Ratio", "1.04"},
|
||||
{"Alpha", "0.239"},
|
||||
{"Beta", "0.695"},
|
||||
{"Annual Standard Deviation", "0.178"},
|
||||
{"Annual Variance", "0.032"},
|
||||
{"Information Ratio", "2.059"},
|
||||
{"Tracking Error", "0.093"},
|
||||
{"Treynor Ratio", "0.501"},
|
||||
{"Total Fees", "$4.30"},
|
||||
{"Estimated Strategy Capacity", "$39000000.00"},
|
||||
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
|
||||
{"Portfolio Turnover", "33.59%"},
|
||||
{"Drawdown Recovery", "3"},
|
||||
{"OrderListHash", "8286cb0dd42649527c2c0032ee00e2bd"}
|
||||
{"Estimated Strategy Capacity", "$25000000.00"},
|
||||
{"Lowest Capacity Asset", "ES VU1EHIDJYLMP"},
|
||||
{"Portfolio Turnover", "33.58%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "5a14a3f8b50e3117d87c69d6b11102fc"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
SetCash(500000);
|
||||
|
||||
var option = AddOption("GOOG");
|
||||
option.SetFilter(universe => universe.Strikes(-3, 3).Expiration(0, 180));
|
||||
option.SetFilter(universe => universe.StandardsOnly().Strikes(-3, 3).Expiration(0, 180));
|
||||
|
||||
_symbol = option.Symbol;
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "0.02%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "dafe02af29d6a320da2e5dad28411559"}
|
||||
{"OrderListHash", "9d53c0501981b8d3aa922bbc45b6e80f"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "0.02%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "8940204f430a8040b372cc22d80f1399"}
|
||||
{"OrderListHash", "e1d37155b945867337ae64a1807bf0ce"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 52987;
|
||||
public long DataPoints => 50978;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
@@ -110,31 +110,31 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Total Orders", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "113.036%"},
|
||||
{"Drawdown", "3.700%"},
|
||||
{"Compounding Annual Return", "-0.626%"},
|
||||
{"Drawdown", "2.400%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "101041.4"},
|
||||
{"Net Profit", "1.041%"},
|
||||
{"Sharpe Ratio", "4.262"},
|
||||
{"Sortino Ratio", "29.102"},
|
||||
{"Probabilistic Sharpe Ratio", "58.720%"},
|
||||
{"End Equity", "99991.4"},
|
||||
{"Net Profit", "-0.009%"},
|
||||
{"Sharpe Ratio", "1.959"},
|
||||
{"Sortino Ratio", "4.862"},
|
||||
{"Probabilistic Sharpe Ratio", "53.257%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "1.135"},
|
||||
{"Beta", "1.285"},
|
||||
{"Annual Standard Deviation", "0.314"},
|
||||
{"Annual Variance", "0.098"},
|
||||
{"Information Ratio", "15.206"},
|
||||
{"Tracking Error", "0.078"},
|
||||
{"Treynor Ratio", "1.04"},
|
||||
{"Alpha", "0.239"},
|
||||
{"Beta", "0.694"},
|
||||
{"Annual Standard Deviation", "0.177"},
|
||||
{"Annual Variance", "0.031"},
|
||||
{"Information Ratio", "2.05"},
|
||||
{"Tracking Error", "0.093"},
|
||||
{"Treynor Ratio", "0.501"},
|
||||
{"Total Fees", "$4.30"},
|
||||
{"Estimated Strategy Capacity", "$12000000.00"},
|
||||
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
|
||||
{"Portfolio Turnover", "33.61%"},
|
||||
{"Estimated Strategy Capacity", "$15000000.00"},
|
||||
{"Lowest Capacity Asset", "ES VU1EHIDJYLMP"},
|
||||
{"Portfolio Turnover", "33.51%"},
|
||||
{"Drawdown Recovery", "3"},
|
||||
{"OrderListHash", "1a8899e6c1498f63634de38910878619"}
|
||||
{"OrderListHash", "523d76e17b23ee0c94ded9f826cb8c22"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var option = AddOption("GOOG");
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(-2, +2, 0, 180);
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
|
||||
|
||||
SetBenchmark("GOOG");
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var option = AddOption(UnderlyingTicker);
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(u => u.Strikes(-2, +2).Expiration(0, 180 * 3));
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180 * 3));
|
||||
|
||||
SetBenchmark(equity.Symbol);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var option = AddOption(equity.Symbol);
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(-2, +2, 0, 180);
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var option = AddOption(equity.Symbol);
|
||||
OptionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(u => u.Strikes(-2, +2).Expiration(0, 180));
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
|
||||
}
|
||||
|
||||
protected virtual void OverrideMarginModels()
|
||||
@@ -75,7 +75,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
.ThenBy(x => x.Strike)
|
||||
.First();
|
||||
|
||||
if(!_placedTrades)
|
||||
if (!_placedTrades)
|
||||
{
|
||||
_placedTrades = true;
|
||||
PlaceTrades(atmContracts);
|
||||
@@ -100,7 +100,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected position group count {Portfolio.Positions.Groups.Count} for symbol {ticket.Symbol} and quantity {ticket.Quantity}");
|
||||
}
|
||||
if(Portfolio.TotalMarginUsed != expectedMarginUsed)
|
||||
if (Portfolio.TotalMarginUsed != expectedMarginUsed)
|
||||
{
|
||||
throw new RegressionTestException($"Unexpected margin used {expectedMarginUsed}");
|
||||
}
|
||||
|
||||
@@ -133,10 +133,10 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$9.88"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "GC VMRHKN2NLWV1"},
|
||||
{"Lowest Capacity Asset", "GC VOFJUCDY9XNH"},
|
||||
{"Portfolio Turnover", "1.32%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "cc9ca77de1272050971b5438e757df61"}
|
||||
{"OrderListHash", "4a7e699024771890b97c4ab74365e4b7"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
|
||||
var option = GetOption();
|
||||
|
||||
var optionChainFromAlgorithmApi = OptionChain(option.Symbol).Contracts.Values.Select(x => x.Symbol).ToList();
|
||||
var optionChainFromAlgorithmApi = OptionChain(option.Symbol).Contracts.Keys.ToList();
|
||||
|
||||
var exchangeTime = UtcTime.ConvertFromUtc(option.Exchange.TimeZone);
|
||||
var optionChainFromProviderApi = OptionChainProvider.GetOptionContractList(option.Symbol, exchangeTime).ToList();
|
||||
var optionChainFromProviderApi = OptionChainProvider.GetOptionContractList(option.Symbol, exchangeTime).Order().ToList();
|
||||
|
||||
if (optionChainFromAlgorithmApi.Count == 0)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities.Option;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Verifies that weekly option contracts are included when no standard contracts are available.
|
||||
/// </summary>
|
||||
public class OptionChainIncludeWeeklysByDefaultRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Option _option;
|
||||
private Symbol _optionSymbol;
|
||||
private int _weeklyCount;
|
||||
private int _totalCount;
|
||||
|
||||
/// <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(2015, 12, 24);
|
||||
SetEndDate(2015, 12, 24);
|
||||
|
||||
_option = AddOption("GOOG");
|
||||
_optionSymbol = _option.Symbol;
|
||||
|
||||
_option.SetFilter((optionFilter) =>
|
||||
{
|
||||
return optionFilter.Strikes(-8, +8).Expiration(0, 0);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
OptionChain chain;
|
||||
if (slice.OptionChains.TryGetValue(_optionSymbol, out chain))
|
||||
{
|
||||
_totalCount += chain.Contracts.Count;
|
||||
foreach (var contract in chain.Contracts.Values)
|
||||
{
|
||||
if (!OptionSymbol.IsStandard(contract.Symbol))
|
||||
{
|
||||
_weeklyCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (_weeklyCount == 0)
|
||||
{
|
||||
throw new RegressionTestException("No weekly contracts found");
|
||||
}
|
||||
if (_totalCount != _weeklyCount)
|
||||
{
|
||||
throw new RegressionTestException("When no standard option expirations are available, the option chain must fall back to weekly contracts only");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 22702;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100000"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "0"},
|
||||
{"Tracking Error", "0"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Portfolio Turnover", "0%"},
|
||||
{"Drawdown Recovery", "0"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -96,7 +96,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
|
||||
protected override OptionFilterUniverse Filter(OptionFilterUniverse filter)
|
||||
{
|
||||
return filter.BackMonth().Contracts(contracts => contracts.Take(15));
|
||||
return filter.StandardsOnly().BackMonth().Contracts(contracts => contracts.Take(15));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,9 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
SetStartDate(2014, 06, 05);
|
||||
SetEndDate(2014, 06, 09);
|
||||
|
||||
_aaplOption = AddOption("AAPL").Symbol;
|
||||
var option = AddOption("AAPL");
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-1, 1).Expiration(0, 35));
|
||||
_aaplOption = option.Symbol;
|
||||
AddUniverseSelection(new DailyUniverseSelectionModel("MyCustomSelectionModel", time => new[] { "AAPL" }, this));
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <summary>
|
||||
/// Regression algorithm to test the OptionChainedUniverseSelectionModel class
|
||||
/// </summary>
|
||||
public class OptionChainedUniverseSelectionModelRegressionAlgorithm: QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
public class OptionChainedUniverseSelectionModelRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -39,7 +39,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
|
||||
var universe = AddUniverse("my-minute-universe-name", time => new List<string> { "AAPL", "TWX" });
|
||||
|
||||
AddUniverseSelection(new OptionChainedUniverseSelectionModel(universe, u => u.Strikes(-2, +2)
|
||||
AddUniverseSelection(new OptionChainedUniverseSelectionModel(universe, u => u.StandardsOnly().Strikes(-2, +2)
|
||||
// Expiration method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
.Expiration(0, 180)));
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
// set our strike/expiry filter for this option chain
|
||||
option.SetFilter(u => u.Strikes(-2, +2)
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
|
||||
// Expiration method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
.Expiration(0, 180));
|
||||
@@ -83,7 +83,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
spread = security.Price - security.Holdings.AveragePrice;
|
||||
}
|
||||
}
|
||||
else if(security.BidPrice != 0)
|
||||
else if (security.BidPrice != 0)
|
||||
{
|
||||
spread = security.Holdings.AveragePrice - security.Price;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
// set our strike/expiry filter for this option chain
|
||||
option.SetFilter(u => u.Strikes(-1, +1)
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-1, +1)
|
||||
// Expiration method accepts TimeSpan objects or integer for days.
|
||||
// The following statements yield the same filtering criteria
|
||||
.Expiration(0, 60));
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
_aapl = AddEquity("AAPL", Resolution.Minute, extendedMarketHours: true, dataNormalizationMode: DataNormalizationMode.Raw).Symbol;
|
||||
|
||||
var option = AddOption(_aapl, Resolution.Minute);
|
||||
option.SetFilter(-1, +1, 0, 365);
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-1, +1).Expiration(0, 365));
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
|
||||
@@ -30,6 +30,8 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
SetEndDate(2014, 6, 9);
|
||||
|
||||
var option = AddOption("AAPL", Resolution.Minute);
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-1, 1).Expiration(0, 35));
|
||||
|
||||
// BaroneAdesiWhaley model supports American style options
|
||||
option.PriceModel = OptionPriceModels.BaroneAdesiWhaley();
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
SetEndDate(2014, 6, 9);
|
||||
|
||||
var option = AddOption("AAPL", Resolution.Minute);
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-1, 1).Expiration(0, 35));
|
||||
|
||||
// BlackSholes model does not support American style options
|
||||
option.PriceModel = OptionPriceModels.BlackScholes();
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
UniverseSettings.Resolution = Resolution.Daily;
|
||||
|
||||
var option = AddOption("GOOG");
|
||||
option.SetFilter(u => u.Strikes(-2, +2).Expiration(0, 180));
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
if (UniverseManager.TryGetValue(option.Symbol, out var universe)
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var option = AddOption(equitySymbol);
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(u => u.Strikes(-2, +2)
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2)
|
||||
.Expiration(0, 180));
|
||||
|
||||
Portfolio.MarginCallModel = new CustomMarginCallModel(Portfolio, DefaultOrderProperties);
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
SetEndDate(2014, 06, 09);
|
||||
|
||||
var option = AddOption("AAPL");
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-1, 1).Expiration(0, 35));
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
var optionContractSymbol = OptionChain(_optionSymbol)
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var option = AddOption("GOOG");
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(-2, +2, 0, 180);
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
|
||||
|
||||
SetBenchmark("GOOG");
|
||||
}
|
||||
@@ -67,8 +67,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var buyingPowerModel = positionGroup.BuyingPowerModel as OptionStrategyPositionGroupBuyingPowerModel;
|
||||
if (buyingPowerModel == null)
|
||||
{
|
||||
throw new RegressionTestException($@"Expected position group buying power model type: {nameof(OptionStrategyPositionGroupBuyingPowerModel)
|
||||
}. Actual: {positionGroup.BuyingPowerModel.GetType()}");
|
||||
throw new RegressionTestException($@"Expected position group buying power model type: {nameof(OptionStrategyPositionGroupBuyingPowerModel)}. Actual: {positionGroup.BuyingPowerModel.GetType()}");
|
||||
}
|
||||
|
||||
AssertStrategyPositionGroup(positionGroup);
|
||||
@@ -91,9 +90,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var ordersCount = Transactions.GetOrders((order) => order.Status == OrderStatus.Filled).Count();
|
||||
if (ordersCount != ExpectedOrdersCount)
|
||||
{
|
||||
throw new RegressionTestException($@"Expected {ExpectedOrdersCount
|
||||
} orders to have been submitted and filled, half for buying the strategy and the other half for the liquidation. Actual {
|
||||
ordersCount}");
|
||||
throw new RegressionTestException($@"Expected {ExpectedOrdersCount} orders to have been submitted and filled, half for buying the strategy and the other half for the liquidation. Actual {ordersCount}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
|
||||
var option = AddOption(equity.Symbol);
|
||||
|
||||
option.SetFilter(u => u.Strikes(-2, +2).Expiration(0, 180));
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
|
||||
// Subscribe to GOOG Options
|
||||
var option = AddOption("GOOG");
|
||||
option.SetFilter(x => x.CallsOnly().Strikes(0, 1).Expiration(0, 30));
|
||||
option.SetFilter(x => x.StandardsOnly().CallsOnly().Strikes(0, 1).Expiration(0, 30));
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<RootNamespace>QuantConnect.Algorithm.CSharp</RootNamespace>
|
||||
<AssemblyName>QuantConnect.Algorithm.CSharp</AssemblyName>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
|
||||
@@ -32,7 +32,7 @@
|
||||
<DebugType>portable</DebugType>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.50" />
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.52" />
|
||||
<PackageReference Include="Accord" Version="3.6.0" />
|
||||
<PackageReference Include="Accord.Fuzzy" Version="3.6.0" />
|
||||
<PackageReference Include="Accord.MachineLearning" Version="3.6.0" />
|
||||
|
||||
@@ -49,6 +49,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var equitySymbol = AddEquity("GOOG", leverage: 4, fillForward: true).Symbol;
|
||||
_option = AddOption(equitySymbol, fillForward: true);
|
||||
_option.SetFilter(optionFilterUniverse => optionFilterUniverse
|
||||
.StandardsOnly()
|
||||
.Strikes(-2, 2)
|
||||
.Expiration(0, 180));
|
||||
}
|
||||
@@ -136,17 +137,13 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var expectedEntryQuantity = leg.Quantity * _comboQuantity;
|
||||
if (entryOrderTicket.Quantity != expectedEntryQuantity || entryOrderTicket.QuantityFilled != expectedEntryQuantity)
|
||||
{
|
||||
throw new RegressionTestException($@"Entry order ticket quantity and filled quantity do not match expected quantity for leg {i
|
||||
}. Expected: {expectedEntryQuantity}. Actual quantity: {entryOrderTicket.Quantity}. Actual filled quantity: {
|
||||
entryOrderTicket.QuantityFilled}");
|
||||
throw new RegressionTestException($@"Entry order ticket quantity and filled quantity do not match expected quantity for leg {i}. Expected: {expectedEntryQuantity}. Actual quantity: {entryOrderTicket.Quantity}. Actual filled quantity: {entryOrderTicket.QuantityFilled}");
|
||||
}
|
||||
|
||||
var expectedExitQuantity = -expectedEntryQuantity;
|
||||
if (exitOrderTicket.Quantity != expectedExitQuantity || exitOrderTicket.QuantityFilled != expectedExitQuantity)
|
||||
{
|
||||
throw new RegressionTestException($@"Exit order ticket quantity and filled quantity do not match expected quantity for leg {i
|
||||
}. Expected: {expectedExitQuantity}. Actual quantity: {exitOrderTicket.Quantity}. Actual filled quantity: {
|
||||
exitOrderTicket.QuantityFilled}");
|
||||
throw new RegressionTestException($@"Exit order ticket quantity and filled quantity do not match expected quantity for leg {i}. Expected: {expectedExitQuantity}. Actual quantity: {exitOrderTicket.Quantity}. Actual filled quantity: {exitOrderTicket.QuantityFilled}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
SetCash(500000);
|
||||
|
||||
var option = AddOption("GOOG", Resolution.Minute);
|
||||
option.SetFilter(universe => universe.Strikes(-1, 1).Expiration(0, 62));
|
||||
option.SetFilter(universe => universe.StandardsOnly().Strikes(-1, 1).Expiration(0, 62));
|
||||
|
||||
_symbol = option.Symbol;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
SetEndDate(2013, 10, 08);
|
||||
|
||||
Security = AddFuture(Futures.Metals.Gold, Resolution.Minute, extendedMarketHours: ExtendedMarketHours);
|
||||
_futureContract = AddFutureContract(FuturesChain(Security.Symbol).First());
|
||||
_futureContract = AddFutureContract(FuturesChain(Security.Symbol).OrderBy(x => x.Symbol.ID.Date).First());
|
||||
|
||||
// Manually add consolidators to simulate Session behavior
|
||||
_continuousContractConsolidator = new MarketHourAwareConsolidator(false, Resolution.Daily, typeof(QuoteBar), TickType.Quote, false);
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
var option = AddOption(equitySymbol);
|
||||
_optionSymbol = option.Symbol;
|
||||
|
||||
option.SetFilter(u => u.Strikes(-2, +2).Expiration(0, 180));
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-2, +2).Expiration(0, 180));
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
@@ -124,8 +124,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
|
||||
if (positionQuantityForDeltaWithPositionGroupBuyingPowerModel != expectedQuantity)
|
||||
{
|
||||
throw new RegressionTestException($@"Expected position quantity for delta buying power to be {expectedQuantity} but was {
|
||||
positionQuantityForDeltaWithPositionGroupBuyingPowerModel}");
|
||||
throw new RegressionTestException($@"Expected position quantity for delta buying power to be {expectedQuantity} but was {positionQuantityForDeltaWithPositionGroupBuyingPowerModel}");
|
||||
}
|
||||
|
||||
var position = positionGroup.Positions.Single();
|
||||
@@ -144,8 +143,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
if (positionQuantityForDeltaWithSecurityPositionGroupBuyingPowerModel != expectedSingleSecurityModelsQuantity ||
|
||||
positionQuantityForDeltaWithSecurityBuyingPowerModel != expectedSingleSecurityModelsQuantity)
|
||||
{
|
||||
throw new RegressionTestException($@"Expected order quantity for delta buying power calls from default buying power models to return {
|
||||
expectedSingleSecurityModelsQuantity}. Results were:" +
|
||||
throw new RegressionTestException($@"Expected order quantity for delta buying power calls from default buying power models to return {expectedSingleSecurityModelsQuantity}. Results were:" +
|
||||
$" \nSecurityPositionGroupBuyingPowerModel: {positionQuantityForDeltaWithSecurityPositionGroupBuyingPowerModel}" +
|
||||
$" \nBuyingPowerModel: {positionQuantityForDeltaWithSecurityBuyingPowerModel}\n");
|
||||
}
|
||||
|
||||
@@ -54,7 +54,8 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
if (Time.Hour == 9 && Time.Minute == 58)
|
||||
{
|
||||
AddOption(UnderlyingTicker);
|
||||
var option = AddOption(UnderlyingTicker);
|
||||
option.SetFilter(u => u.StandardsOnly().Strikes(-1, 1).Expiration(0, 35));
|
||||
}
|
||||
|
||||
AssertValue(slice);
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data.Fundamental;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression test algorithm for scheduled universe selection GH 3890
|
||||
/// </summary>
|
||||
public class YearlyUniverseSelectionScheduleRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private int _yearlyDateSelection;
|
||||
private readonly Symbol _symbol = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2014, 03, 25);
|
||||
SetEndDate(2014, 05, 10);
|
||||
UniverseSettings.Resolution = Resolution.Daily;
|
||||
|
||||
AddUniverse(DateRules.YearStart(), SelectionFunction);
|
||||
}
|
||||
|
||||
public IEnumerable<Symbol> SelectionFunction(IEnumerable<Fundamental> coarse)
|
||||
{
|
||||
_yearlyDateSelection++;
|
||||
if (Time != StartDate)
|
||||
{
|
||||
throw new RegressionTestException($"SelectionFunction_SpecificDate unexpected selection: {Time}");
|
||||
}
|
||||
return new[] { _symbol };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="slice">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings(_symbol, 1);
|
||||
Debug($"Purchased Stock {_symbol}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (_yearlyDateSelection != 1)
|
||||
{
|
||||
throw new RegressionTestException($"Initial yearly selection didn't happen!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of all timeslices of algorithm
|
||||
/// </summary>
|
||||
public long DataPoints => 271;
|
||||
|
||||
/// <summary>
|
||||
/// Data Points count of the algorithm history
|
||||
/// </summary>
|
||||
public int AlgorithmHistoryDataPoints => 0;
|
||||
|
||||
/// <summary>
|
||||
/// Final status of the algorithm
|
||||
/// </summary>
|
||||
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public List<Language> Languages { get; } = new() { Language.CSharp };
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Orders", "1"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "4.334%"},
|
||||
{"Drawdown", "3.900%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Start Equity", "100000"},
|
||||
{"End Equity", "100532.22"},
|
||||
{"Net Profit", "0.532%"},
|
||||
{"Sharpe Ratio", "0.28"},
|
||||
{"Sortino Ratio", "0.283"},
|
||||
{"Probabilistic Sharpe Ratio", "39.422%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.022"},
|
||||
{"Beta", "1.018"},
|
||||
{"Annual Standard Deviation", "0.099"},
|
||||
{"Annual Variance", "0.01"},
|
||||
{"Information Ratio", "-2.462"},
|
||||
{"Tracking Error", "0.009"},
|
||||
{"Treynor Ratio", "0.027"},
|
||||
{"Total Fees", "$3.07"},
|
||||
{"Estimated Strategy Capacity", "$920000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Portfolio Turnover", "2.20%"},
|
||||
{"Drawdown Recovery", "5"},
|
||||
{"OrderListHash", "87438e51988f37757a2d7f97389483ea"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -36,17 +36,6 @@ namespace QuantConnect.Algorithm.Framework.Alphas
|
||||
private readonly HashSet<Security> _securities;
|
||||
private readonly Dictionary<Symbol, DateTime> _insightsTimeBySymbol;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConstantAlphaModel"/> class
|
||||
/// </summary>
|
||||
/// <param name="type">The type of insight</param>
|
||||
/// <param name="direction">The direction of the insight</param>
|
||||
/// <param name="period">The period over which the insight with come to fruition</param>
|
||||
public ConstantAlphaModel(InsightType type, InsightDirection direction, TimeSpan period)
|
||||
: this(type, direction, period, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConstantAlphaModel"/> class
|
||||
/// </summary>
|
||||
@@ -56,7 +45,7 @@ namespace QuantConnect.Algorithm.Framework.Alphas
|
||||
/// <param name="magnitude">The predicted change in magnitude as a +- percentage</param>
|
||||
/// <param name="confidence">The confidence in the insight</param>
|
||||
/// <param name="weight">The portfolio weight of the insights</param>
|
||||
public ConstantAlphaModel(InsightType type, InsightDirection direction, TimeSpan period, double? magnitude, double? confidence, double? weight = null)
|
||||
public ConstantAlphaModel(InsightType type, InsightDirection direction, TimeSpan period, double? magnitude = null, double? confidence = null, double? weight = null)
|
||||
{
|
||||
_type = type;
|
||||
_direction = direction;
|
||||
@@ -127,7 +116,7 @@ namespace QuantConnect.Algorithm.Framework.Alphas
|
||||
/// <param name="symbol">The symbol to emit an insight for</param>
|
||||
protected virtual bool ShouldEmitInsight(DateTime utcTime, Symbol symbol)
|
||||
{
|
||||
if(symbol.IsCanonical())
|
||||
if (symbol.IsCanonical())
|
||||
{
|
||||
// canonical futures & options are none tradable
|
||||
return false;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<RootNamespace>QuantConnect.Algorithm.Framework</RootNamespace>
|
||||
<AssemblyName>QuantConnect.Algorithm.Framework</AssemblyName>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
|
||||
@@ -29,7 +29,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.50" />
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.52" />
|
||||
<PackageReference Include="Accord" Version="3.6.0" />
|
||||
<PackageReference Include="Accord.Math" Version="3.6.0" />
|
||||
<PackageReference Include="Accord.Statistics" Version="3.6.0" />
|
||||
|
||||
@@ -17,19 +17,19 @@ class FundamentalUniverseSelectionModel:
|
||||
'''Provides a base class for defining equity coarse/fine fundamental selection models'''
|
||||
|
||||
def __init__(self,
|
||||
filterFineData = None,
|
||||
universeSettings = None):
|
||||
filter_fine_data = None,
|
||||
universe_settings = None):
|
||||
'''Initializes a new instance of the FundamentalUniverseSelectionModel class
|
||||
Args:
|
||||
filterFineData: [Obsolete] Fine and Coarse selection are merged
|
||||
universeSettings: The settings used when adding symbols to the algorithm, specify null to use algorithm.UniverseSettings'''
|
||||
self.filter_fine_data = filterFineData
|
||||
filter_fine_data: [Obsolete] Fine and Coarse selection are merged
|
||||
universeSettings: The settings used when adding symbols to the algorithm, specify null to use algorithm.universe_settings'''
|
||||
self.filter_fine_data = filter_fine_data
|
||||
if self.filter_fine_data == None:
|
||||
self.fundamental_data = True
|
||||
else:
|
||||
self.fundamental_data = False
|
||||
self.market = Market.USA
|
||||
self.universe_settings = universeSettings
|
||||
self.universe_settings = universe_settings
|
||||
|
||||
|
||||
def create_universes(self, algorithm: QCAlgorithm) -> list[Universe]:
|
||||
|
||||
@@ -33,7 +33,7 @@ class BasicTemplateOptionEquityStrategyAlgorithm(QCAlgorithm):
|
||||
self._option_symbol = option.symbol
|
||||
|
||||
# set our strike/expiry filter for this option chain
|
||||
option.set_filter(lambda u: (u.strikes(-2, +2)
|
||||
option.set_filter(lambda u: (u.standards_only().strikes(-2, +2)
|
||||
# Expiration method accepts TimeSpan objects or integer for days.
|
||||
# The following statements yield the same filtering criteria
|
||||
.expiration(0, 180)))
|
||||
|
||||
@@ -39,8 +39,7 @@ class BasicTemplateOptionStrategyAlgorithm(QCAlgorithm):
|
||||
# set our strike/expiry filter for this option chain
|
||||
# SetFilter method accepts timedelta objects or integer for days.
|
||||
# The following statements yield the same filtering criteria
|
||||
option.set_filter(-2, +2, 0, 180)
|
||||
# option.set_filter(-2,2, timedelta(0), timedelta(180))
|
||||
option.set_filter(lambda u: (u.standards_only().strikes(-2, +2).expiration(0, 180)))
|
||||
|
||||
# use the underlying equity as the benchmark
|
||||
self.set_benchmark("GOOG")
|
||||
|
||||
@@ -34,7 +34,7 @@ class BasicTemplateOptionsAlgorithm(QCAlgorithm):
|
||||
self.option_symbol = option.symbol
|
||||
|
||||
# set our strike/expiry filter for this option chain
|
||||
option.set_filter(lambda u: (u.strikes(-2, +2)
|
||||
option.set_filter(lambda u: (u.standards_only().strikes(-2, +2)
|
||||
# Expiration method accepts TimeSpan objects or integer for days.
|
||||
# The following statements yield the same filtering criteria
|
||||
.expiration(0, 180)))
|
||||
|
||||
@@ -34,7 +34,7 @@ class BasicTemplateOptionsHourlyAlgorithm(QCAlgorithm):
|
||||
self.option_symbol = option.symbol
|
||||
|
||||
# set our strike/expiry filter for this option chain
|
||||
option.set_filter(lambda u: (u.strikes(-2, +2)
|
||||
option.set_filter(lambda u: (u.standards_only().strikes(-2, +2)
|
||||
# Expiration method accepts TimeSpan objects or integer for days.
|
||||
# The following statements yield the same filtering criteria
|
||||
.expiration(0, 180)))
|
||||
|
||||
@@ -28,7 +28,7 @@ class ComboOrderTicketDemoAlgorithm(QCAlgorithm):
|
||||
option = self.add_option(equity.symbol, fill_forward=True)
|
||||
self._option_symbol = option.symbol
|
||||
|
||||
option.set_filter(lambda u: u.strikes(-2, +2).expiration(0, 180))
|
||||
option.set_filter(lambda u: u.standards_only().strikes(-2, +2).expiration(0, 180))
|
||||
|
||||
self._open_market_orders = []
|
||||
self._open_leg_limit_orders = []
|
||||
|
||||
@@ -25,7 +25,7 @@ class ConsolidateRegressionAlgorithm(QCAlgorithm):
|
||||
self.set_end_date(2020, 1, 20)
|
||||
|
||||
SP500 = Symbol.create(Futures.Indices.SP_500_E_MINI, SecurityType.FUTURE, Market.CME)
|
||||
symbol = list(self.futures_chain(SP500))[0]
|
||||
symbol = list(sorted(self.futures_chain(SP500).contracts.keys(), key=lambda symbol: symbol.id.date))[0]
|
||||
self._future = self.add_future_contract(symbol)
|
||||
|
||||
tradable_dates_count = len(list(Time.each_tradeable_day_in_time_zone(self._future.exchange.hours,
|
||||
|
||||
@@ -26,7 +26,7 @@ class FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFu
|
||||
self._create_option(datetime(2020, 2, 25), OptionRight.CALL, 1600.0): False,
|
||||
self._create_option(datetime(2020, 2, 25), OptionRight.PUT, 1545.0): False
|
||||
}
|
||||
|
||||
|
||||
# Required for FOPs to use extended hours, until GH #6491 is addressed
|
||||
self.universe_settings.extended_market_hours = True
|
||||
|
||||
@@ -34,9 +34,9 @@ class FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFu
|
||||
self.set_end_date(2020, 1, 6)
|
||||
|
||||
gold_futures = self.add_future("GC", Resolution.MINUTE, Market.COMEX, extended_market_hours=True)
|
||||
gold_futures.SetFilter(0, 365)
|
||||
gold_futures.set_filter(0, 365)
|
||||
|
||||
self.add_future_option(gold_futures.Symbol)
|
||||
self.add_future_option(gold_futures.symbol)
|
||||
|
||||
def on_data(self, data: Slice):
|
||||
for symbol in data.quote_bars.keys():
|
||||
|
||||
@@ -32,7 +32,7 @@ class HistoryAlgorithm(QCAlgorithm):
|
||||
self.add_equity("SPY", Resolution.DAILY)
|
||||
IBM = self.add_data(CustomDataEquity, "IBM", Resolution.DAILY)
|
||||
# specifying the exchange will allow the history methods that accept a number of bars to return to work properly
|
||||
IBM.Exchange = EquityExchange()
|
||||
IBM.exchange = EquityExchange()
|
||||
|
||||
# we can get history in initialize to set up indicators and such
|
||||
self.daily_sma = SimpleMovingAverage(14)
|
||||
@@ -96,7 +96,7 @@ class HistoryAlgorithm(QCAlgorithm):
|
||||
self.assert_history_count("History(CustomDataEquity, self.securities.keys(), 14)", all_custom_data, 14 * 2)
|
||||
|
||||
# NOTE: Using different resolutions require that they are properly implemented in your data type. If your
|
||||
# custom data source has different resolutions, it would need to be implemented in the GetSource and
|
||||
# custom data source has different resolutions, it would need to be implemented in the GetSource and
|
||||
# Reader methods properly.
|
||||
#custom_data_history = self.history(CustomDataEquity, "IBM", timedelta(7), Resolution.MINUTE)
|
||||
#custom_data_history = self.history(CustomDataEquity, "IBM", 14, Resolution.MINUTE)
|
||||
|
||||
@@ -33,7 +33,7 @@ class NullBuyingPowerOptionBullCallSpreadAlgorithm(QCAlgorithm):
|
||||
option = self.add_option(equity.symbol)
|
||||
self.option_symbol = option.symbol
|
||||
|
||||
option.set_filter(-2, 2, 0, 180)
|
||||
option.set_filter(lambda u: u.standards_only().strikes(-2, +2).expiration(0, 180))
|
||||
|
||||
def on_data(self, slice):
|
||||
if self.portfolio.invested or not self.is_market_open(self.option_symbol):
|
||||
|
||||
@@ -32,7 +32,7 @@ class NullMarginMultipleOrdersRegressionAlgorithm(QCAlgorithm):
|
||||
option = self.add_option(equity.symbol, fill_forward=True)
|
||||
self._option_symbol = option.symbol
|
||||
|
||||
option.set_filter(lambda u: u.strikes(-2, +2).expiration(0, 180))
|
||||
option.set_filter(lambda u: u.standards_only().strikes(-2, +2).expiration(0, 180))
|
||||
|
||||
def on_data(self, data: Slice):
|
||||
if not self.portfolio.invested:
|
||||
|
||||
@@ -28,10 +28,10 @@ class OptionChainApisConsistencyRegressionAlgorithm(QCAlgorithm):
|
||||
|
||||
option = self.get_option()
|
||||
|
||||
option_chain_from_algorithm_api = [x.symbol for x in self.option_chain(option.symbol).contracts.values()]
|
||||
option_chain_from_algorithm_api = self.option_chain(option.symbol).contracts.keys()
|
||||
|
||||
exchange_time = Extensions.convert_from_utc(self.utc_time, option.exchange.time_zone)
|
||||
option_chain_from_provider_api = list(self.option_chain_provider.get_option_contract_list(option.symbol, exchange_time))
|
||||
option_chain_from_provider_api = list(sorted(self.option_chain_provider.get_option_contract_list(option.symbol, exchange_time)))
|
||||
|
||||
if len(option_chain_from_algorithm_api) == 0:
|
||||
raise AssertionError("No options in chain from algorithm API")
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from AlgorithmImports import *
|
||||
|
||||
### <summary>
|
||||
### Verifies that weekly option contracts are included when no standard contracts are available.
|
||||
### </summary>
|
||||
class OptionChainIncludeWeeklysByDefaultRegressionAlgorithm(QCAlgorithm):
|
||||
|
||||
def initialize(self):
|
||||
self.set_start_date(2015, 12, 24)
|
||||
self.set_end_date(2015, 12, 24)
|
||||
|
||||
self.option = self.add_option("GOOG")
|
||||
self.option_symbol = self.option.Symbol
|
||||
|
||||
self.option.set_filter(lambda u: u.strikes(-8, 8).expiration(0, 0))
|
||||
|
||||
self.weekly_count = 0
|
||||
self.total_count = 0
|
||||
|
||||
def on_data(self, data):
|
||||
chain = data.option_chains.get(self.option_symbol)
|
||||
if chain:
|
||||
self.total_count += len(chain.contracts)
|
||||
for contract in chain.contracts.values():
|
||||
if not OptionSymbol.is_standard(contract.symbol):
|
||||
self.weekly_count += 1
|
||||
|
||||
def on_end_of_algorithm(self):
|
||||
if self.weekly_count == 0:
|
||||
raise RegressionTestException("No weekly contracts found")
|
||||
|
||||
if self.total_count != self.weekly_count:
|
||||
raise RegressionTestException("When no standard option expirations are available, the option chain must fall back to weekly contracts only")
|
||||
@@ -28,7 +28,7 @@ class OptionChainedUniverseSelectionModelRegressionAlgorithm(QCAlgorithm):
|
||||
self.add_universe_selection(
|
||||
OptionChainedUniverseSelectionModel(
|
||||
universe,
|
||||
lambda u: (u.strikes(-2, +2)
|
||||
lambda u: (u.standards_only().strikes(-2, +2)
|
||||
# Expiration method accepts TimeSpan objects or integer for days.
|
||||
# The following statements yield the same filtering criteria
|
||||
.expiration(0, 180))
|
||||
|
||||
@@ -24,6 +24,8 @@ class OptionPriceModelForSupportedAmericanOptionRegressionAlgorithm(OptionPriceM
|
||||
self.set_end_date(2014, 6, 9)
|
||||
|
||||
option = self.add_option("AAPL", Resolution.MINUTE)
|
||||
option.set_filter(lambda u: u.standards_only().strikes(-1, 1).expiration(0, 35))
|
||||
|
||||
# BaroneAdesiWhaley model supports American style options
|
||||
option.price_model = OptionPriceModels.barone_adesi_whaley()
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ class OptionPriceModelForUnsupportedAmericanOptionRegressionAlgorithm(OptionPric
|
||||
self.set_end_date(2014, 6, 9)
|
||||
|
||||
option = self.add_option("AAPL", Resolution.MINUTE)
|
||||
option.set_filter(lambda u: u.standards_only().strikes(-1, 1).expiration(0, 35))
|
||||
|
||||
# BlackSholes model does not support American style options
|
||||
option.price_model = OptionPriceModels.black_scholes()
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class OptionStrategyFactoryMethodsBaseAlgorithm(QCAlgorithm):
|
||||
option = self.add_option("GOOG")
|
||||
self._option_symbol = option.symbol
|
||||
|
||||
option.set_filter(-2, +2, 0, 180)
|
||||
option.set_filter(lambda u: u.standards_only().strikes(-2, +2).expiration(0, 180))
|
||||
|
||||
self.set_benchmark("GOOG")
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<RootNamespace>QuantConnect.Algorithm.Python</RootNamespace>
|
||||
<AssemblyName>QuantConnect.Algorithm.Python</AssemblyName>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
@@ -37,7 +37,7 @@
|
||||
<Compile Include="..\Common\Properties\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.50" />
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.52" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="OptionUniverseFilterGreeksShortcutsRegressionAlgorithm.py" />
|
||||
|
||||
@@ -20,18 +20,18 @@ class ScheduledQueuingAlgorithm(QCAlgorithm):
|
||||
self.set_start_date(2020, 9, 1)
|
||||
self.set_end_date(2020, 9, 2)
|
||||
self.set_cash(100000)
|
||||
|
||||
|
||||
self.__number_of_symbols = 2000
|
||||
self.__number_of_symbols_fine = 1000
|
||||
self.set_universe_selection(FineFundamentalUniverseSelectionModel(self.coarse_selection_function, self.fine_selection_function, None))
|
||||
|
||||
|
||||
self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
|
||||
|
||||
|
||||
self.set_execution(ImmediateExecutionModel())
|
||||
|
||||
|
||||
self._queue = Queue()
|
||||
self._dequeue_size = 100
|
||||
|
||||
|
||||
self.add_equity("SPY", Resolution.MINUTE)
|
||||
self.schedule.on(self.date_rules.every_day("SPY"), self.time_rules.at(0, 0), self.fill_queue)
|
||||
self.schedule.on(self.date_rules.every_day("SPY"), self.time_rules.every(timedelta(minutes=60)), self.take_from_queue)
|
||||
@@ -40,22 +40,22 @@ class ScheduledQueuingAlgorithm(QCAlgorithm):
|
||||
has_fundamentals = [security for security in coarse if security.has_fundamental_data]
|
||||
sorted_by_dollar_volume = sorted(has_fundamentals, key=lambda x: x.dollar_volume, reverse=True)
|
||||
return [ x.symbol for x in sorted_by_dollar_volume[:self.__number_of_symbols] ]
|
||||
|
||||
|
||||
def fine_selection_function(self, fine: list[FineFundamental]) -> list[Symbol]:
|
||||
sorted_by_pe_ratio = sorted(fine, key=lambda x: x.valuation_ratios.pe_ratio, reverse=True)
|
||||
return [ x.symbol for x in sorted_by_pe_ratio[:self.__number_of_symbols_fine] ]
|
||||
|
||||
|
||||
def fill_queue(self) -> None:
|
||||
securities = [security for security in self.active_securities.values if security.fundamentals]
|
||||
|
||||
securities = [security for security in self.active_securities.values() if security.fundamentals]
|
||||
|
||||
# Fill queue with symbols sorted by PE ratio (decreasing order)
|
||||
self._queue.queue.clear()
|
||||
sorted_by_pe_ratio = sorted(securities, key=lambda x: x.fundamentals.valuation_ratios.pe_ratio, reverse=True)
|
||||
for security in sorted_by_pe_ratio:
|
||||
self._queue.put(security.symbol)
|
||||
|
||||
|
||||
def take_from_queue(self) -> None:
|
||||
symbols = [self._queue.get() for _ in range(min(self._dequeue_size, self._queue.qsize()))]
|
||||
self.history(symbols, 10, Resolution.DAILY)
|
||||
|
||||
|
||||
self.log(f"Symbols at {self.time}: {[str(symbol) for symbol in symbols]}")
|
||||
|
||||
@@ -116,11 +116,10 @@ namespace QuantConnect.Algorithm.Framework.Alphas
|
||||
/// <param name="pyAlphaModel">The alpha model to add</param>
|
||||
public void AddAlpha(PyObject pyAlphaModel)
|
||||
{
|
||||
IAlphaModel alphaModel;
|
||||
if (!pyAlphaModel.TryConvert(out alphaModel))
|
||||
{
|
||||
alphaModel = new AlphaModelPythonWrapper(pyAlphaModel);
|
||||
}
|
||||
var alphaModel = PythonUtil.CreateInstanceOrWrapper<IAlphaModel>(
|
||||
pyAlphaModel,
|
||||
py => new AlphaModelPythonWrapper(py)
|
||||
);
|
||||
_alphaModels.Add(alphaModel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace QuantConnect.Algorithm
|
||||
private readonly IAlgorithm _algorithm;
|
||||
|
||||
/// <summary>
|
||||
/// Universe which selects companies whose revenues and earnings have both been growing significantly faster than
|
||||
/// <see cref="Universe"/> which selects companies whose revenues and earnings have both been growing significantly faster than
|
||||
/// the general economy.
|
||||
/// </summary>
|
||||
public Universe AggressiveGrowth(UniverseSettings universeSettings = null)
|
||||
@@ -40,7 +40,7 @@ namespace QuantConnect.Algorithm
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Universe which selects companies that are growing respectably faster than the general economy, and often pay a
|
||||
/// <see cref="Universe"/> which selects companies that are growing respectably faster than the general economy, and often pay a
|
||||
/// steady dividend. They tend to be mature and solidly profitable businesses.
|
||||
/// </summary>
|
||||
public Universe ClassicGrowth(UniverseSettings universeSettings = null)
|
||||
@@ -51,7 +51,7 @@ namespace QuantConnect.Algorithm
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Universe which selects companies in the cyclicals and durables sectors, except those in the three types below.
|
||||
/// <see cref="Universe"/> which selects companies in the cyclicals and durables sectors, except those in the three types below.
|
||||
/// The profits of cyclicals tend to rise and fall with the general economy.
|
||||
/// </summary>
|
||||
public Universe Cyclicals(UniverseSettings universeSettings = null)
|
||||
@@ -62,7 +62,7 @@ namespace QuantConnect.Algorithm
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Universe which selects companies that have had consistently declining cash flows and earnings over the past
|
||||
/// <see cref="Universe"/> which selects companies that have had consistently declining cash flows and earnings over the past
|
||||
/// three years, and/or very high debt.
|
||||
/// </summary>
|
||||
public Universe Distressed(UniverseSettings universeSettings = null)
|
||||
@@ -73,7 +73,7 @@ namespace QuantConnect.Algorithm
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Universe which selects companies that deal in assets such as oil, metals, and real estate, which tend to do
|
||||
/// <see cref="Universe"/> which selects companies that deal in assets such as oil, metals, and real estate, which tend to do
|
||||
/// well in inflationary environments.
|
||||
/// </summary>
|
||||
public Universe HardAsset(UniverseSettings universeSettings = null)
|
||||
@@ -84,7 +84,7 @@ namespace QuantConnect.Algorithm
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Universe which selects companies that have dividend yields at least twice the average for large-cap stocks.
|
||||
/// <see cref="Universe"/> which selects companies that have dividend yields at least twice the average for large-cap stocks.
|
||||
/// They tend to be mature, slow-growing companies.
|
||||
/// </summary>
|
||||
public Universe HighYield(UniverseSettings universeSettings = null)
|
||||
@@ -95,7 +95,7 @@ namespace QuantConnect.Algorithm
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Universe which selects companies that have shown slow revenue and earnings growth (typically less than the rate
|
||||
/// <see cref="Universe"/> which selects companies that have shown slow revenue and earnings growth (typically less than the rate
|
||||
/// of GDP growth) over at least three years.
|
||||
/// </summary>
|
||||
public Universe SlowGrowth(UniverseSettings universeSettings = null)
|
||||
@@ -106,7 +106,7 @@ namespace QuantConnect.Algorithm
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Universe which selects companies that have shown strong revenue growth but slower or spotty earnings growth.
|
||||
/// <see cref="Universe"/> which selects companies that have shown strong revenue growth but slower or spotty earnings growth.
|
||||
/// Very small or young companies also tend to fall into this class.
|
||||
/// </summary>
|
||||
public Universe SpeculativeGrowth(UniverseSettings universeSettings = null)
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace QuantConnect.Algorithm
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new coarse universe that contains the top count of stocks
|
||||
/// Creates a new coarse <see cref="Universe"/> that contains the top count of stocks
|
||||
/// by daily dollar volume
|
||||
/// </summary>
|
||||
/// <param name="count">The number of stock to select</param>
|
||||
|
||||
@@ -19,6 +19,7 @@ using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Algorithm
|
||||
{
|
||||
@@ -31,15 +32,10 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void SetAlpha(PyObject alpha)
|
||||
{
|
||||
IAlphaModel model;
|
||||
if (alpha.TryConvert(out model))
|
||||
{
|
||||
SetAlpha(model);
|
||||
}
|
||||
else
|
||||
{
|
||||
Alpha = new AlphaModelPythonWrapper(alpha);
|
||||
}
|
||||
Alpha = PythonUtil.CreateInstanceOrWrapper<IAlphaModel>(
|
||||
alpha,
|
||||
py => new AlphaModelPythonWrapper(py)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -49,15 +45,11 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void AddAlpha(PyObject alpha)
|
||||
{
|
||||
IAlphaModel model;
|
||||
if (alpha.TryConvert(out model))
|
||||
{
|
||||
AddAlpha(model);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddAlpha(new AlphaModelPythonWrapper(alpha));
|
||||
}
|
||||
var model = PythonUtil.CreateInstanceOrWrapper<IAlphaModel>(
|
||||
alpha,
|
||||
py => new AlphaModelPythonWrapper(py)
|
||||
);
|
||||
AddAlpha(model);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -68,15 +60,10 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetExecution(PyObject execution)
|
||||
{
|
||||
IExecutionModel model;
|
||||
if (execution.TryConvert(out model))
|
||||
{
|
||||
SetExecution(model);
|
||||
}
|
||||
else
|
||||
{
|
||||
Execution = new ExecutionModelPythonWrapper(execution);
|
||||
}
|
||||
Execution = PythonUtil.CreateInstanceOrWrapper<IExecutionModel>(
|
||||
execution,
|
||||
py => new ExecutionModelPythonWrapper(py)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -87,15 +74,10 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetPortfolioConstruction(PyObject portfolioConstruction)
|
||||
{
|
||||
IPortfolioConstructionModel model;
|
||||
if (portfolioConstruction.TryConvert(out model))
|
||||
{
|
||||
SetPortfolioConstruction(model);
|
||||
}
|
||||
else
|
||||
{
|
||||
PortfolioConstruction = new PortfolioConstructionModelPythonWrapper(portfolioConstruction);
|
||||
}
|
||||
PortfolioConstruction = PythonUtil.CreateInstanceOrWrapper<IPortfolioConstructionModel>(
|
||||
portfolioConstruction,
|
||||
py => new PortfolioConstructionModelPythonWrapper(py)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -106,12 +88,10 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void SetUniverseSelection(PyObject universeSelection)
|
||||
{
|
||||
IUniverseSelectionModel model;
|
||||
if (!universeSelection.TryConvert(out model))
|
||||
{
|
||||
model = new UniverseSelectionModelPythonWrapper(universeSelection);
|
||||
}
|
||||
SetUniverseSelection(model);
|
||||
UniverseSelection = PythonUtil.CreateInstanceOrWrapper<IUniverseSelectionModel>(
|
||||
universeSelection,
|
||||
py => new UniverseSelectionModelPythonWrapper(py)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -122,11 +102,10 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void AddUniverseSelection(PyObject universeSelection)
|
||||
{
|
||||
IUniverseSelectionModel model;
|
||||
if (!universeSelection.TryConvert(out model))
|
||||
{
|
||||
model = new UniverseSelectionModelPythonWrapper(universeSelection);
|
||||
}
|
||||
var model = PythonUtil.CreateInstanceOrWrapper<IUniverseSelectionModel>(
|
||||
universeSelection,
|
||||
py => new UniverseSelectionModelPythonWrapper(py)
|
||||
);
|
||||
AddUniverseSelection(model);
|
||||
}
|
||||
|
||||
@@ -138,15 +117,10 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetRiskManagement(PyObject riskManagement)
|
||||
{
|
||||
IRiskManagementModel model;
|
||||
if (riskManagement.TryConvert(out model))
|
||||
{
|
||||
SetRiskManagement(model);
|
||||
}
|
||||
else
|
||||
{
|
||||
RiskManagement = new RiskManagementModelPythonWrapper(riskManagement);
|
||||
}
|
||||
RiskManagement = PythonUtil.CreateInstanceOrWrapper<IRiskManagementModel>(
|
||||
riskManagement,
|
||||
py => new RiskManagementModelPythonWrapper(py)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -157,11 +131,10 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void AddRiskManagement(PyObject riskManagement)
|
||||
{
|
||||
IRiskManagementModel model;
|
||||
if (!riskManagement.TryConvert(out model))
|
||||
{
|
||||
model = new RiskManagementModelPythonWrapper(riskManagement);
|
||||
}
|
||||
var model = PythonUtil.CreateInstanceOrWrapper<IRiskManagementModel>(
|
||||
riskManagement,
|
||||
py => new RiskManagementModelPythonWrapper(py)
|
||||
);
|
||||
AddRiskManagement(model);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,8 +79,8 @@ namespace QuantConnect.Algorithm
|
||||
public IRiskManagementModel RiskManagement { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called by setup handlers after Initialize and allows the algorithm a chance to organize
|
||||
/// the data gather in the Initialize method
|
||||
/// Called by setup handlers after <see cref="Initialize"/> and allows the algorithm a chance to organize
|
||||
/// the data gather in the <see cref="Initialize"/> method
|
||||
/// </summary>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void FrameworkPostInitialize()
|
||||
@@ -100,7 +100,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Used to send data updates to algorithm framework models
|
||||
/// </summary>
|
||||
/// <param name="slice">The current data slice</param>
|
||||
/// <param name="slice">The current data <see cref="Slice"/></param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(HandlingData)]
|
||||
public void OnFrameworkData(Slice slice)
|
||||
@@ -166,12 +166,12 @@ namespace QuantConnect.Algorithm
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// They different framework models will process the new provided insight.
|
||||
/// They different framework models will process the new provided <see cref="Insight"/>.
|
||||
/// The <see cref="IPortfolioConstructionModel"/> will create targets,
|
||||
/// the <see cref="IRiskManagementModel"/> will adjust the targets
|
||||
/// and the <see cref="IExecutionModel"/> will execute the <see cref="IPortfolioTarget"/>
|
||||
/// </summary>
|
||||
/// <param name="insights">The insight to process</param>
|
||||
/// <param name="insights">The <see cref="Insight"/> to process</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
private void ProcessInsights(Insight[] insights)
|
||||
{
|
||||
@@ -179,7 +179,7 @@ namespace QuantConnect.Algorithm
|
||||
var targetsEnumerable = PortfolioConstruction.CreateTargets(this, insights);
|
||||
// for performance only call 'ToArray' if not empty enumerable (which is static)
|
||||
var targets = targetsEnumerable == Enumerable.Empty<IPortfolioTarget>()
|
||||
? new IPortfolioTarget[] {} : targetsEnumerable.ToArray();
|
||||
? new IPortfolioTarget[] { } : targetsEnumerable.ToArray();
|
||||
|
||||
// set security targets w/ those generated via portfolio construction module
|
||||
foreach (var target in targets)
|
||||
|
||||
@@ -31,10 +31,10 @@ namespace QuantConnect.Algorithm
|
||||
{
|
||||
public partial class QCAlgorithm
|
||||
{
|
||||
private readonly int SeedLookbackPeriod = Config.GetInt("seed-lookback-period", 5);
|
||||
private readonly int SeedRetryMinuteLookbackPeriod = Config.GetInt("seed-retry-minute-lookback-period", 24 * 60);
|
||||
private readonly int SeedRetryHourLookbackPeriod = Config.GetInt("seed-retry-hour-lookback-period", 24);
|
||||
private readonly int SeedRetryDailyLookbackPeriod = Config.GetInt("seed-retry-daily-lookback-period", 10);
|
||||
private static readonly int SeedLookbackPeriod = Config.GetInt("seed-lookback-period", 5);
|
||||
private static readonly int SeedRetryMinuteLookbackPeriod = Config.GetInt("seed-retry-minute-lookback-period", 24 * 60);
|
||||
private static readonly int SeedRetryHourLookbackPeriod = Config.GetInt("seed-retry-hour-lookback-period", 24);
|
||||
private static readonly int SeedRetryDailyLookbackPeriod = Config.GetInt("seed-retry-daily-lookback-period", 10);
|
||||
|
||||
private bool _dataDictionaryTickWarningSent;
|
||||
|
||||
@@ -742,7 +742,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <returns>Securities historical data</returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public Dictionary<Symbol, IEnumerable<BaseData>> GetLastKnownPrices(IEnumerable<Security> securities)
|
||||
public DataDictionary<IEnumerable<BaseData>> GetLastKnownPrices(IEnumerable<Security> securities)
|
||||
{
|
||||
return GetLastKnownPrices(securities.Select(s => s.Symbol));
|
||||
}
|
||||
@@ -754,11 +754,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <returns>Securities historical data</returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public Dictionary<Symbol, IEnumerable<BaseData>> GetLastKnownPrices(IEnumerable<Symbol> symbols)
|
||||
public DataDictionary<IEnumerable<BaseData>> GetLastKnownPrices(IEnumerable<Symbol> symbols)
|
||||
{
|
||||
if (HistoryProvider == null)
|
||||
{
|
||||
return new Dictionary<Symbol, IEnumerable<BaseData>>();
|
||||
return new DataDictionary<IEnumerable<BaseData>>();
|
||||
}
|
||||
|
||||
var data = new Dictionary<(Symbol, Type, TickType), BaseData>();
|
||||
@@ -766,10 +766,12 @@ namespace QuantConnect.Algorithm
|
||||
|
||||
return data
|
||||
.GroupBy(kvp => kvp.Key.Item1)
|
||||
.ToDictionary(g => g.Key,
|
||||
.ToDataDictionary(
|
||||
g => g.Key,
|
||||
g => g.OrderBy(kvp => kvp.Value.Time)
|
||||
.ThenBy(kvp => GetTickTypeOrder(kvp.Key.Item1.SecurityType, kvp.Key.Item3))
|
||||
.Select(kvp => kvp.Value));
|
||||
.Select(kvp => kvp.Value)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1281,6 +1283,15 @@ namespace QuantConnect.Algorithm
|
||||
}
|
||||
else
|
||||
{
|
||||
// let's try to respect already added user settings, even if resolution/type don't match, like Tick vs Bars
|
||||
var userConfigIfAny = subscriptions.FirstOrDefault(x => LeanData.IsCommonLeanDataType(x.Type) && !x.IsInternalFeed);
|
||||
|
||||
// Inherit values from existing subscriptions or use defaults
|
||||
var extendedMarketHours = userConfigIfAny?.ExtendedMarketHours ?? UniverseSettings.ExtendedMarketHours;
|
||||
var dataNormalizationMode = userConfigIfAny?.DataNormalizationMode ?? UniverseSettings.GetUniverseNormalizationModeOrDefault(symbol.SecurityType);
|
||||
var dataMappingMode = userConfigIfAny?.DataMappingMode ?? UniverseSettings.GetUniverseMappingModeOrDefault(symbol.SecurityType, symbol.ID.Market);
|
||||
var contractDepthOffset = userConfigIfAny?.ContractDepthOffset ?? (uint)Math.Abs(UniverseSettings.ContractDepthOffset);
|
||||
|
||||
// If type was specified and not a lean data type and also not abstract, we create a new subscription
|
||||
if (type != null && !LeanData.IsCommonLeanDataType(type) && !type.IsAbstract)
|
||||
{
|
||||
@@ -1304,17 +1315,16 @@ namespace QuantConnect.Algorithm
|
||||
entry.DataTimeZone,
|
||||
entry.ExchangeHours.TimeZone,
|
||||
UniverseSettings.FillForward,
|
||||
UniverseSettings.ExtendedMarketHours,
|
||||
extendedMarketHours,
|
||||
true,
|
||||
isCustom,
|
||||
LeanData.GetCommonTickTypeForCommonDataTypes(dataType, symbol.SecurityType),
|
||||
true,
|
||||
UniverseSettings.GetUniverseNormalizationModeOrDefault(symbol.SecurityType))};
|
||||
dataNormalizationMode,
|
||||
dataMappingMode,
|
||||
contractDepthOffset)};
|
||||
}
|
||||
|
||||
// let's try to respect already added user settings, even if resolution/type don't match, like Tick vs Bars
|
||||
var userConfigIfAny = subscriptions.FirstOrDefault(x => LeanData.IsCommonLeanDataType(x.Type) && !x.IsInternalFeed);
|
||||
|
||||
var res = GetResolution(symbol, resolution, type);
|
||||
return SubscriptionManager
|
||||
.LookupSubscriptionConfigDataTypes(symbol.SecurityType, res,
|
||||
@@ -1335,14 +1345,14 @@ namespace QuantConnect.Algorithm
|
||||
entry.DataTimeZone,
|
||||
entry.ExchangeHours.TimeZone,
|
||||
UniverseSettings.FillForward,
|
||||
userConfigIfAny?.ExtendedMarketHours ?? UniverseSettings.ExtendedMarketHours,
|
||||
extendedMarketHours,
|
||||
true,
|
||||
false,
|
||||
x.Item2,
|
||||
true,
|
||||
userConfigIfAny?.DataNormalizationMode ?? UniverseSettings.GetUniverseNormalizationModeOrDefault(symbol.SecurityType),
|
||||
userConfigIfAny?.DataMappingMode ?? UniverseSettings.GetUniverseMappingModeOrDefault(symbol.SecurityType, symbol.ID.Market),
|
||||
userConfigIfAny?.ContractDepthOffset ?? (uint)Math.Abs(UniverseSettings.ContractDepthOffset));
|
||||
dataNormalizationMode,
|
||||
dataMappingMode,
|
||||
contractDepthOffset);
|
||||
})
|
||||
// lets make sure to respect the order of the data types, if used on a history request will affect outcome when using pushthrough for example
|
||||
.OrderByDescending(config => GetTickTypeOrder(config.SecurityType, config.TickType));
|
||||
|
||||
@@ -53,7 +53,8 @@ namespace QuantConnect.Algorithm
|
||||
"IsReady",
|
||||
"Window",
|
||||
"Item",
|
||||
"WarmUpPeriod"
|
||||
"WarmUpPeriod",
|
||||
"Period"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -489,6 +490,26 @@ namespace QuantConnect.Algorithm
|
||||
return correlation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Covariance indicator for the given target symbol in relation with the reference used.
|
||||
/// The indicator will be automatically updated on the given resolution.
|
||||
/// </summary>
|
||||
/// <param name="target">The target symbol whose Covariance value we want</param>
|
||||
/// <param name="reference">The reference symbol to compare with the target symbol</param>
|
||||
/// <param name="period">The period of the Covariance indicator</param>
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
|
||||
/// <returns>The Covariance indicator for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public Covariance COV(Symbol target, Symbol reference, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(QuantConnect.Symbol.None, $"COV({period})", resolution);
|
||||
var covariance = new Covariance(name, target, reference, period);
|
||||
InitializeIndicator(covariance, resolution, selector, target, reference);
|
||||
|
||||
return covariance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CommodityChannelIndex indicator. The indicator will be automatically
|
||||
/// updated on the given resolution.
|
||||
@@ -1691,6 +1712,50 @@ namespace QuantConnect.Algorithm
|
||||
return normalizedAverageTrueRange;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new New Highs - New Lows indicator
|
||||
/// </summary>
|
||||
/// <param name="symbols">The symbols whose NHNL we want</param>
|
||||
/// <param name="period">The period over which to compute the NHNL</param>
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a IBaseDataBar</param>
|
||||
/// <returns>The NewHighsNewLows indicator for the requested symbols over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public NewHighsNewLows NHNL(IEnumerable<Symbol> symbols, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(QuantConnect.Symbol.None, $"NH/NL({period})", resolution ?? GetSubscription(symbols.First()).Resolution);
|
||||
var nhnlDifference = new NewHighsNewLows(name, period);
|
||||
foreach (var symbol in symbols)
|
||||
{
|
||||
nhnlDifference.Add(symbol);
|
||||
}
|
||||
InitializeIndicator(nhnlDifference, resolution, selector, symbols.ToArray());
|
||||
|
||||
return nhnlDifference;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new New Highs - New Lows Volume indicator
|
||||
/// </summary>
|
||||
/// <param name="symbols">The symbols whose NHNLV we want</param>
|
||||
/// <param name="period">The period over which to compute the NHNLV</param>
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
|
||||
/// <returns>The NewHighsNewLowsVolume indicator for the requested symbols over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public NewHighsNewLowsVolume NHNLV(IEnumerable<Symbol> symbols, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(QuantConnect.Symbol.None, $"NH/NL Volume({period})", resolution ?? GetSubscription(symbols.First()).Resolution);
|
||||
var nhnlVolume = new NewHighsNewLowsVolume(name, period);
|
||||
foreach (var symbol in symbols)
|
||||
{
|
||||
nhnlVolume.Add(symbol);
|
||||
}
|
||||
InitializeIndicator(nhnlVolume, resolution, selector, symbols.ToArray());
|
||||
|
||||
return nhnlVolume;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new On Balance Volume indicator. This will compute the cumulative total volume
|
||||
/// based on whether the close price being higher or lower than the previous period.
|
||||
@@ -2215,7 +2280,7 @@ namespace QuantConnect.Algorithm
|
||||
|
||||
return targetDownsideDeviation;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new TomDemark Sequential candlestick indicator for the symbol. The indicator will be automatically
|
||||
/// updated on the symbol's subscription resolution.
|
||||
|
||||
@@ -497,6 +497,12 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(StatisticsTag)]
|
||||
public void SetSummaryStatistic(string name, string value)
|
||||
{
|
||||
if (int.TryParse(name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intName) &&
|
||||
intName >= 0 && intName <= 100)
|
||||
{
|
||||
throw new ArgumentException($"'{name}' is a reserved statistic name.");
|
||||
}
|
||||
|
||||
_statisticsService.SetSummaryStatistic(name, value);
|
||||
}
|
||||
|
||||
@@ -508,7 +514,7 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(StatisticsTag)]
|
||||
public void SetSummaryStatistic(string name, int value)
|
||||
{
|
||||
_statisticsService.SetSummaryStatistic(name, value.ToStringInvariant());
|
||||
SetSummaryStatistic(name, value.ToStringInvariant());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -519,7 +525,7 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(StatisticsTag)]
|
||||
public void SetSummaryStatistic(string name, double value)
|
||||
{
|
||||
_statisticsService.SetSummaryStatistic(name, value.ToStringInvariant());
|
||||
SetSummaryStatistic(name, value.ToStringInvariant());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -530,7 +536,7 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(StatisticsTag)]
|
||||
public void SetSummaryStatistic(string name, decimal value)
|
||||
{
|
||||
_statisticsService.SetSummaryStatistic(name, value.ToStringInvariant());
|
||||
SetSummaryStatistic(name, value.ToStringInvariant());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1372,12 +1372,10 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(Modeling)]
|
||||
public void SetBrokerageModel(PyObject model)
|
||||
{
|
||||
IBrokerageModel brokerageModel;
|
||||
if (!model.TryConvert(out brokerageModel))
|
||||
{
|
||||
brokerageModel = new BrokerageModelPythonWrapper(model);
|
||||
}
|
||||
|
||||
var brokerageModel = PythonUtil.CreateInstanceOrWrapper<IBrokerageModel>(
|
||||
model,
|
||||
py => new BrokerageModelPythonWrapper(py)
|
||||
);
|
||||
SetBrokerageModel(brokerageModel);
|
||||
}
|
||||
|
||||
@@ -1392,11 +1390,10 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(Logging)]
|
||||
public void SetBrokerageMessageHandler(PyObject handler)
|
||||
{
|
||||
if (!handler.TryConvert(out IBrokerageMessageHandler brokerageMessageHandler))
|
||||
{
|
||||
brokerageMessageHandler = new BrokerageMessageHandlerPythonWrapper(handler);
|
||||
}
|
||||
|
||||
var brokerageMessageHandler = PythonUtil.CreateInstanceOrWrapper<IBrokerageMessageHandler>(
|
||||
handler,
|
||||
py => new BrokerageMessageHandlerPythonWrapper(py)
|
||||
);
|
||||
SetBrokerageMessageHandler(brokerageMessageHandler);
|
||||
}
|
||||
|
||||
@@ -1407,7 +1404,11 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(Modeling)]
|
||||
public void SetRiskFreeInterestRateModel(PyObject model)
|
||||
{
|
||||
SetRiskFreeInterestRateModel(RiskFreeInterestRateModelPythonWrapper.FromPyObject(model));
|
||||
var riskFreeInterestRateModel = PythonUtil.CreateInstanceOrWrapper<IRiskFreeInterestRateModel>(
|
||||
model,
|
||||
py => new RiskFreeInterestRateModelPythonWrapper(py)
|
||||
);
|
||||
SetRiskFreeInterestRateModel(riskFreeInterestRateModel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -58,6 +58,7 @@ using QuantConnect.Commands;
|
||||
using Newtonsoft.Json;
|
||||
using QuantConnect.Securities.Index;
|
||||
using QuantConnect.Api;
|
||||
using Common.Util;
|
||||
|
||||
namespace QuantConnect.Algorithm
|
||||
{
|
||||
@@ -256,7 +257,7 @@ namespace QuantConnect.Algorithm
|
||||
public event AlgorithmEvent<GeneratedInsightsCollection> InsightsGenerated;
|
||||
|
||||
/// <summary>
|
||||
/// Security collection is an array of the security objects such as Equities and FOREX. Securities data
|
||||
/// Security collection is an array of the security objects such as <see cref="Equity"/> and <see cref="Forex"/>. Securities data
|
||||
/// manages the properties of tradeable assets such as price, open and close time and holdings information.
|
||||
/// </summary>
|
||||
[DocumentationAttribute(SecuritiesAndPortfolio)]
|
||||
@@ -271,7 +272,7 @@ namespace QuantConnect.Algorithm
|
||||
/// a security that is currently selected by the universe or has holdings or open orders.
|
||||
/// </summary>
|
||||
[DocumentationAttribute(SecuritiesAndPortfolio)]
|
||||
public IReadOnlyDictionary<Symbol, Security> ActiveSecurities => UniverseManager.ActiveSecurities;
|
||||
public ReadOnlyExtendedDictionary<Symbol, Security> ActiveSecurities => UniverseManager.ActiveSecurities;
|
||||
|
||||
/// <summary>
|
||||
/// Portfolio object provieds easy access to the underlying security-holding properties; summed together in a way to make them useful.
|
||||
@@ -839,11 +840,6 @@ namespace QuantConnect.Algorithm
|
||||
SetFinishedWarmingUp();
|
||||
}
|
||||
|
||||
if (Settings.DailyPreciseEndTime)
|
||||
{
|
||||
Debug("Accurate daily end-times now enabled by default. See more at https://qnt.co/3YHaWHL. To disable it and use legacy daily bars set self.settings.daily_precise_end_time = False.");
|
||||
}
|
||||
|
||||
// perform end of time step checks, such as enforcing underlying securities are in raw data mode
|
||||
OnEndOfTimeStep();
|
||||
}
|
||||
@@ -914,9 +910,9 @@ namespace QuantConnect.Algorithm
|
||||
/// Gets a read-only dictionary with all current parameters
|
||||
/// </summary>
|
||||
[DocumentationAttribute(ParameterAndOptimization)]
|
||||
public IReadOnlyDictionary<string, string> GetParameters()
|
||||
public ReadOnlyExtendedDictionary<string, string> GetParameters()
|
||||
{
|
||||
return _parameters.ToReadOnlyDictionary();
|
||||
return _parameters.ToReadOnlyExtendedDictionary();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1247,6 +1243,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Brokerage message event handler. This method is called for all types of brokerage messages.
|
||||
/// </summary>
|
||||
/// <param name="messageEvent">The brokerage message event instance containing the message details.</param>
|
||||
[DocumentationAttribute(LiveTrading)]
|
||||
[DocumentationAttribute(Modeling)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
@@ -1440,7 +1437,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Sets the benchmark used for computing statistics of the algorithm to the specified symbol
|
||||
/// </summary>
|
||||
/// <param name="symbol">symbol to use as the benchmark</param>
|
||||
/// <param name="securityType">Is the symbol an equity, forex, base, etc. Default SecurityType.Equity</param>
|
||||
/// <param name="securityType">Is the symbol an equity, forex, base, etc. Default <see cref="SecurityType.Equity"/></param>
|
||||
/// <remarks>
|
||||
/// Must use symbol that is available to the trade engine in your data store(not strictly enforced)
|
||||
/// </remarks>
|
||||
@@ -1462,12 +1459,12 @@ namespace QuantConnect.Algorithm
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the benchmark used for computing statistics of the algorithm to the specified ticker, defaulting to SecurityType.Equity
|
||||
/// Sets the benchmark used for computing statistics of the algorithm to the specified ticker, defaulting to <see cref="SecurityType.Equity"/>
|
||||
/// if the ticker doesn't exist in the algorithm
|
||||
/// </summary>
|
||||
/// <param name="ticker">Ticker to use as the benchmark</param>
|
||||
/// <remarks>
|
||||
/// Overload to accept ticker without passing SecurityType. If ticker is in portfolio it will use that SecurityType, otherwise will default to SecurityType.Equity
|
||||
/// Overload to accept ticker without passing <see cref="SecurityType"/>. If ticker is in portfolio it will use that <see cref="SecurityType"/>, otherwise will default to <see cref="SecurityType.Equity"/>
|
||||
/// </remarks>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
[DocumentationAttribute(SecuritiesAndPortfolio)]
|
||||
@@ -1531,9 +1528,9 @@ namespace QuantConnect.Algorithm
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Benchmark
|
||||
/// The <see cref="IBenchmark"/> for the algorithm
|
||||
/// </summary>
|
||||
/// <remarks>Use Benchmark to override default symbol based benchmark, and create your own benchmark. For example a custom moving average benchmark </remarks>
|
||||
/// <remarks>Use <see cref="IBenchmark"/> for the algorithm to override default symbol based benchmark, and create your own benchmark. For example a custom moving average benchmark </remarks>
|
||||
///
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
[DocumentationAttribute(SecuritiesAndPortfolio)]
|
||||
@@ -1622,7 +1619,7 @@ namespace QuantConnect.Algorithm
|
||||
/// and replaced with the actual cash of your brokerage account.
|
||||
/// </summary>
|
||||
/// <param name="startingCash">Starting cash for the strategy backtest</param>
|
||||
/// <remarks>Alias of SetCash(decimal)</remarks>
|
||||
/// <remarks>Alias of <see cref="SetCash(decimal)"/></remarks>
|
||||
[DocumentationAttribute(SecuritiesAndPortfolio)]
|
||||
public void SetCash(double startingCash)
|
||||
{
|
||||
@@ -1634,7 +1631,7 @@ namespace QuantConnect.Algorithm
|
||||
/// and replaced with the actual cash of your brokerage account.
|
||||
/// </summary>
|
||||
/// <param name="startingCash">Starting cash for the strategy backtest</param>
|
||||
/// <remarks>Alias of SetCash(decimal)</remarks>
|
||||
/// <remarks>Alias of <see cref="SetCash(decimal)"/></remarks>
|
||||
[DocumentationAttribute(SecuritiesAndPortfolio)]
|
||||
public void SetCash(int startingCash)
|
||||
{
|
||||
@@ -1746,7 +1743,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Set the start date for the backtest
|
||||
/// </summary>
|
||||
/// <param name="start">Datetime Start date for backtest</param>
|
||||
/// <param name="start">The start date for the backtest</param>
|
||||
/// <remarks>Must be less than end date and within data available</remarks>
|
||||
/// <seealso cref="SetStartDate(int, int, int)"/>
|
||||
[DocumentationAttribute(HandlingData)]
|
||||
@@ -2148,7 +2145,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="underlying">Underlying asset Symbol to use as the option's underlying</param>
|
||||
/// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
|
||||
/// <param name="market">The option's market, <seealso cref="Market"/>. Default value is null, but will be resolved using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="market">The option's market, <seealso cref="Market"/>. Default value is null, but will be resolved using <see cref="IBrokerageModel.DefaultMarkets"/> in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="fillForward">If true, data will be provided to the algorithm every Second, Minute, Hour, or Day, while the asset is open and depending on the Resolution this option was configured to use.</param>
|
||||
/// <param name="leverage">The requested leverage for the </param>
|
||||
/// <returns>The new option security instance</returns>
|
||||
@@ -2167,7 +2164,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="underlying">Underlying asset Symbol to use as the option's underlying</param>
|
||||
/// <param name="targetOption">The target option ticker. This is useful when the option ticker does not match the underlying, e.g. SPX index and the SPXW weekly option. If null is provided will use underlying</param>
|
||||
/// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
|
||||
/// <param name="market">The option's market, <seealso cref="Market"/>. Default value is null, but will be resolved using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="market">The option's market, <seealso cref="Market"/>. Default value is null, but will be resolved using <see cref="IBrokerageModel.DefaultMarkets"/> in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="fillForward">If true, data will be provided to the algorithm every Second, Minute, Hour, or Day, while the asset is open and depending on the Resolution this option was configured to use.</param>
|
||||
/// <param name="leverage">The requested leverage for the </param>
|
||||
/// <returns>The new option security instance</returns>
|
||||
@@ -2206,9 +2203,9 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="ticker">The future ticker</param>
|
||||
/// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
|
||||
/// <param name="market">The futures market, <seealso cref="Market"/>. Default is value null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="market">The futures market, <seealso cref="Market"/>. Default is value null and looked up using <see cref="IBrokerageModel.DefaultMarkets"> in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
|
||||
/// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
|
||||
/// <param name="leverage">The requested leverage for this future. Default is set by <see cref="SecurityInitializer"/></param>
|
||||
/// <param name="extendedMarketHours">Use extended market hours data</param>
|
||||
/// <param name="dataMappingMode">The contract mapping mode to use for the continuous future contract</param>
|
||||
/// <param name="dataNormalizationMode">The price scaling mode to use for the continuous future contract</param>
|
||||
@@ -2241,7 +2238,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">The futures contract symbol</param>
|
||||
/// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
|
||||
/// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
|
||||
/// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
|
||||
/// <param name="leverage">The requested leverage for this future. Default is set by <see cref="SecurityInitializer"/></param>
|
||||
/// <param name="extendedMarketHours">Use extended market hours data</param>
|
||||
/// <returns>The new <see cref="Future"/> security</returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
@@ -2301,12 +2298,13 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Creates and adds index options to the algorithm.
|
||||
/// </summary>
|
||||
/// <param name="underlying">The underlying ticker of the Index Option</param>
|
||||
/// <param name="underlying">The underlying ticker of the <see cref="IndexOption"/></param>
|
||||
/// <param name="resolution">Resolution of the index option contracts, i.e. the granularity of the data</param>
|
||||
/// <param name="market">The foreign exchange trading market, <seealso cref="Market"/>. Default value is null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="market">The foreign exchange trading market, <seealso cref="Market"/>. Default value is null and looked up using <see cref="IBrokerageModel.DefaultMarkets"/> in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="fillForward">If true, this will fill in missing data points with the previous data point</param>
|
||||
/// <returns>Canonical Option security</returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
|
||||
public IndexOption AddIndexOption(string underlying, Resolution? resolution = null, string market = null, bool fillForward = true)
|
||||
{
|
||||
return AddIndexOption(underlying, null, resolution, market, fillForward);
|
||||
@@ -2350,7 +2348,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="underlying">The underlying ticker of the Index Option</param>
|
||||
/// <param name="targetOption">The target option ticker. This is useful when the option ticker does not match the underlying, e.g. SPX index and the SPXW weekly option. If null is provided will use underlying</param>
|
||||
/// <param name="resolution">Resolution of the index option contracts, i.e. the granularity of the data</param>
|
||||
/// <param name="market">The foreign exchange trading market, <seealso cref="Market"/>. Default value is null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="market">The foreign exchange trading market, <seealso cref="Market"/>. Default value is null and looked up using <see cref="IBrokerageModel.DefaultMarkets"> in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="fillForward">If true, this will fill in missing data points with the previous data point</param>
|
||||
/// <returns>Canonical Option security</returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
@@ -2368,7 +2366,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">Resolution of the index option contract, i.e. the granularity of the data</param>
|
||||
/// <param name="fillForward">If true, this will fill in missing data points with the previous data point</param>
|
||||
/// <returns>Index Option Contract</returns>
|
||||
/// <exception cref="ArgumentException">The provided Symbol is not an Index Option</exception>
|
||||
/// <exception cref="ArgumentException">The provided Symbol is not an <see cref="IndexOption"/></exception>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
public IndexOption AddIndexOptionContract(Symbol symbol, Resolution? resolution = null, bool fillForward = true)
|
||||
{
|
||||
@@ -2386,7 +2384,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">The option contract symbol</param>
|
||||
/// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
|
||||
/// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
|
||||
/// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
|
||||
/// <param name="leverage">The requested leverage for this option. Default is set by <see cref="SecurityInitializer"/></param>
|
||||
/// <param name="extendedMarketHours">Use extended market hours data</param>
|
||||
/// <returns>The new <see cref="Option"/> security</returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
@@ -2481,9 +2479,9 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="ticker">The currency pair</param>
|
||||
/// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
|
||||
/// <param name="market">The foreign exchange trading market, <seealso cref="Market"/>. Default value is null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="market">The foreign exchange trading market, <seealso cref="Market"/>. Default value is null and looked up using <see cref="IBrokerageModel.DefaultMarkets" /> in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
|
||||
/// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
|
||||
/// <param name="leverage">The requested leverage for this forex security. Default is set by <see cref="SecurityInitializer"/></param>
|
||||
/// <returns>The new <see cref="Forex"/> security</returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
public Forex AddForex(string ticker, Resolution? resolution = null, string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
|
||||
@@ -2494,11 +2492,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Creates and adds a new <see cref="Cfd"/> security to the algorithm
|
||||
/// </summary>
|
||||
/// <param name="ticker">The currency pair</param>
|
||||
/// <param name="ticker">The CFD ticker symbol</param>
|
||||
/// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
|
||||
/// <param name="market">The cfd trading market, <seealso cref="Market"/>. Default value is null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="market">The cfd trading market, <seealso cref="Market"/>. Default value is null and looked up using <see cref="IBrokerageModel.DefaultMarkets"/> in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
|
||||
/// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
|
||||
/// <param name="leverage">The requested leverage for this CFD. Default is set by <see cref="SecurityInitializer"/></param>
|
||||
/// <returns>The new <see cref="Cfd"/> security</returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
public Cfd AddCfd(string ticker, Resolution? resolution = null, string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
|
||||
@@ -2510,9 +2508,9 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Creates and adds a new <see cref="Index"/> security to the algorithm
|
||||
/// </summary>
|
||||
/// <param name="ticker">The currency pair</param>
|
||||
/// <param name="ticker">The index ticker</param>
|
||||
/// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
|
||||
/// <param name="market">The index trading market, <seealso cref="Market"/>. Default value is null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="market">The index trading market, <seealso cref="Market"/>. Default value is null and looked up using <see cref="IBrokerageModel.DefaultMarkets"> in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
|
||||
/// <returns>The new <see cref="Index"/> security</returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
@@ -2525,11 +2523,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Creates and adds a new <see cref="Crypto"/> security to the algorithm
|
||||
/// </summary>
|
||||
/// <param name="ticker">The currency pair</param>
|
||||
/// <param name="ticker">The crypto ticker symbol/param>
|
||||
/// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
|
||||
/// <param name="market">The cfd trading market, <seealso cref="Market"/>. Default value is null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="market">The The crypto trading market, <seealso cref="Market"/>. Default value is null and looked up using <see cref="IBrokerageModel.DefaultMarkets"/> in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
|
||||
/// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
|
||||
/// <param name="leverage">The requested leverage for this crypto. Default is set by <see cref="SecurityInitializer"/></param>
|
||||
/// <returns>The new <see cref="Crypto"/> security</returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
public Crypto AddCrypto(string ticker, Resolution? resolution = null, string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
|
||||
@@ -2540,11 +2538,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Creates and adds a new <see cref="CryptoFuture"/> security to the algorithm
|
||||
/// </summary>
|
||||
/// <param name="ticker">The currency pair</param>
|
||||
/// <param name="ticker">The crypto future ticker symbol</param>
|
||||
/// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
|
||||
/// <param name="market">The cfd trading market, <seealso cref="Market"/>. Default value is null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="market">The The crypto future trading market, <seealso cref="Market"/>. Default value is null and looked up using <see cref="IBrokerageModel.DefaultMarkets"/> in <see cref="AddSecurity{T}"/></param>
|
||||
/// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
|
||||
/// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
|
||||
/// <param name="leverage">The requested leverage for this crypto future. Default is set by <see cref="SecurityInitializer"/></param>
|
||||
/// <returns>The new <see cref="CryptoFuture"/> security</returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
public CryptoFuture AddCryptoFuture(string ticker, Resolution? resolution = null, string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
|
||||
@@ -2558,7 +2556,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol of the security to be removed</param>
|
||||
/// <param name="tag">Optional tag to indicate the cause of removal</param>
|
||||
/// <remarks>Sugar syntax for <see cref="AddOptionContract"/></remarks>
|
||||
/// <remarks>Sugar syntax for <see cref="RemoveSecurity"/></remarks>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
public bool RemoveOptionContract(Symbol symbol, string tag = null)
|
||||
{
|
||||
@@ -2788,7 +2786,7 @@ namespace QuantConnect.Algorithm
|
||||
public void Debug(string message)
|
||||
{
|
||||
if (!_liveMode && (string.IsNullOrEmpty(message) || _previousDebugMessage == message)) return;
|
||||
_debugMessages.Enqueue(message);
|
||||
_debugMessages.Enqueue(FormatLog(message));
|
||||
_previousDebugMessage = message;
|
||||
}
|
||||
|
||||
@@ -2838,7 +2836,7 @@ namespace QuantConnect.Algorithm
|
||||
public void Log(string message)
|
||||
{
|
||||
if (!_liveMode && string.IsNullOrEmpty(message)) return;
|
||||
_logMessages.Enqueue(message);
|
||||
_logMessages.Enqueue(FormatLog(message));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -2887,7 +2885,7 @@ namespace QuantConnect.Algorithm
|
||||
public void Error(string message)
|
||||
{
|
||||
if (!_liveMode && (string.IsNullOrEmpty(message) || _previousErrorMessage == message)) return;
|
||||
_errorMessages.Enqueue(message);
|
||||
_errorMessages.Enqueue(FormatLog(message));
|
||||
_previousErrorMessage = message;
|
||||
}
|
||||
|
||||
@@ -2936,10 +2934,7 @@ namespace QuantConnect.Algorithm
|
||||
[DocumentationAttribute(Logging)]
|
||||
public void Error(Exception error)
|
||||
{
|
||||
var message = error.Message;
|
||||
if (!_liveMode && (string.IsNullOrEmpty(message) || _previousErrorMessage == message)) return;
|
||||
_errorMessages.Enqueue(message);
|
||||
_previousErrorMessage = message;
|
||||
Error(error.Message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -3817,5 +3812,10 @@ namespace QuantConnect.Algorithm
|
||||
var exchange = MarketHoursDatabase.GetExchangeHours(symbol.ID.Market, symbol, symbol.SecurityType);
|
||||
return UtcTime.ConvertFromUtc(exchange.TimeZone);
|
||||
}
|
||||
|
||||
private string FormatLog(string message)
|
||||
{
|
||||
return $"{Time.ToStringInvariant(DateFormat.UI)} {message}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<RootNamespace>QuantConnect.Algorithm</RootNamespace>
|
||||
<AssemblyName>QuantConnect.Algorithm</AssemblyName>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
|
||||
@@ -29,7 +29,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.50" />
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.52" />
|
||||
<PackageReference Include="MathNet.Numerics" Version="5.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
<PackageReference Include="NodaTime" Version="3.0.5" />
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace QuantConnect.Algorithm.Framework.Risk
|
||||
/// Initializes a new instance of the <see cref="CompositeRiskManagementModel"/> class
|
||||
/// </summary>
|
||||
/// <param name="riskManagementModels">The individual risk management models defining this composite model</param>
|
||||
public CompositeRiskManagementModel(IEnumerable<IRiskManagementModel>riskManagementModels)
|
||||
public CompositeRiskManagementModel(IEnumerable<IRiskManagementModel> riskManagementModels)
|
||||
{
|
||||
foreach (var riskManagementModel in riskManagementModels)
|
||||
{
|
||||
@@ -129,11 +129,10 @@ namespace QuantConnect.Algorithm.Framework.Risk
|
||||
/// <param name="pyRiskManagementModel">The risk management model to add</param>
|
||||
public void AddRiskManagement(PyObject pyRiskManagementModel)
|
||||
{
|
||||
IRiskManagementModel riskManagementModel;
|
||||
if (!pyRiskManagementModel.TryConvert(out riskManagementModel))
|
||||
{
|
||||
riskManagementModel = new RiskManagementModelPythonWrapper(pyRiskManagementModel);
|
||||
}
|
||||
var riskManagementModel = PythonUtil.CreateInstanceOrWrapper<IRiskManagementModel>(
|
||||
pyRiskManagementModel,
|
||||
py => new RiskManagementModelPythonWrapper(py)
|
||||
);
|
||||
_riskManagementModels.Add(riskManagementModel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ using QuantConnect.Algorithm.Framework.Alphas.Analysis;
|
||||
using QuantConnect.Commands;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio.SignalExports;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using Common.Util;
|
||||
|
||||
namespace QuantConnect.AlgorithmFactory.Python.Wrappers
|
||||
{
|
||||
@@ -681,7 +682,7 @@ namespace QuantConnect.AlgorithmFactory.Python.Wrappers
|
||||
/// <summary>
|
||||
/// Gets a read-only dictionary with all current parameters
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, string> GetParameters() => _baseAlgorithm.GetParameters();
|
||||
public ReadOnlyExtendedDictionary<string, string> GetParameters() => _baseAlgorithm.GetParameters();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parameter with the specified name. If a parameter with the specified name does not exist,
|
||||
@@ -1103,7 +1104,7 @@ namespace QuantConnect.AlgorithmFactory.Python.Wrappers
|
||||
/// </summary>
|
||||
/// <param name="symbols">The symbols we want to get seed data for</param>
|
||||
/// <returns>Securities historical data</returns>
|
||||
public Dictionary<Symbol, IEnumerable<BaseData>> GetLastKnownPrices(IEnumerable<Symbol> symbols) => _baseAlgorithm.GetLastKnownPrices(symbols);
|
||||
public DataDictionary<IEnumerable<BaseData>> GetLastKnownPrices(IEnumerable<Symbol> symbols) => _baseAlgorithm.GetLastKnownPrices(symbols);
|
||||
|
||||
/// <summary>
|
||||
/// Set the runtime error
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<RootNamespace>QuantConnect.AlgorithmFactory</RootNamespace>
|
||||
<AssemblyName>QuantConnect.AlgorithmFactory</AssemblyName>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
|
||||
@@ -28,7 +28,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.50" />
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.52" />
|
||||
<PackageReference Include="NodaTime" Version="3.0.5" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
896
Api/Api.cs
896
Api/Api.cs
File diff suppressed because it is too large
Load Diff
@@ -15,24 +15,32 @@
|
||||
|
||||
using System;
|
||||
using RestSharp;
|
||||
using Newtonsoft.Json;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Logging;
|
||||
using System.Threading.Tasks;
|
||||
using RestSharp.Authenticators;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Util;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace QuantConnect.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// API Connection and Hash Manager
|
||||
/// </summary>
|
||||
public class ApiConnection
|
||||
public class ApiConnection : IDisposable
|
||||
{
|
||||
private readonly static JsonSerializerSettings _jsonSettings = new() { Converters = { new LiveAlgorithmResultsJsonConverter(), new OrderJsonConverter() } };
|
||||
/// <summary>
|
||||
/// Authorized client to use for requests.
|
||||
/// </summary>
|
||||
private HttpClient _httpClient;
|
||||
|
||||
/// <summary>
|
||||
/// Authorized client to use for requests.
|
||||
/// </summary>
|
||||
[Obsolete("RestSharp is deprecated and will be removed in a future release. Please use the SetClient method or the request methods that take an HttpRequestMessage")]
|
||||
public RestClient Client { get; set; }
|
||||
|
||||
// Authorization Credentials
|
||||
@@ -47,10 +55,23 @@ namespace QuantConnect.Api
|
||||
/// <param name="userId">User Id number from QuantConnect.com account. Found at www.quantconnect.com/account </param>
|
||||
/// <param name="token">Access token for the QuantConnect account. Found at www.quantconnect.com/account </param>
|
||||
public ApiConnection(int userId, string token)
|
||||
: this(userId, token, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new Api Connection Class.
|
||||
/// </summary>
|
||||
/// <param name="userId">User Id number from QuantConnect.com account. Found at www.quantconnect.com/account </param>
|
||||
/// <param name="token">Access token for the QuantConnect account. Found at www.quantconnect.com/account </param>
|
||||
/// <param name="baseUrl">The client's base address</param>
|
||||
/// <param name="defaultHeaders">Default headers for the client</param>
|
||||
/// <param name="timeout">The client timeout in seconds</param>
|
||||
public ApiConnection(int userId, string token, string baseUrl = null, Dictionary<string, string> defaultHeaders = null, int timeout = 0)
|
||||
{
|
||||
_token = token;
|
||||
_userId = userId.ToStringInvariant();
|
||||
Client = new RestClient(Globals.Api);
|
||||
SetClient(!string.IsNullOrEmpty(baseUrl) ? baseUrl : Globals.Api, defaultHeaders, timeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -60,16 +81,55 @@ namespace QuantConnect.Api
|
||||
{
|
||||
get
|
||||
{
|
||||
var request = new RestRequest("authenticate", Method.GET);
|
||||
AuthenticationResponse response;
|
||||
if (TryRequest(request, out response))
|
||||
{
|
||||
return response.Success;
|
||||
}
|
||||
return false;
|
||||
using var request = new HttpRequestMessage(HttpMethod.Get, "authenticate");
|
||||
return TryRequest(request, out AuthenticationResponse response) && response.Success;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current client
|
||||
/// </summary>
|
||||
/// <param name="baseUrl">The client's base address</param>
|
||||
/// <param name="defaultHeaders">Default headers for the client</param>
|
||||
/// <param name="timeout">The client timeout in seconds</param>
|
||||
public void SetClient(string baseUrl, Dictionary<string, string> defaultHeaders = null, int timeout = 0)
|
||||
{
|
||||
if (_httpClient != null)
|
||||
{
|
||||
_httpClient.DisposeSafely();
|
||||
}
|
||||
|
||||
_httpClient = new HttpClient() { BaseAddress = new Uri($"{baseUrl.TrimEnd('/')}/") };
|
||||
Client = new RestClient(baseUrl);
|
||||
|
||||
if (defaultHeaders != null)
|
||||
{
|
||||
foreach (var header in defaultHeaders)
|
||||
{
|
||||
_httpClient.DefaultRequestHeaders.Add(header.Key, header.Value);
|
||||
}
|
||||
Client.AddDefaultHeaders(defaultHeaders);
|
||||
}
|
||||
|
||||
if (timeout > 0)
|
||||
{
|
||||
_httpClient.Timeout = TimeSpan.FromSeconds(timeout);
|
||||
Client.Timeout = timeout * 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
_httpClient.Timeout = Timeout.InfiniteTimeSpan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes of the HTTP client
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
_httpClient.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Place a secure request and get back an object of type T.
|
||||
/// </summary>
|
||||
@@ -77,6 +137,7 @@ namespace QuantConnect.Api
|
||||
/// <param name="request"></param>
|
||||
/// <param name="result">Result object from the </param>
|
||||
/// <returns>T typed object response</returns>
|
||||
[Obsolete("RestSharp is deprecated and will be removed in a future release. Please use the TryRequest(HttpRequestMessage)")]
|
||||
public bool TryRequest<T>(RestRequest request, out T result)
|
||||
where T : RestResponse
|
||||
{
|
||||
@@ -90,7 +151,24 @@ namespace QuantConnect.Api
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="result">Result object from the </param>
|
||||
/// <param name="timeout">Timeout for the request</param>
|
||||
/// <returns>T typed object response</returns>
|
||||
public bool TryRequest<T>(HttpRequestMessage request, out T result, TimeSpan? timeout = null)
|
||||
where T : RestResponse
|
||||
{
|
||||
var resultTuple = TryRequestAsync<T>(request, timeout).SynchronouslyAwaitTaskResult();
|
||||
result = resultTuple.Item2;
|
||||
return resultTuple.Item1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Place a secure request and get back an object of type T.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="request"></param>
|
||||
/// <returns>T typed object response</returns>
|
||||
[Obsolete("RestSharp is deprecated and will be removed in a future release. Please use the TryRequestAsync(HttpRequestMessage)")]
|
||||
public async Task<Tuple<bool, T>> TryRequestAsync<T>(RestRequest request)
|
||||
where T : RestResponse
|
||||
{
|
||||
@@ -116,7 +194,7 @@ namespace QuantConnect.Api
|
||||
}
|
||||
|
||||
responseContent = restsharpResponse.Content;
|
||||
result = JsonConvert.DeserializeObject<T>(responseContent, _jsonSettings);
|
||||
result = responseContent.DeserializeJson<T>();
|
||||
|
||||
if (result == null || !result.Success)
|
||||
{
|
||||
@@ -133,10 +211,106 @@ namespace QuantConnect.Api
|
||||
return new Tuple<bool, T>(true, result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Place a secure request and get back an object of type T.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="timeout">Timeout for the request</param>
|
||||
/// <returns>T typed object response</returns>
|
||||
public async Task<Tuple<bool, T>> TryRequestAsync<T>(HttpRequestMessage request, TimeSpan? timeout = null)
|
||||
where T : RestResponse
|
||||
{
|
||||
HttpResponseMessage response = null;
|
||||
Stream responseContentStream = null;
|
||||
T result = null;
|
||||
|
||||
// Default to 100 seconds (since we disabled the default client timeout)
|
||||
timeout ??= TimeSpan.FromSeconds(100);
|
||||
|
||||
try
|
||||
{
|
||||
if (request.RequestUri.OriginalString.StartsWith('/'))
|
||||
{
|
||||
request.RequestUri = new Uri(request.RequestUri.ToString().TrimStart('/'), UriKind.Relative);
|
||||
}
|
||||
|
||||
SetAuthenticator(request);
|
||||
|
||||
// Execute the authenticated REST API Call
|
||||
using var cancellationTokenSource = new CancellationTokenSource(timeout.Value);
|
||||
response = await _httpClient.SendAsync(request, cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
responseContentStream = await response.Content.ReadAsStreamAsync(cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
|
||||
result = responseContentStream.DeserializeJson<T>(leaveOpen: true);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
Log.Error($"ApiConnect.TryRequest({request.RequestUri}): HTTP Error: {(int)response.StatusCode} {response.ReasonPhrase}. " +
|
||||
$"Content: {GetRawResponseContent(responseContentStream)}");
|
||||
}
|
||||
if (result == null || !result.Success)
|
||||
{
|
||||
if (Log.DebuggingEnabled)
|
||||
{
|
||||
Log.Debug($"ApiConnection.TryRequest({request.RequestUri}): Raw response: '{GetRawResponseContent(responseContentStream)}'");
|
||||
}
|
||||
return new Tuple<bool, T>(false, result);
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
Log.Error($"ApiConnection.TryRequest({request.RequestUri}): Error: {err.Message}, Response content: {GetRawResponseContent(responseContentStream)}");
|
||||
return new Tuple<bool, T>(false, null);
|
||||
}
|
||||
finally
|
||||
{
|
||||
response?.DisposeSafely();
|
||||
responseContentStream?.DisposeSafely();
|
||||
}
|
||||
|
||||
return new Tuple<bool, T>(true, result);
|
||||
}
|
||||
|
||||
private static string GetRawResponseContent(Stream stream)
|
||||
{
|
||||
if (stream == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
stream.Position = 0;
|
||||
using var reader = new StreamReader(stream, leaveOpen: true);
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetAuthenticator(RestRequest request)
|
||||
{
|
||||
var newTimeStamp = (int)Time.TimeStamp();
|
||||
var base64EncodedAuthenticationString = GetAuthenticatorHeader(out var timeStamp);
|
||||
request.AddOrUpdateHeader("Authorization", $"Basic {base64EncodedAuthenticationString}");
|
||||
request.AddOrUpdateHeader("Timestamp", timeStamp);
|
||||
}
|
||||
|
||||
private void SetAuthenticator(HttpRequestMessage request)
|
||||
{
|
||||
request.Headers.Remove("Authorization");
|
||||
request.Headers.Remove("Timestamp");
|
||||
|
||||
var base64EncodedAuthenticationString = GetAuthenticatorHeader(out var timeStamp);
|
||||
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64EncodedAuthenticationString);
|
||||
request.Headers.Add("Timestamp", timeStamp);
|
||||
}
|
||||
|
||||
private string GetAuthenticatorHeader(out string timeStamp)
|
||||
{
|
||||
var newTimeStamp = (int)Time.TimeStamp();
|
||||
var currentAuth = _authenticator;
|
||||
if (currentAuth == null || newTimeStamp - currentAuth.TimeStamp > 7000)
|
||||
{
|
||||
@@ -144,25 +318,25 @@ namespace QuantConnect.Api
|
||||
// Add the UTC timestamp to the request header.
|
||||
// Timestamps older than 7200 seconds will not work.
|
||||
var hash = Api.CreateSecureHash(newTimeStamp, _token);
|
||||
var authenticator = new HttpBasicAuthenticator(_userId, hash);
|
||||
_authenticator = currentAuth = new LeanAuthenticator(authenticator, newTimeStamp);
|
||||
|
||||
Client.Authenticator = currentAuth.Authenticator;
|
||||
var authenticationString = $"{_userId}:{hash}";
|
||||
var base64EncodedAuthenticationString = Convert.ToBase64String(Encoding.UTF8.GetBytes(authenticationString));
|
||||
_authenticator = currentAuth = new LeanAuthenticator(newTimeStamp, base64EncodedAuthenticationString);
|
||||
}
|
||||
|
||||
request.AddHeader("Timestamp", currentAuth.TimeStampStr);
|
||||
timeStamp = currentAuth.TimeStampStr;
|
||||
return currentAuth.Base64EncodedAuthenticationString;
|
||||
}
|
||||
|
||||
private class LeanAuthenticator
|
||||
{
|
||||
public int TimeStamp { get; }
|
||||
public string TimeStampStr { get; }
|
||||
public HttpBasicAuthenticator Authenticator { get; }
|
||||
public LeanAuthenticator(HttpBasicAuthenticator authenticator, int timeStamp)
|
||||
public string Base64EncodedAuthenticationString { get; }
|
||||
public LeanAuthenticator(int timeStamp, string base64EncodedAuthenticationString)
|
||||
{
|
||||
TimeStamp = timeStamp;
|
||||
Authenticator = authenticator;
|
||||
TimeStampStr = timeStamp.ToStringInvariant();
|
||||
Base64EncodedAuthenticationString = base64EncodedAuthenticationString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user