Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d3733c0fb | ||
|
|
1303ccf843 | ||
|
|
3b5f3fcf42 | ||
|
|
e2de241c2b | ||
|
|
68e2a9170a | ||
|
|
d395f704b3 | ||
|
|
4d1fc7e05a | ||
|
|
e3a562d3c9 | ||
|
|
4fdd60d146 | ||
|
|
abbb50e209 | ||
|
|
0e1cc288a6 | ||
|
|
3b826535c7 | ||
|
|
59da486e30 | ||
|
|
f42d7bb3a2 | ||
|
|
87bd0d7792 | ||
|
|
8ca9258e70 | ||
|
|
72105539fc | ||
|
|
589e8a9293 | ||
|
|
dd27a382f7 | ||
|
|
62a8aee38c | ||
|
|
7e7c27416b | ||
|
|
26f2f88c67 | ||
|
|
c08c129860 | ||
|
|
bae10389ae | ||
|
|
4301d7cead | ||
|
|
d49f1d0d6c | ||
|
|
264c3c8374 | ||
|
|
8a1f67edfc | ||
|
|
5f434f2fa5 | ||
|
|
e37f8ae878 | ||
|
|
b4e95209f6 | ||
|
|
ea65c61dc8 | ||
|
|
6bf6ff1a6a | ||
|
|
d1a35e6281 |
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm reproducing GH issue #5971 where we add and remove an option in the same loop
|
||||
/// </summary>
|
||||
public class AddAndRemoveSecuritySameLoopRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _contract;
|
||||
private bool _hasRemoved;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2014, 06, 06);
|
||||
SetEndDate(2014, 06, 09);
|
||||
|
||||
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
|
||||
UniverseSettings.MinimumTimeInUniverse = TimeSpan.Zero;
|
||||
|
||||
var aapl = AddEquity("AAPL").Symbol;
|
||||
|
||||
_contract = OptionChainProvider.GetOptionContractList(aapl, Time)
|
||||
.OrderBy(symbol => symbol.ID.Symbol)
|
||||
.FirstOrDefault(optionContract => optionContract.ID.OptionRight == OptionRight.Call
|
||||
&& optionContract.ID.OptionStyle == OptionStyle.American);
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (_hasRemoved)
|
||||
{
|
||||
throw new Exception("Expect a single call to OnData where we removed the option and underlying");
|
||||
}
|
||||
|
||||
_hasRemoved = true;
|
||||
AddOptionContract(_contract);
|
||||
|
||||
// changed my mind!
|
||||
RemoveOptionContract(_contract);
|
||||
RemoveSecurity(_contract.Underlying);
|
||||
|
||||
RemoveSecurity(AddEquity("SPY", Resolution.Daily).Symbol);
|
||||
}
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_hasRemoved)
|
||||
{
|
||||
throw new Exception("We did not remove the option contract!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public Language[] Languages { get; } = { 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 Trades", "0"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-9.486"},
|
||||
{"Tracking Error", "0.008"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$0.00"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", ""},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
{"Long Insight Count", "0"},
|
||||
{"Short Insight Count", "0"},
|
||||
{"Long/Short Ratio", "100%"},
|
||||
{"Estimated Monthly Alpha Value", "$0"},
|
||||
{"Total Accumulated Estimated Alpha Value", "$0"},
|
||||
{"Mean Population Estimated Insight Value", "$0"},
|
||||
{"Mean Population Direction", "0%"},
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Securities.Future;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Continuous Futures Regression algorithm. Asserting and showcasing the behavior of adding a continuous future
|
||||
/// and a future contract at the same time
|
||||
/// </summary>
|
||||
public class AddFutureContractWithContinuousRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _currentMappedSymbol;
|
||||
private Future _continuousContract;
|
||||
private Future _futureContract;
|
||||
private bool _ended;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 6);
|
||||
SetEndDate(2013, 10, 10);
|
||||
|
||||
_continuousContract = AddFuture(Futures.Indices.SP500EMini,
|
||||
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
|
||||
dataMappingMode: DataMappingMode.LastTradingDay,
|
||||
contractDepthOffset: 0
|
||||
);
|
||||
|
||||
_futureContract = AddFutureContract(FutureChainProvider.GetFutureContractList(_continuousContract.Symbol, Time).First());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice data)
|
||||
{
|
||||
if (_ended)
|
||||
{
|
||||
throw new Exception($"Algorithm should of ended!");
|
||||
}
|
||||
if (data.Keys.Count > 2)
|
||||
{
|
||||
throw new Exception($"Getting data for more than 2 symbols! {string.Join(",", data.Keys.Select(symbol => symbol))}");
|
||||
}
|
||||
if (UniverseManager.Count != 3)
|
||||
{
|
||||
throw new Exception($"Expecting 3 universes (chain, continuous and user defined) but have {UniverseManager.Count}");
|
||||
}
|
||||
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
Buy(_futureContract.Symbol, 1);
|
||||
Buy(_continuousContract.Mapped, 1);
|
||||
|
||||
RemoveSecurity(_futureContract.Symbol);
|
||||
RemoveSecurity(_continuousContract.Symbol);
|
||||
|
||||
_ended = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
if (orderEvent.Status == OrderStatus.Filled)
|
||||
{
|
||||
Log($"{orderEvent}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
Debug($"{Time}-{changes}");
|
||||
|
||||
if (changes.AddedSecurities.Any(security => security.Symbol != _continuousContract.Symbol && security.Symbol != _futureContract.Symbol)
|
||||
|| changes.RemovedSecurities.Any(security => security.Symbol != _continuousContract.Symbol && security.Symbol != _futureContract.Symbol))
|
||||
{
|
||||
throw new Exception($"We got an unexpected security changes {changes}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public Language[] Languages { get; } = { 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 Trades", "3"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.03%"},
|
||||
{"Compounding Annual Return", "-2.503%"},
|
||||
{"Drawdown", "0.000%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-0.032%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.678"},
|
||||
{"Tracking Error", "0.243"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$7.40"},
|
||||
{"Estimated Strategy Capacity", "$2100000.00"},
|
||||
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
|
||||
{"Fitness Score", "0.419"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "-81.557"},
|
||||
{"Portfolio Turnover", "0.837"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
{"Long Insight Count", "0"},
|
||||
{"Short Insight Count", "0"},
|
||||
{"Long/Short Ratio", "100%"},
|
||||
{"Estimated Monthly Alpha Value", "$0"},
|
||||
{"Total Accumulated Estimated Alpha Value", "$0"},
|
||||
{"Mean Population Estimated Insight Value", "$0"},
|
||||
{"Mean Population Direction", "0%"},
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "68775c18eb40c1bde212653faec4016e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
165
Algorithm.CSharp/AddOptionContractTwiceRegressionAlgorithm.cs
Normal file
165
Algorithm.CSharp/AddOptionContractTwiceRegressionAlgorithm.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm reproducing GH issue #6073 where we remove and re add an option and expect it to work
|
||||
/// </summary>
|
||||
public class AddOptionContractTwiceRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Symbol _contract;
|
||||
private bool _hasRemoved;
|
||||
private bool _reAdded;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2014, 06, 06);
|
||||
SetEndDate(2014, 06, 09);
|
||||
|
||||
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
|
||||
UniverseSettings.MinimumTimeInUniverse = TimeSpan.Zero;
|
||||
UniverseSettings.FillForward = false;
|
||||
|
||||
AddEquity("SPY", Resolution.Daily);
|
||||
|
||||
var aapl = QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA);
|
||||
|
||||
_contract = OptionChainProvider.GetOptionContractList(aapl, Time)
|
||||
.OrderBy(symbol => symbol.ID.Symbol)
|
||||
.FirstOrDefault(optionContract => optionContract.ID.OptionRight == OptionRight.Call
|
||||
&& optionContract.ID.OptionStyle == OptionStyle.American);
|
||||
AddOptionContract(_contract);
|
||||
}
|
||||
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (_hasRemoved)
|
||||
{
|
||||
if (!_reAdded && slice.ContainsKey(_contract) && slice.ContainsKey(_contract.Underlying))
|
||||
{
|
||||
throw new Exception("Getting data for removed option and underlying!");
|
||||
}
|
||||
|
||||
if (!Portfolio.Invested && _reAdded)
|
||||
{
|
||||
var option = Securities[_contract];
|
||||
var optionUnderlying = Securities[_contract.Underlying];
|
||||
if (option.IsTradable && optionUnderlying.IsTradable
|
||||
&& slice.ContainsKey(_contract) && slice.ContainsKey(_contract.Underlying))
|
||||
{
|
||||
Buy(_contract, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Securities[_contract].IsTradable
|
||||
&& !Securities[_contract.Underlying].IsTradable
|
||||
&& !_reAdded)
|
||||
{
|
||||
// ha changed my mind!
|
||||
AddOptionContract(_contract);
|
||||
_reAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (slice.ContainsKey(_contract) && slice.ContainsKey(_contract.Underlying))
|
||||
{
|
||||
if (!_hasRemoved)
|
||||
{
|
||||
RemoveOptionContract(_contract);
|
||||
RemoveSecurity(_contract.Underlying);
|
||||
_hasRemoved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
if (!_hasRemoved)
|
||||
{
|
||||
throw new Exception("We did not remove the option contract!");
|
||||
}
|
||||
if (!_reAdded)
|
||||
{
|
||||
throw new Exception("We did not re add the option contract!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public Language[] Languages { get; } = { 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 Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.05%"},
|
||||
{"Compounding Annual Return", "-4.548%"},
|
||||
{"Drawdown", "0.100%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-0.051%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-9.486"},
|
||||
{"Tracking Error", "0.008"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$2.00"},
|
||||
{"Estimated Strategy Capacity", "$30000.00"},
|
||||
{"Lowest Capacity Asset", "AAPL VXBK4Q9ZIFD2|AAPL R735QTJ8XC9X"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "-89.181"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
{"Long Insight Count", "0"},
|
||||
{"Short Insight Count", "0"},
|
||||
{"Long/Short Ratio", "100%"},
|
||||
{"Estimated Monthly Alpha Value", "$0"},
|
||||
{"Total Accumulated Estimated Alpha Value", "$0"},
|
||||
{"Mean Population Estimated Insight Value", "$0"},
|
||||
{"Mean Population Direction", "0%"},
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "7fbcd12db40304d50b3a34d7878eb3cf"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -86,10 +86,10 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "93.443%"},
|
||||
{"Compounding Annual Return", "93.340%"},
|
||||
{"Drawdown", "1.100%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0.847%"},
|
||||
{"Net Profit", "0.846%"},
|
||||
{"Sharpe Ratio", "6.515"},
|
||||
{"Probabilistic Sharpe Ratio", "67.535%"},
|
||||
{"Loss Rate", "0%"},
|
||||
@@ -102,14 +102,14 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Information Ratio", "6.515"},
|
||||
{"Tracking Error", "0.11"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$0.52"},
|
||||
{"Total Fees", "$1.20"},
|
||||
{"Estimated Strategy Capacity", "$8600000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Fitness Score", "0.124"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "78.376"},
|
||||
{"Return Over Maximum Drawdown", "78.222"},
|
||||
{"Portfolio Turnover", "0.124"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
|
||||
161
Algorithm.CSharp/BasicTemplateContinuousFutureAlgorithm.cs
Normal file
161
Algorithm.CSharp/BasicTemplateContinuousFutureAlgorithm.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Future;
|
||||
using Futures = QuantConnect.Securities.Futures;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic Continuous Futures Template Algorithm
|
||||
/// </summary>
|
||||
public class BasicTemplateContinuousFutureAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private Future _continuousContract;
|
||||
private Security _currentContract;
|
||||
private SimpleMovingAverage _fast;
|
||||
private SimpleMovingAverage _slow;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 7, 1);
|
||||
SetEndDate(2014, 1, 1);
|
||||
|
||||
_continuousContract = AddFuture(Futures.Indices.SP500EMini,
|
||||
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
|
||||
dataMappingMode: DataMappingMode.LastTradingDay,
|
||||
contractDepthOffset: 0
|
||||
);
|
||||
|
||||
_fast = SMA(_continuousContract.Symbol, 3, Resolution.Daily);
|
||||
_slow = SMA(_continuousContract.Symbol, 10, Resolution.Daily);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice data)
|
||||
{
|
||||
foreach (var changedEvent in data.SymbolChangedEvents.Values)
|
||||
{
|
||||
Log($"{Time} - SymbolChanged event: {changedEvent}");
|
||||
}
|
||||
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
if(_fast > _slow)
|
||||
{
|
||||
_currentContract = Securities[_continuousContract.Mapped];
|
||||
Buy(_currentContract.Symbol, 1);
|
||||
}
|
||||
}
|
||||
else if(_fast < _slow)
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
|
||||
if (_currentContract != null && _currentContract.Symbol != _continuousContract.Mapped)
|
||||
{
|
||||
Log($"{Time} - rolling position from {_currentContract.Symbol} to {_continuousContract.Mapped}");
|
||||
|
||||
var currentPositionSize = _currentContract.Holdings.Quantity;
|
||||
Liquidate(_currentContract.Symbol);
|
||||
Buy(_continuousContract.Mapped, currentPositionSize);
|
||||
_currentContract = Securities[_continuousContract.Mapped];
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Debug($"{orderEvent}");
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
Debug($"{Time}-{changes}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public Language[] Languages { get; } = { Language.CSharp, Language.Python };
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "-0.007%"},
|
||||
{"Drawdown", "0.000%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "-0.004%"},
|
||||
{"Sharpe Ratio", "-0.369"},
|
||||
{"Probabilistic Sharpe Ratio", "10.640%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-2.751"},
|
||||
{"Tracking Error", "0.082"},
|
||||
{"Treynor Ratio", "-0.616"},
|
||||
{"Total Fees", "$3.70"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
|
||||
{"Fitness Score", "0.007"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "-0.738"},
|
||||
{"Portfolio Turnover", "0.01"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
{"Long Insight Count", "0"},
|
||||
{"Short Insight Count", "0"},
|
||||
{"Long/Short Ratio", "100%"},
|
||||
{"Estimated Monthly Alpha Value", "$0"},
|
||||
{"Total Accumulated Estimated Alpha Value", "$0"},
|
||||
{"Mean Population Estimated Insight Value", "$0"},
|
||||
{"Mean Population Direction", "0%"},
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "bd7fbe57802dfedb36c85609b7234016"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -131,30 +131,30 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Average Win", "0.00%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "-100.000%"},
|
||||
{"Drawdown", "13.400%"},
|
||||
{"Drawdown", "13.500%"},
|
||||
{"Expectancy", "-0.818"},
|
||||
{"Net Profit", "-13.418%"},
|
||||
{"Sharpe Ratio", "-321.172"},
|
||||
{"Net Profit", "-13.517%"},
|
||||
{"Sharpe Ratio", "-98.781"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "89%"},
|
||||
{"Win Rate", "11%"},
|
||||
{"Profit-Loss Ratio", "0.69"},
|
||||
{"Alpha", "-1.208"},
|
||||
{"Beta", "0.013"},
|
||||
{"Annual Standard Deviation", "0.003"},
|
||||
{"Alpha", "-1.676"},
|
||||
{"Beta", "0.042"},
|
||||
{"Annual Standard Deviation", "0.01"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-71.816"},
|
||||
{"Tracking Error", "0.24"},
|
||||
{"Treynor Ratio", "-77.951"},
|
||||
{"Information Ratio", "-73.981"},
|
||||
{"Tracking Error", "0.233"},
|
||||
{"Treynor Ratio", "-23.975"},
|
||||
{"Total Fees", "$15207.00"},
|
||||
{"Estimated Strategy Capacity", "$8000.00"},
|
||||
{"Lowest Capacity Asset", "GC VOFJUCDY9XNH"},
|
||||
{"Fitness Score", "0.031"},
|
||||
{"Fitness Score", "0.033"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "-9.206"},
|
||||
{"Return Over Maximum Drawdown", "-7.871"},
|
||||
{"Portfolio Turnover", "302.123"},
|
||||
{"Sortino Ratio", "-8.62"},
|
||||
{"Return Over Maximum Drawdown", "-7.81"},
|
||||
{"Portfolio Turnover", "302.321"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
@@ -168,7 +168,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "9e50b7d8e41033110f927658e731f4c6"}
|
||||
{"OrderListHash", "35b3f4b7a225468d42ca085386a2383e"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
SetEndDate(2019, 2, 21);
|
||||
SetCash("EUR", 100000);
|
||||
|
||||
_symbol = AddCfd("DE30EUR", Resolution.Minute, Market.Oanda).Symbol;
|
||||
_symbol = AddCfd("DE30EUR").Symbol;
|
||||
|
||||
SetBenchmark(_symbol);
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
}
|
||||
}
|
||||
|
||||
if (_lastDateLog.Month != Time.Month)
|
||||
if (_lastDateLog.Month != Time.Month && _continuousContract.HasData)
|
||||
{
|
||||
_lastDateLog = Time;
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
else if(_continuousContract.HasData)
|
||||
else
|
||||
{
|
||||
// This works because we set this contract as tradable, even if it's a canonical security
|
||||
Buy(_continuousContract.Symbol, 1);
|
||||
@@ -138,33 +138,33 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "1.11%"},
|
||||
{"Average Win", "1.16%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "2.199%"},
|
||||
{"Drawdown", "1.700%"},
|
||||
{"Compounding Annual Return", "2.311%"},
|
||||
{"Drawdown", "1.600%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "1.109%"},
|
||||
{"Sharpe Ratio", "0.717"},
|
||||
{"Probabilistic Sharpe Ratio", "38.157%"},
|
||||
{"Net Profit", "1.159%"},
|
||||
{"Sharpe Ratio", "0.753"},
|
||||
{"Probabilistic Sharpe Ratio", "39.483%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.007"},
|
||||
{"Alpha", "-0.006"},
|
||||
{"Beta", "0.099"},
|
||||
{"Annual Standard Deviation", "0.022"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-2.732"},
|
||||
{"Tracking Error", "0.076"},
|
||||
{"Treynor Ratio", "0.156"},
|
||||
{"Treynor Ratio", "0.165"},
|
||||
{"Total Fees", "$3.70"},
|
||||
{"Estimated Strategy Capacity", "$3900000.00"},
|
||||
{"Lowest Capacity Asset", "ES 1S1"},
|
||||
{"Fitness Score", "0.007"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0.484"},
|
||||
{"Return Over Maximum Drawdown", "1.736"},
|
||||
{"Portfolio Turnover", "0.011"},
|
||||
{"Sortino Ratio", "0.563"},
|
||||
{"Return Over Maximum Drawdown", "1.87"},
|
||||
{"Portfolio Turnover", "0.01"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
@@ -178,7 +178,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "7d6fb409115f2f8d403c7eb261b9b3b6"}
|
||||
{"OrderListHash", "8aa2ed1319e8bb5beb403476a5aebfef"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
}
|
||||
}
|
||||
|
||||
if (_lastDateLog.Month != Time.Month)
|
||||
if (_lastDateLog.Month != Time.Month && _continuousContract.HasData)
|
||||
{
|
||||
_lastDateLog = Time;
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
else if(_continuousContract.HasData)
|
||||
else
|
||||
{
|
||||
// This works because we set this contract as tradable, even if it's a canonical security
|
||||
Buy(_continuousContract.Symbol, 1);
|
||||
@@ -151,14 +151,14 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "3"},
|
||||
{"Average Win", "1.11%"},
|
||||
{"Average Win", "1.16%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "2.092%"},
|
||||
{"Drawdown", "1.700%"},
|
||||
{"Compounding Annual Return", "2.229%"},
|
||||
{"Drawdown", "1.600%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "1.055%"},
|
||||
{"Sharpe Ratio", "0.682"},
|
||||
{"Probabilistic Sharpe Ratio", "36.937%"},
|
||||
{"Net Profit", "1.118%"},
|
||||
{"Sharpe Ratio", "0.726"},
|
||||
{"Probabilistic Sharpe Ratio", "38.511%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
@@ -166,18 +166,18 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Beta", "0.099"},
|
||||
{"Annual Standard Deviation", "0.022"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-2.742"},
|
||||
{"Information Ratio", "-2.74"},
|
||||
{"Tracking Error", "0.076"},
|
||||
{"Treynor Ratio", "0.149"},
|
||||
{"Treynor Ratio", "0.159"},
|
||||
{"Total Fees", "$5.55"},
|
||||
{"Estimated Strategy Capacity", "$190000.00"},
|
||||
{"Estimated Strategy Capacity", "$290000.00"},
|
||||
{"Lowest Capacity Asset", "ES 1S1"},
|
||||
{"Fitness Score", "0.01"},
|
||||
{"Fitness Score", "0.009"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0.479"},
|
||||
{"Return Over Maximum Drawdown", "1.652"},
|
||||
{"Portfolio Turnover", "0.015"},
|
||||
{"Sortino Ratio", "0.498"},
|
||||
{"Return Over Maximum Drawdown", "1.803"},
|
||||
{"Portfolio Turnover", "0.014"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
@@ -191,7 +191,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "9f7574803b8ebfac8f912019c943d27e"}
|
||||
{"OrderListHash", "e669103cc598f59d85f5e8d5f0b8df30"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Securities.Future;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
@@ -90,6 +91,16 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
Debug($"{Time}-{changes}");
|
||||
if (changes.AddedSecurities.Any(security => security.Symbol != _continuousContract.Symbol)
|
||||
|| changes.RemovedSecurities.Any(security => security.Symbol != _continuousContract.Symbol))
|
||||
{
|
||||
throw new Exception($"We got an unexpected security changes {changes}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
|
||||
@@ -22,6 +22,7 @@ using QuantConnect.Securities;
|
||||
using QuantConnect.Data.Market;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Securities.Future;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
@@ -31,8 +32,9 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public class ContinuousFutureRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private List<SymbolChangedEvent> _mappings = new();
|
||||
private Symbol _currentMappedSymbol;
|
||||
private Future _continuousContract;
|
||||
private DateTime _lastDateLog;
|
||||
private DateTime _lastMonth;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
@@ -55,6 +57,17 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice data)
|
||||
{
|
||||
// we subtract a minute cause we can get data on the market close, from the previous minute
|
||||
if (!_continuousContract.Exchange.DateTimeIsOpen(Time.AddMinutes(-1)))
|
||||
{
|
||||
if (data.Bars.Count > 0 || data.QuoteBars.Count > 0)
|
||||
{
|
||||
throw new Exception($"We are getting data during closed market!");
|
||||
}
|
||||
}
|
||||
|
||||
var currentlyMappedSecurity = Securities[_continuousContract.Mapped];
|
||||
|
||||
if (data.Keys.Count != 1)
|
||||
{
|
||||
throw new Exception($"We are getting data for more than one symbols! {string.Join(",", data.Keys.Select(symbol => symbol))}");
|
||||
@@ -65,7 +78,12 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
if (changedEvent.Symbol == _continuousContract.Symbol)
|
||||
{
|
||||
_mappings.Add(changedEvent);
|
||||
Log($"SymbolChanged event: {changedEvent}");
|
||||
Log($"{Time} - SymbolChanged event: {changedEvent}");
|
||||
|
||||
if (_currentMappedSymbol == _continuousContract.Mapped)
|
||||
{
|
||||
throw new Exception($"Continuous contract current symbol did not change! {_continuousContract.Mapped}");
|
||||
}
|
||||
|
||||
var currentExpiration = changedEvent.Symbol.Underlying.ID.Date;
|
||||
var frontMonthExpiration = FuturesExpiryFunctions.FuturesExpiryFunction(_continuousContract.Symbol)(Time.AddMonths(1));
|
||||
@@ -77,20 +95,19 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_lastDateLog.Month != Time.Month)
|
||||
if (_lastMonth.Month != Time.Month && currentlyMappedSecurity.HasData)
|
||||
{
|
||||
_lastDateLog = Time;
|
||||
_lastMonth = Time;
|
||||
|
||||
Log($"{Time}- {Securities[_continuousContract.Symbol].GetLastData()}");
|
||||
Log($"{Time}- {currentlyMappedSecurity.GetLastData()}");
|
||||
if (Portfolio.Invested)
|
||||
{
|
||||
Liquidate();
|
||||
}
|
||||
else if(_continuousContract.HasData)
|
||||
else
|
||||
{
|
||||
// This works because we set this contract as tradable, even if it's a canonical security
|
||||
Buy(_continuousContract.Symbol, 1);
|
||||
Buy(currentlyMappedSecurity.Symbol, 1);
|
||||
}
|
||||
|
||||
if(Time.Month == 1 && Time.Year == 2013)
|
||||
@@ -102,6 +119,8 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_currentMappedSymbol = _continuousContract.Mapped;
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
@@ -112,6 +131,16 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
Debug($"{Time}-{changes}");
|
||||
if (changes.AddedSecurities.Any(security => security.Symbol != _continuousContract.Symbol)
|
||||
|| changes.RemovedSecurities.Any(security => security.Symbol != _continuousContract.Symbol))
|
||||
{
|
||||
throw new Exception($"We got an unexpected security changes {changes}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEndOfAlgorithm()
|
||||
{
|
||||
var expectedMappingCounts = 2;
|
||||
@@ -137,32 +166,32 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "3"},
|
||||
{"Average Win", "1.03%"},
|
||||
{"Average Win", "1.21%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "1.970%"},
|
||||
{"Drawdown", "1.400%"},
|
||||
{"Compounding Annual Return", "2.392%"},
|
||||
{"Drawdown", "1.600%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0.994%"},
|
||||
{"Sharpe Ratio", "0.7"},
|
||||
{"Probabilistic Sharpe Ratio", "37.553%"},
|
||||
{"Net Profit", "1.199%"},
|
||||
{"Sharpe Ratio", "0.775"},
|
||||
{"Probabilistic Sharpe Ratio", "40.287%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "100%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.006"},
|
||||
{"Beta", "0.091"},
|
||||
{"Annual Standard Deviation", "0.02"},
|
||||
{"Beta", "0.099"},
|
||||
{"Annual Standard Deviation", "0.022"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-2.745"},
|
||||
{"Information Ratio", "-2.726"},
|
||||
{"Tracking Error", "0.076"},
|
||||
{"Treynor Ratio", "0.153"},
|
||||
{"Treynor Ratio", "0.169"},
|
||||
{"Total Fees", "$5.55"},
|
||||
{"Estimated Strategy Capacity", "$48000000.00"},
|
||||
{"Lowest Capacity Asset", "ES 1S1"},
|
||||
{"Estimated Strategy Capacity", "$0"},
|
||||
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
|
||||
{"Fitness Score", "0.01"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0.492"},
|
||||
{"Return Over Maximum Drawdown", "1.708"},
|
||||
{"Sortino Ratio", "0.516"},
|
||||
{"Return Over Maximum Drawdown", "1.935"},
|
||||
{"Portfolio Turnover", "0.016"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
@@ -177,7 +206,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "fb3bb82d84fc6c390a40f36d0d1faf59"}
|
||||
{"OrderListHash", "8ad040c62ad255e4f9cd423364147e85"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Average Win", "1.64%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "7.329%"},
|
||||
{"Drawdown", "1.500%"},
|
||||
{"Drawdown", "1.300%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "1.642%"},
|
||||
{"Sharpe Ratio", "2.36"},
|
||||
|
||||
@@ -109,7 +109,6 @@ namespace QuantConnect.Algorithm.Framework
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the provided <paramref name="add"/> and <paramref name="remove"/> functions for each
|
||||
/// <seealso cref="SecurityChanges.Added"/> and <seealso cref="SecurityChanges.Removed"/>, respectively
|
||||
/// </summary>
|
||||
/// <param name="changes">The security changes to process</param>
|
||||
/// <param name="add">Function called for each added security</param>
|
||||
@@ -126,4 +125,4 @@ namespace QuantConnect.Algorithm.Framework
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
66
Algorithm.Python/BasicTemplateContinuousFutureAlgorithm.py
Normal file
66
Algorithm.Python/BasicTemplateContinuousFutureAlgorithm.py
Normal file
@@ -0,0 +1,66 @@
|
||||
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from AlgorithmImports import *
|
||||
|
||||
### <summary>
|
||||
### Basic Continuous Futures Template Algorithm
|
||||
### </summary>
|
||||
class BasicTemplateContinuousFutureAlgorithm(QCAlgorithm):
|
||||
'''Basic template algorithm simply initializes the date range and cash'''
|
||||
|
||||
def Initialize(self):
|
||||
'''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''
|
||||
|
||||
self.SetStartDate(2013, 7, 1)
|
||||
self.SetEndDate(2014, 1, 1)
|
||||
|
||||
self._continuousContract = self.AddFuture(Futures.Indices.SP500EMini,
|
||||
dataNormalizationMode = DataNormalizationMode.BackwardsRatio,
|
||||
dataMappingMode = DataMappingMode.LastTradingDay,
|
||||
contractDepthOffset= 0)
|
||||
|
||||
self._fast = self.SMA(self._continuousContract.Symbol, 3, Resolution.Daily)
|
||||
self._slow = self.SMA(self._continuousContract.Symbol, 10, Resolution.Daily)
|
||||
self._currentContract = None
|
||||
|
||||
def OnData(self, data):
|
||||
'''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
|
||||
Arguments:
|
||||
data: Slice object keyed by symbol containing the stock data
|
||||
'''
|
||||
for changedEvent in data.SymbolChangedEvents.Values:
|
||||
if changedEvent.Symbol == self._continuousContract.Symbol:
|
||||
self.Log(f"SymbolChanged event: {changedEvent}")
|
||||
|
||||
if not self.Portfolio.Invested:
|
||||
if self._fast.Current.Value > self._slow.Current.Value:
|
||||
self._currentContract = self.Securities[self._continuousContract.Mapped]
|
||||
self.Buy(self._currentContract.Symbol, 1)
|
||||
elif self._fast.Current.Value < self._slow.Current.Value:
|
||||
self.Liquidate()
|
||||
|
||||
if self._currentContract is not None and self._currentContract.Symbol != self._continuousContract.Mapped:
|
||||
self.Log(f"{Time} - rolling position from {self._currentContract.Symbol} to {self._continuousContract.Mapped}")
|
||||
|
||||
currentPositionSize = self._currentContract.Holdings.Quantity
|
||||
self.Liquidate(self._currentContract.Symbol)
|
||||
self.Buy(self._continuousContract.Mapped, currentPositionSize)
|
||||
self._currentContract = self.Securities[self._continuousContract.Mapped]
|
||||
|
||||
def OnOrderEvent(self, orderEvent):
|
||||
self.Debug("Purchased Stock: {0}".format(orderEvent.Symbol))
|
||||
|
||||
def OnSecuritiesChanged(self, changes):
|
||||
self.Debug(f"{self.Time}-{changes}")
|
||||
@@ -31,6 +31,7 @@ class ContinuousFutureRegressionAlgorithm(QCAlgorithm):
|
||||
dataNormalizationMode = DataNormalizationMode.BackwardsRatio,
|
||||
dataMappingMode = DataMappingMode.LastTradingDay,
|
||||
contractDepthOffset= 0)
|
||||
self._currentMappedSymbol = self._continuousContract.Symbol;
|
||||
|
||||
def OnData(self, data):
|
||||
'''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
@@ -38,6 +39,7 @@ class ContinuousFutureRegressionAlgorithm(QCAlgorithm):
|
||||
Arguments:
|
||||
data: Slice object keyed by symbol containing the stock data
|
||||
'''
|
||||
currentlyMappedSecurity = self.Securities[self._continuousContract.Mapped]
|
||||
if len(data.Keys) != 1:
|
||||
raise ValueError(f"We are getting data for more than one symbols! {','.join(data.Keys)}")
|
||||
|
||||
@@ -46,25 +48,33 @@ class ContinuousFutureRegressionAlgorithm(QCAlgorithm):
|
||||
self._mappings.append(changedEvent)
|
||||
self.Log(f"SymbolChanged event: {changedEvent}")
|
||||
|
||||
if self._lastDateLog != self.Time.month:
|
||||
if self._currentMappedSymbol == self._continuousContract.Mapped:
|
||||
raise ValueError(f"Continuous contract current symbol did not change! {self._continuousContract.Mapped}")
|
||||
|
||||
if self._lastDateLog != self.Time.month and currentlyMappedSecurity.HasData:
|
||||
self._lastDateLog = self.Time.month
|
||||
|
||||
self.Log(f"{self.Time}- {self._continuousContract.GetLastData()}")
|
||||
self.Log(f"{self.Time}- {currentlyMappedSecurity.GetLastData()}")
|
||||
if self.Portfolio.Invested:
|
||||
self.Liquidate()
|
||||
elif self._continuousContract.HasData:
|
||||
else:
|
||||
# This works because we set this contract as tradable, even if it's a canonical security
|
||||
self.Buy(self._continuousContract.Symbol, 1)
|
||||
self.Buy(currentlyMappedSecurity.Symbol, 1)
|
||||
|
||||
if self.Time.month == 1 and self.Time.year == 2013:
|
||||
response = self.History( [ self._continuousContract.Symbol ], 60 * 24 * 90)
|
||||
if response.empty:
|
||||
raise ValueError("Unexpected empty history response")
|
||||
|
||||
self._currentMappedSymbol = self._continuousContract.Mapped
|
||||
|
||||
def OnOrderEvent(self, orderEvent):
|
||||
if orderEvent.Status == OrderStatus.Filled:
|
||||
self.Debug("Purchased Stock: {0}".format(orderEvent.Symbol))
|
||||
|
||||
def OnSecuritiesChanged(self, changes):
|
||||
self.Debug(f"{self.Time}-{changes}")
|
||||
|
||||
def OnEndOfAlgorithm(self):
|
||||
expectedMappingCounts = 2
|
||||
if len(self._mappings) != expectedMappingCounts:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
@@ -28,6 +28,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Sets the alpha model
|
||||
/// </summary>
|
||||
/// <param name="alpha">Model that generates alpha</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void SetAlpha(PyObject alpha)
|
||||
{
|
||||
IAlphaModel model;
|
||||
@@ -45,6 +46,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Adds a new alpha model
|
||||
/// </summary>
|
||||
/// <param name="alpha">Model that generates alpha to add</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void AddAlpha(PyObject alpha)
|
||||
{
|
||||
IAlphaModel model;
|
||||
@@ -62,6 +64,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Sets the execution model
|
||||
/// </summary>
|
||||
/// <param name="execution">Model defining how to execute trades to reach a portfolio target</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetExecution(PyObject execution)
|
||||
{
|
||||
IExecutionModel model;
|
||||
@@ -79,6 +83,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Sets the portfolio construction model
|
||||
/// </summary>
|
||||
/// <param name="portfolioConstruction">Model defining how to build a portfolio from alphas</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetPortfolioConstruction(PyObject portfolioConstruction)
|
||||
{
|
||||
IPortfolioConstructionModel model;
|
||||
@@ -96,6 +102,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Sets the universe selection model
|
||||
/// </summary>
|
||||
/// <param name="universeSelection">Model defining universes for the algorithm</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void SetUniverseSelection(PyObject universeSelection)
|
||||
{
|
||||
IUniverseSelectionModel model;
|
||||
@@ -110,6 +118,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Adds a new universe selection model
|
||||
/// </summary>
|
||||
/// <param name="universeSelection">Model defining universes for the algorithm to add</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void AddUniverseSelection(PyObject universeSelection)
|
||||
{
|
||||
IUniverseSelectionModel model;
|
||||
@@ -124,6 +134,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Sets the risk management model
|
||||
/// </summary>
|
||||
/// <param name="riskManagement">Model defining how risk is managed</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetRiskManagement(PyObject riskManagement)
|
||||
{
|
||||
IRiskManagementModel model;
|
||||
@@ -141,6 +153,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Adds a new risk management model
|
||||
/// </summary>
|
||||
/// <param name="riskManagement">Model defining how risk is managed to add</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void AddRiskManagement(PyObject riskManagement)
|
||||
{
|
||||
IRiskManagementModel model;
|
||||
@@ -151,4 +165,4 @@ namespace QuantConnect.Algorithm
|
||||
AddRiskManagement(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
@@ -38,37 +38,44 @@ namespace QuantConnect.Algorithm
|
||||
/// Enables additional logging of framework models including:
|
||||
/// All insights, portfolio targets, order events, and any risk management altered targets
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Logging)]
|
||||
public bool DebugMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the universe selection model.
|
||||
/// </summary>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public IUniverseSelectionModel UniverseSelection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the alpha model
|
||||
/// </summary>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public IAlphaModel Alpha { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the portfolio construction model
|
||||
/// </summary>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public IPortfolioConstructionModel PortfolioConstruction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the execution model
|
||||
/// </summary>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public IExecutionModel Execution { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the risk management model
|
||||
/// </summary>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
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
|
||||
/// </summary>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void FrameworkPostInitialize()
|
||||
{
|
||||
//Prevents execution in the case of cash brokerage with IExecutionModel and IPortfolioConstructionModel
|
||||
@@ -97,6 +104,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Used to send data updates to algorithm framework models
|
||||
/// </summary>
|
||||
/// <param name="slice">The current data slice</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(HandlingData)]
|
||||
public void OnFrameworkData(Slice slice)
|
||||
{
|
||||
if (UtcTime >= UniverseSelection.GetNextRefreshTimeUtc())
|
||||
@@ -170,6 +179,7 @@ namespace QuantConnect.Algorithm
|
||||
/// and the <see cref="IExecutionModel"/> will execute the <see cref="IPortfolioTarget"/>
|
||||
/// </summary>
|
||||
/// <param name="insights">The insight to process</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
private void ProcessInsights(Insight[] insights)
|
||||
{
|
||||
// construct portfolio targets from insights
|
||||
@@ -244,6 +254,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Used to send security changes to algorithm framework models
|
||||
/// </summary>
|
||||
/// <param name="changes">Security additions/removals for this time step</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void OnFrameworkSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
if (DebugMode)
|
||||
@@ -261,6 +273,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Sets the universe selection model
|
||||
/// </summary>
|
||||
/// <param name="universeSelection">Model defining universes for the algorithm</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void SetUniverseSelection(IUniverseSelectionModel universeSelection)
|
||||
{
|
||||
UniverseSelection = universeSelection;
|
||||
@@ -270,6 +284,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Adds a new universe selection model
|
||||
/// </summary>
|
||||
/// <param name="universeSelection">Model defining universes for the algorithm to add</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void AddUniverseSelection(IUniverseSelectionModel universeSelection)
|
||||
{
|
||||
if (UniverseSelection.GetType() != typeof(NullUniverseSelectionModel))
|
||||
@@ -294,6 +310,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Sets the alpha model
|
||||
/// </summary>
|
||||
/// <param name="alpha">Model that generates alpha</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void SetAlpha(IAlphaModel alpha)
|
||||
{
|
||||
Alpha = alpha;
|
||||
@@ -303,6 +320,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Adds a new alpha model
|
||||
/// </summary>
|
||||
/// <param name="alpha">Model that generates alpha to add</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void AddAlpha(IAlphaModel alpha)
|
||||
{
|
||||
if (Alpha.GetType() != typeof(NullAlphaModel))
|
||||
@@ -327,6 +345,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Sets the portfolio construction model
|
||||
/// </summary>
|
||||
/// <param name="portfolioConstruction">Model defining how to build a portfolio from insights</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetPortfolioConstruction(IPortfolioConstructionModel portfolioConstruction)
|
||||
{
|
||||
PortfolioConstruction = portfolioConstruction;
|
||||
@@ -336,6 +356,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Sets the execution model
|
||||
/// </summary>
|
||||
/// <param name="execution">Model defining how to execute trades to reach a portfolio target</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetExecution(IExecutionModel execution)
|
||||
{
|
||||
Execution = execution;
|
||||
@@ -345,6 +367,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Sets the risk management model
|
||||
/// </summary>
|
||||
/// <param name="riskManagement">Model defining how risk is managed</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetRiskManagement(IRiskManagementModel riskManagement)
|
||||
{
|
||||
RiskManagement = riskManagement;
|
||||
@@ -354,6 +378,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Adds a new risk management model
|
||||
/// </summary>
|
||||
/// <param name="riskManagement">Model defining how risk is managed to add</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void AddRiskManagement(IRiskManagementModel riskManagement)
|
||||
{
|
||||
if (RiskManagement.GetType() != typeof(NullRiskManagementModel))
|
||||
@@ -380,6 +406,7 @@ namespace QuantConnect.Algorithm
|
||||
/// QCAlgorithm that have been ported into the algorithm framework.
|
||||
/// </summary>
|
||||
/// <param name="insights">The array of insights to be emitted</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void EmitInsights(params Insight[] insights)
|
||||
{
|
||||
if (IsWarmingUp)
|
||||
@@ -403,6 +430,7 @@ namespace QuantConnect.Algorithm
|
||||
/// QCAlgorithm that have been ported into the algorithm framework.
|
||||
/// </summary>
|
||||
/// <param name="insight">The insight to be emitted</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void EmitInsights(Insight insight)
|
||||
{
|
||||
EmitInsights(new[] { insight });
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Gets whether or not this algorithm is still warming up
|
||||
/// </summary>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public bool IsWarmingUp
|
||||
{
|
||||
get;
|
||||
@@ -49,6 +50,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Sets the warm up period to the specified value
|
||||
/// </summary>
|
||||
/// <param name="timeSpan">The amount of time to warm up, this does not take into account market hours/weekends</param>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public void SetWarmup(TimeSpan timeSpan)
|
||||
{
|
||||
SetWarmUp(timeSpan, null);
|
||||
@@ -58,6 +60,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Sets the warm up period to the specified value
|
||||
/// </summary>
|
||||
/// <param name="timeSpan">The amount of time to warm up, this does not take into account market hours/weekends</param>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public void SetWarmUp(TimeSpan timeSpan)
|
||||
{
|
||||
SetWarmup(timeSpan);
|
||||
@@ -68,6 +71,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="timeSpan">The amount of time to warm up, this does not take into account market hours/weekends</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public void SetWarmup(TimeSpan timeSpan, Resolution? resolution)
|
||||
{
|
||||
if (_locked)
|
||||
@@ -85,6 +89,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="timeSpan">The amount of time to warm up, this does not take into account market hours/weekends</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public void SetWarmUp(TimeSpan timeSpan, Resolution? resolution)
|
||||
{
|
||||
SetWarmup(timeSpan, resolution);
|
||||
@@ -97,6 +102,7 @@ namespace QuantConnect.Algorithm
|
||||
/// use 200 minute bars.
|
||||
/// </summary>
|
||||
/// <param name="barCount">The number of data points requested for warm up</param>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public void SetWarmup(int barCount)
|
||||
{
|
||||
SetWarmUp(barCount, null);
|
||||
@@ -109,6 +115,7 @@ namespace QuantConnect.Algorithm
|
||||
/// use 200 minute bars.
|
||||
/// </summary>
|
||||
/// <param name="barCount">The number of data points requested for warm up</param>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public void SetWarmUp(int barCount)
|
||||
{
|
||||
SetWarmup(barCount);
|
||||
@@ -120,6 +127,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="barCount">The number of data points requested for warm up</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public void SetWarmup(int barCount, Resolution? resolution)
|
||||
{
|
||||
if (_locked)
|
||||
@@ -138,6 +146,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="barCount">The number of data points requested for warm up</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public void SetWarmUp(int barCount, Resolution? resolution)
|
||||
{
|
||||
SetWarmup(barCount, resolution);
|
||||
@@ -146,6 +155,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Sets <see cref="IAlgorithm.IsWarmingUp"/> to false to indicate this algorithm has finished its warm up
|
||||
/// </summary>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public void SetFinishedWarmingUp()
|
||||
{
|
||||
IsWarmingUp = false;
|
||||
@@ -165,6 +175,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Gets the history requests required for provide warm up data for the algorithm
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<HistoryRequest> GetWarmupHistoryRequests()
|
||||
{
|
||||
if (_warmupBarCount.HasValue)
|
||||
@@ -189,6 +200,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="span">The span over which to request data. This is a calendar span, so take into consideration weekends and such</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>An enumerable of slice containing data over the most recent span for all configured securities</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<Slice> History(TimeSpan span, Resolution? resolution = null)
|
||||
{
|
||||
return History(Securities.Keys, Time - span, Time, resolution).Memoize();
|
||||
@@ -202,6 +214,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="periods">The number of bars to request</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>An enumerable of slice containing data over the most recent span for all configured securities</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<Slice> History(int periods, Resolution? resolution = null)
|
||||
{
|
||||
return History(Securities.Keys, periods, resolution).Memoize();
|
||||
@@ -215,6 +228,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="span">The span over which to retrieve recent historical data</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>An enumerable of slice containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<DataDictionary<T>> History<T>(TimeSpan span, Resolution? resolution = null)
|
||||
where T : IBaseData
|
||||
{
|
||||
@@ -230,6 +244,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="span">The span over which to retrieve recent historical data</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>An enumerable of slice containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<DataDictionary<T>> History<T>(IEnumerable<Symbol> symbols, TimeSpan span, Resolution? resolution = null)
|
||||
where T : IBaseData
|
||||
{
|
||||
@@ -246,6 +261,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="periods">The number of bars to request</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>An enumerable of slice containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<DataDictionary<T>> History<T>(IEnumerable<Symbol> symbols, int periods, Resolution? resolution = null)
|
||||
where T : IBaseData
|
||||
{
|
||||
@@ -272,6 +288,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="end">The end time in the algorithm's time zone</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>An enumerable of slice containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<DataDictionary<T>> History<T>(IEnumerable<Symbol> symbols, DateTime start, DateTime end, Resolution? resolution = null)
|
||||
where T : IBaseData
|
||||
{
|
||||
@@ -294,6 +311,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="span">The span over which to retrieve recent historical data</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>An enumerable of slice containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<T> History<T>(Symbol symbol, TimeSpan span, Resolution? resolution = null)
|
||||
where T : IBaseData
|
||||
{
|
||||
@@ -308,6 +326,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="periods">The number of bars to request</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>An enumerable of slice containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<TradeBar> History(Symbol symbol, int periods, Resolution? resolution = null)
|
||||
{
|
||||
if (symbol == null) throw new ArgumentException(_symbolEmptyErrorMessage);
|
||||
@@ -328,6 +347,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="periods">The number of bars to request</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>An enumerable of slice containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<T> History<T>(Symbol symbol, int periods, Resolution? resolution = null)
|
||||
where T : IBaseData
|
||||
{
|
||||
@@ -347,6 +367,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="end">The end time in the algorithm's time zone</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>An enumerable of slice containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<T> History<T>(Symbol symbol, DateTime start, DateTime end, Resolution? resolution = null)
|
||||
where T : IBaseData
|
||||
{
|
||||
@@ -363,6 +384,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="span">The span over which to retrieve recent historical data</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>An enumerable of slice containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<TradeBar> History(Symbol symbol, TimeSpan span, Resolution? resolution = null)
|
||||
{
|
||||
return History(symbol, Time - span, Time, resolution);
|
||||
@@ -376,6 +398,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="end">The end time in the algorithm's time zone</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>An enumerable of slice containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<TradeBar> History(Symbol symbol, DateTime start, DateTime end, Resolution? resolution = null)
|
||||
{
|
||||
var securityType = symbol.ID.SecurityType;
|
||||
@@ -403,6 +426,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="span">The span over which to retrieve recent historical data</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>An enumerable of slice containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<Slice> History(IEnumerable<Symbol> symbols, TimeSpan span, Resolution? resolution = null)
|
||||
{
|
||||
return History(symbols, Time - span, Time, resolution).Memoize();
|
||||
@@ -417,6 +441,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="periods">The number of bars to request</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>An enumerable of slice containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<Slice> History(IEnumerable<Symbol> symbols, int periods, Resolution? resolution = null)
|
||||
{
|
||||
if (resolution == Resolution.Tick) throw new ArgumentException("History functions that accept a 'periods' parameter can not be used with Resolution.Tick");
|
||||
@@ -433,6 +458,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="fillForward">True to fill forward missing data, false otherwise</param>
|
||||
/// <param name="extendedMarket">True to include extended market hours data, false otherwise</param>
|
||||
/// <returns>An enumerable of slice containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<Slice> History(IEnumerable<Symbol> symbols, DateTime start, DateTime end, Resolution? resolution = null, bool? fillForward = null, bool? extendedMarket = null)
|
||||
{
|
||||
return History(CreateDateRangeHistoryRequests(symbols, start, end, resolution, fillForward, extendedMarket)).Memoize();
|
||||
@@ -443,6 +469,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="request">the history request to execute</param>
|
||||
/// <returns>An enumerable of slice satisfying the specified history request</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<Slice> History(HistoryRequest request)
|
||||
{
|
||||
return History(new[] { request }).Memoize();
|
||||
@@ -453,6 +480,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="requests">the history requests to execute</param>
|
||||
/// <returns>An enumerable of slice satisfying the specified history request</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<Slice> History(IEnumerable<HistoryRequest> requests)
|
||||
{
|
||||
return History(requests, TimeZone).Memoize();
|
||||
@@ -463,6 +491,8 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="security"><see cref="Security"/> object for which to retrieve historical data</param>
|
||||
/// <returns>Securities historical data</returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<BaseData> GetLastKnownPrices(Security security)
|
||||
{
|
||||
return GetLastKnownPrices(security.Symbol);
|
||||
@@ -473,6 +503,8 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol we want to get seed data for</param>
|
||||
/// <returns>Securities historical data</returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public IEnumerable<BaseData> GetLastKnownPrices(Symbol symbol)
|
||||
{
|
||||
if (!HistoryRequestValid(symbol) || HistoryProvider == null)
|
||||
@@ -534,6 +566,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <returns>A single <see cref="BaseData"/> object with the last known price</returns>
|
||||
[Obsolete("This method is obsolete please use 'GetLastKnownPrices' which will return the last data point" +
|
||||
" for each type associated with the requested security")]
|
||||
[DocumentationAttribute(AddingData)]
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public BaseData GetLastKnownPrice(Security security)
|
||||
{
|
||||
return GetLastKnownPrices(security.Symbol)
|
||||
@@ -563,7 +597,8 @@ namespace QuantConnect.Algorithm
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
private IEnumerable<Slice> History(IEnumerable<HistoryRequest> requests, DateTimeZone timeZone)
|
||||
{
|
||||
var sentMessage = false;
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Gets whether or not WarmUpIndicator is allowed to warm up indicators/>
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public bool EnableAutomaticIndicatorWarmUp { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
@@ -42,6 +43,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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></returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public AccelerationBands ABANDS(Symbol symbol, int period, decimal width = 4, MovingAverageType movingAverageType = MovingAverageType.Simple,
|
||||
Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
@@ -64,6 +66,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The AccumulationDistribution indicator for the requested symbol over the speified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public AccumulationDistribution AD(Symbol symbol, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, "AD", resolution);
|
||||
@@ -87,6 +90,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The AccumulationDistributionOscillator indicator for the requested symbol over the speified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public AccumulationDistributionOscillator ADOSC(Symbol symbol, int fastPeriod, int slowPeriod, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"ADOSC({fastPeriod},{slowPeriod})", resolution);
|
||||
@@ -111,6 +115,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="period">Size of the rolling series to fit onto</param>
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <returns>The ARIMA indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public AutoRegressiveIntegratedMovingAverage ARIMA(Symbol symbol, int arOrder, int diffOrder, int maOrder, int period, Resolution? resolution = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"ARIMA({arOrder},{diffOrder},{maOrder},{period})", resolution);
|
||||
@@ -134,6 +139,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="period">The period over which to compute the Average Directional Index</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 Average Directional Index indicator for the requested symbol.</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public AverageDirectionalIndex ADX(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"ADX({period})", resolution);
|
||||
@@ -157,6 +163,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="slowPeriod">The period of the slow moving average associated with the AO</param>
|
||||
/// <param name="type">The type of moving average used when computing the fast and slow term. Defaults to simple moving average.</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>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public AwesomeOscillator AO(Symbol symbol, int slowPeriod, int fastPeriod, MovingAverageType type, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"AO({fastPeriod},{slowPeriod},{type})", resolution);
|
||||
@@ -179,6 +186,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution.</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The AverageDirectionalMovementIndexRating indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public AverageDirectionalMovementIndexRating ADXR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"ADXR({period})", resolution);
|
||||
@@ -207,6 +215,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The ArnaudLegouxMovingAverage indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public ArnaudLegouxMovingAverage ALMA(Symbol symbol, int period, int sigma = 6, decimal offset = 0.85m, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"ALMA({period},{sigma},{offset})", resolution);
|
||||
@@ -231,6 +240,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The AbsolutePriceOscillator indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public AbsolutePriceOscillator APO(Symbol symbol, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"APO({fastPeriod},{slowPeriod})", resolution);
|
||||
@@ -253,6 +263,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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>An AroonOscillator configured with the specied periods</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public AroonOscillator AROON(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
return AROON(symbol, period, period, resolution, selector);
|
||||
@@ -267,6 +278,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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>An AroonOscillator configured with the specified periods</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public AroonOscillator AROON(Symbol symbol, int upPeriod, int downPeriod, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"AROON({upPeriod},{downPeriod})", resolution);
|
||||
@@ -291,6 +303,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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>A new AverageTrueRange indicator with the specified smoothing type and period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public AverageTrueRange ATR(Symbol symbol, int period, MovingAverageType type = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"ATR({period})", resolution);
|
||||
@@ -314,6 +327,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The AugenPriceSpike indicator for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public AugenPriceSpike APS(Symbol symbol, int period = 3, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"APS({period})", resolution);
|
||||
@@ -338,6 +352,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>A BollingerBands configured with the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public BollingerBands BB(Symbol symbol, int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"BB({period},{k})", resolution);
|
||||
@@ -361,6 +376,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="period">The period of the Beta indicator</param>
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <returns>The Beta indicator for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public Beta B(Symbol target, Symbol reference, int period, Resolution? resolution = null)
|
||||
{
|
||||
var name = CreateIndicatorName(QuantConnect.Symbol.None, "B", resolution);
|
||||
@@ -385,6 +401,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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 Balance Of Power indicator for the requested symbol.</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public BalanceOfPower BOP(Symbol symbol, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, "BOP", resolution);
|
||||
@@ -409,6 +426,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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 Coppock Curve indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public CoppockCurve CC(Symbol symbol, int shortRocPeriod = 11, int longRocPeriod = 14, int lwmaPeriod = 10, Resolution? resolution = null,
|
||||
Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
@@ -434,6 +452,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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 CommodityChannelIndex indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public CommodityChannelIndex CCI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"CCI({period})", resolution);
|
||||
@@ -456,6 +475,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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 ChaikinMoneyFlow indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public ChaikinMoneyFlow CMF(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"CMF({period})", resolution);
|
||||
@@ -478,6 +498,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The ChandeMomentumOscillator indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public ChandeMomentumOscillator CMO(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"CMO({period})", resolution);
|
||||
@@ -502,6 +523,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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 DeMarker indicator for the requested symbol.</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public DeMarkerIndicator DEM(Symbol symbol, int period, MovingAverageType type, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"DEM({period},{type})", resolution);
|
||||
@@ -526,6 +548,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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 Donchian Channel indicator for the requested symbol.</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public DonchianChannel DCH(Symbol symbol, int upperPeriod, int lowerPeriod, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"DCH({upperPeriod},{lowerPeriod})", resolution);
|
||||
@@ -549,6 +572,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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 Donchian Channel indicator for the requested symbol.</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public DonchianChannel DCH(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
return DCH(symbol, period, period, resolution, selector);
|
||||
@@ -562,6 +586,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The DoubleExponentialMovingAverage indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public DoubleExponentialMovingAverage DEMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"DEMA({period})", resolution);
|
||||
@@ -584,6 +609,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>A new registered DetrendedPriceOscillator indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public DetrendedPriceOscillator DPO(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"DPO({period})", resolution);
|
||||
@@ -607,6 +633,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The ExponentialMovingAverage for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public ExponentialMovingAverage EMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
return EMA(symbol, period, ExponentialMovingAverage.SmoothingFactorDefault(period), resolution, selector);
|
||||
@@ -622,6 +649,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The ExponentialMovingAverage for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public ExponentialMovingAverage EMA(Symbol symbol, int period, decimal smoothingFactor, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"EMA({period})", resolution);
|
||||
@@ -646,6 +674,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The EaseOfMovementValue indicator for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public EaseOfMovementValue EMV(Symbol symbol, int period = 1, int scale = 10000, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"EMV({period}, {scale})", resolution);
|
||||
@@ -669,6 +698,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
|
||||
/// <param name="fieldName">The name of the field being selected</param>
|
||||
/// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public FilteredIdentity FilteredIdentity(Symbol symbol, Func<IBaseData, IBaseDataBar> selector = null, Func<IBaseData, bool> filter = null, string fieldName = null)
|
||||
{
|
||||
var resolution = GetSubscription(symbol).Resolution;
|
||||
@@ -685,6 +715,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
|
||||
/// <param name="fieldName">The name of the field being selected</param>
|
||||
/// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public FilteredIdentity FilteredIdentity(Symbol symbol, Resolution resolution, Func<IBaseData, IBaseDataBar> selector = null, Func<IBaseData, bool> filter = null, string fieldName = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, fieldName ?? "close", resolution);
|
||||
@@ -703,6 +734,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
|
||||
/// <param name="fieldName">The name of the field being selected</param>
|
||||
/// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public FilteredIdentity FilteredIdentity(Symbol symbol, TimeSpan resolution, Func<IBaseData, IBaseDataBar> selector = null, Func<IBaseData, bool> filter = null, string fieldName = null)
|
||||
{
|
||||
var name = Invariant($"{symbol}({fieldName ?? "close"}_{resolution})");
|
||||
@@ -720,6 +752,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The FisherTransform for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public FisherTransform FISH(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"FISH({period})", resolution);
|
||||
@@ -744,6 +777,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The FRAMA for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public FractalAdaptiveMovingAverage FRAMA(Symbol symbol, int period, int longPeriod = 198, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"FRAMA({period},{longPeriod})", resolution);
|
||||
@@ -765,6 +799,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The Heikin-Ashi indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public HeikinAshi HeikinAshi(Symbol symbol, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, "HA", resolution);
|
||||
@@ -787,6 +822,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns></returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public HullMovingAverage HMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"HMA({period})", resolution);
|
||||
@@ -814,6 +850,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="senkouBDelayPeriod">The period to calculate the Tenkan-sen period</param>
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <returns>A new IchimokuKinkoHyo indicator with the specified periods and delays</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public IchimokuKinkoHyo ICHIMOKU(Symbol symbol, int tenkanPeriod, int kijunPeriod, int senkouAPeriod, int senkouBPeriod, int senkouADelayPeriod, int senkouBDelayPeriod, Resolution? resolution = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"ICHIMOKU({tenkanPeriod},{kijunPeriod},{senkouAPeriod},{senkouBPeriod},{senkouADelayPeriod},{senkouBDelayPeriod})", resolution);
|
||||
@@ -836,6 +873,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="selector">Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value)</param>
|
||||
/// <param name="fieldName">The name of the field being selected</param>
|
||||
/// <returns>A new Identity indicator for the specified symbol and selector</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public Identity Identity(Symbol symbol, Func<IBaseData, decimal> selector = null, string fieldName = null)
|
||||
{
|
||||
var resolution = GetSubscription(symbol).Resolution;
|
||||
@@ -851,6 +889,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="selector">Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value)</param>
|
||||
/// <param name="fieldName">The name of the field being selected</param>
|
||||
/// <returns>A new Identity indicator for the specified symbol and selector</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public Identity Identity(Symbol symbol, Resolution resolution, Func<IBaseData, decimal> selector = null, string fieldName = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, fieldName ?? "close", resolution);
|
||||
@@ -868,6 +907,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="selector">Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value)</param>
|
||||
/// <param name="fieldName">The name of the field being selected</param>
|
||||
/// <returns>A new Identity indicator for the specified symbol and selector</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public Identity Identity(Symbol symbol, TimeSpan resolution, Func<IBaseData, decimal> selector = null, string fieldName = null)
|
||||
{
|
||||
var name = Invariant($"{symbol}({fieldName ?? "close"},{resolution})");
|
||||
@@ -884,6 +924,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The KaufmanAdaptiveMovingAverage indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public KaufmanAdaptiveMovingAverage KAMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
return KAMA(symbol, period, 2, 30, resolution, selector);
|
||||
@@ -899,6 +940,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The KaufmanAdaptiveMovingAverage indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public KaufmanAdaptiveMovingAverage KAMA(Symbol symbol, int period, int fastEmaPeriod, int slowEmaPeriod, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"KAMA({period},{fastEmaPeriod},{slowEmaPeriod})", resolution);
|
||||
@@ -913,6 +955,28 @@ namespace QuantConnect.Algorithm
|
||||
return kaufmanAdaptiveMovingAverage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an KaufmanEfficiencyRatio indicator for the symbol. The indicator will be automatically
|
||||
/// updated on the given resolution.
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol whose EF we want</param>
|
||||
/// <param name="period">The period of the EF</param>
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <returns>The KaufmanEfficiencyRatio indicator for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public KaufmanEfficiencyRatio KER(Symbol symbol, int period = 2, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"KER({period})", resolution);
|
||||
var kaufmanEfficiencyRatio = new KaufmanEfficiencyRatio(name, period);
|
||||
RegisterIndicator(symbol, kaufmanEfficiencyRatio, resolution, selector);
|
||||
|
||||
if (EnableAutomaticIndicatorWarmUp)
|
||||
{
|
||||
WarmUpIndicator(symbol, kaufmanEfficiencyRatio, resolution);
|
||||
}
|
||||
return kaufmanEfficiencyRatio;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Keltner Channels indicator.
|
||||
/// The indicator will be automatically updated on the given resolution.
|
||||
@@ -924,6 +988,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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 Keltner Channel indicator for the requested symbol.</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public KeltnerChannels KCH(Symbol symbol, int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"KCH({period},{k})", resolution);
|
||||
@@ -946,6 +1011,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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>log return indicator for the requested symbol.</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public LogReturn LOGR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"LOGR({period})", resolution);
|
||||
@@ -968,6 +1034,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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>A LeastSquaredMovingAverage configured with the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public LeastSquaresMovingAverage LSMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"LSMA({period})", resolution);
|
||||
@@ -991,6 +1058,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns></returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public LinearWeightedMovingAverage LWMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"LWMA({period})", resolution);
|
||||
@@ -1016,6 +1084,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The moving average convergence divergence between the fast and slow averages</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public MovingAverageConvergenceDivergence MACD(Symbol symbol, int fastPeriod, int slowPeriod, int signalPeriod, MovingAverageType type = MovingAverageType.Exponential, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"MACD({fastPeriod},{slowPeriod},{signalPeriod})", resolution);
|
||||
@@ -1038,6 +1107,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The MeanAbsoluteDeviation indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public MeanAbsoluteDeviation MAD(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"MAD({period})", resolution);
|
||||
@@ -1063,6 +1133,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The Volume Profile indicator for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public VolumeProfile VP(Symbol symbol, int period = 2, decimal valueAreaVolumePercentage = 0.70m, decimal priceRangeRoundOff = 0.05m, Resolution resolution = Resolution.Daily, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"VP({period})", resolution);
|
||||
@@ -1088,6 +1159,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The Time Profile indicator for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public TimeProfile TP(Symbol symbol, int period = 2, decimal valueAreaVolumePercentage = 0.70m, decimal priceRangeRoundOff = 0.05m, Resolution resolution = Resolution.Daily, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"TP({period})", resolution);
|
||||
@@ -1111,6 +1183,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null and the symbol is of type TradeBar defaults to the High property,
|
||||
/// otherwise it defaults to Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>A Maximum indicator that compute the max value and the periods since the max value</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public Maximum MAX(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"MAX({period})", resolution);
|
||||
@@ -1146,6 +1219,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The MoneyFlowIndex indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public MoneyFlowIndex MFI(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"MFI({period})", resolution);
|
||||
@@ -1170,6 +1244,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution.</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The Mass Index indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public MassIndex MASS(Symbol symbol, int emaPeriod = 9, int sumPeriod = 25, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"MASS({emaPeriod},{sumPeriod})", resolution);
|
||||
@@ -1192,6 +1267,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The MidPoint indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public MidPoint MIDPOINT(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"MIDPOINT({period})", resolution);
|
||||
@@ -1214,6 +1290,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The MidPrice indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public MidPrice MIDPRICE(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"MIDPRICE({period})", resolution);
|
||||
@@ -1237,6 +1314,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null and the symbol is of type TradeBar defaults to the Low property,
|
||||
/// otherwise it defaults to Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>A Minimum indicator that compute the in value and the periods since the min value</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public Minimum MIN(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"MIN({period})", resolution);
|
||||
@@ -1272,6 +1350,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The momentum indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public Momentum MOM(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"MOM({period})", resolution);
|
||||
@@ -1295,6 +1374,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The Momersion indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public MomersionIndicator MOMERSION(Symbol symbol, int? minPeriod, int fullPeriod, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"MOMERSION({minPeriod},{fullPeriod})", resolution);
|
||||
@@ -1318,6 +1398,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The momentum indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public MomentumPercent MOMP(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"MOMP({period})", resolution);
|
||||
@@ -1340,6 +1421,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The NormalizedAverageTrueRange indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public NormalizedAverageTrueRange NATR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"NATR({period})", resolution);
|
||||
@@ -1363,6 +1445,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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 On Balance Volume indicator for the requested symbol.</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public OnBalanceVolume OBV(Symbol symbol, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, "OBV", resolution);
|
||||
@@ -1387,6 +1470,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The PivotPointsHighLow indicator for the requested symbol.</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public PivotPointsHighLow PPHL(Symbol symbol, int lengthHigh, int lengthLow, int lastStoredValues = 100, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"PPHL({lengthHigh},{lengthLow})", resolution);
|
||||
@@ -1411,6 +1495,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The PercentagePriceOscillator indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public PercentagePriceOscillator PPO(Symbol symbol, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"PPO({fastPeriod},{slowPeriod})", resolution);
|
||||
@@ -1435,6 +1520,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <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>A ParabolicStopAndReverse configured with the specified periods</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public ParabolicStopAndReverse PSAR(Symbol symbol, decimal afStart = 0.02m, decimal afIncrement = 0.02m, decimal afMax = 0.2m, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"PSAR({afStart},{afIncrement},{afMax})", resolution);
|
||||
@@ -1458,6 +1544,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>A Regression Channel configured with the specified period and number of standard deviation</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public RegressionChannel RC(Symbol symbol, int period, decimal k, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"RC({period},{k})", resolution);
|
||||
@@ -1481,6 +1568,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The RateOfChange indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public RateOfChange ROC(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"ROC({period})", resolution);
|
||||
@@ -1504,6 +1592,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The RateOfChangePercent indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public RateOfChangePercent ROCP(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"ROCP({period})", resolution);
|
||||
@@ -1526,6 +1615,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The RateOfChangeRatio indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public RateOfChangeRatio ROCR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"ROCR({period})", resolution);
|
||||
@@ -1550,6 +1640,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The RelativeStrengthIndex indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public RelativeStrengthIndex RSI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Wilders, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"RSI({period},{movingAverageType})", resolution);
|
||||
@@ -1572,6 +1663,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The RelativeVigorIndex indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public RelativeVigorIndex RVI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"RVI({period},{movingAverageType})", resolution);
|
||||
@@ -1595,6 +1687,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The Relative Volume indicator for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public RelativeDailyVolume RDV(Symbol symbol, int period = 2, Resolution resolution = Resolution.Daily, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"RDV({period})", resolution);
|
||||
@@ -1617,6 +1710,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="multiplier">Multiplier to calculate basic upper and lower bands width.</param>
|
||||
/// <param name="movingAverageType">Smoother type for average true range, defaults to Wilders.</param>
|
||||
/// <param name="resolution">The resolution.</param>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public SuperTrend STR(Symbol symbol, int period, decimal multiplier, MovingAverageType movingAverageType = MovingAverageType.Wilders, Resolution? resolution = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"STR({period},{multiplier})", resolution);
|
||||
@@ -1640,6 +1734,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The RollingSharpeRatio indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public SharpeRatio SR(Symbol symbol, int sharpePeriod, decimal riskFreeRate = 0.0m, Resolution ? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"SR({sharpePeriod},{riskFreeRate})", resolution);
|
||||
@@ -1664,6 +1759,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The SimpleMovingAverage for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public SimpleMovingAverage SMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"SMA({period})", resolution);
|
||||
@@ -1689,6 +1785,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The SchaffTrendCycle indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public SchaffTrendCycle STC(Symbol symbol, int cyclePeriod, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType = MovingAverageType.Exponential, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"STC({cyclePeriod},{fastPeriod},{slowPeriod})", resolution);
|
||||
@@ -1711,6 +1808,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The StandardDeviation indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public StandardDeviation STD(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"STD({period})", resolution);
|
||||
@@ -1733,6 +1831,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="kPeriod">The sum period of the stochastic. Normally 14</param>
|
||||
/// <param name="dPeriod">The sum period of the stochastic. Normally 3</param>
|
||||
/// <returns>Stochastic indicator for the requested symbol.</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public Stochastic STO(Symbol symbol, int period, int kPeriod, int dPeriod, Resolution? resolution = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"STO({period},{kPeriod},{dPeriod})", resolution);
|
||||
@@ -1754,6 +1853,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution.</param>
|
||||
/// <param name="period">The period of the stochastic. Normally 14</param>
|
||||
/// <returns>Stochastic indicator for the requested symbol.</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public Stochastic STO(Symbol symbol, int period, Resolution? resolution = null)
|
||||
{
|
||||
return STO(symbol, period, period, 3, resolution);
|
||||
@@ -1767,6 +1867,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The Sum indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public Sum SUM(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"SUM({period})", resolution);
|
||||
@@ -1792,6 +1893,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">elects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The calculation using the given tool</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public SwissArmyKnife SWISS(Symbol symbol, int period, double delta, SwissArmyKnifeTool tool, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"SWISS({period},{delta},{tool})", resolution);
|
||||
@@ -1815,6 +1917,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The T3MovingAverage indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public T3MovingAverage T3(Symbol symbol, int period, decimal volumeFactor = 0.7m, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"T3({period},{volumeFactor})", resolution);
|
||||
@@ -1837,6 +1940,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The TripleExponentialMovingAverage indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public TripleExponentialMovingAverage TEMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"TEMA({period})", resolution);
|
||||
@@ -1858,6 +1962,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The TrueRange indicator for the requested symbol.</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public TrueRange TR(Symbol symbol, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, "TR", resolution);
|
||||
@@ -1880,6 +1985,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The TriangularMovingAverage indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public TriangularMovingAverage TRIMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"TRIMA({period})", resolution);
|
||||
@@ -1902,6 +2008,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The Trix indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public Trix TRIX(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"TRIX({period})", resolution);
|
||||
@@ -1926,6 +2033,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The UltimateOscillator indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public UltimateOscillator ULTOSC(Symbol symbol, int period1, int period2, int period3, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"ULTOSC({period1},{period2},{period3})", resolution);
|
||||
@@ -1948,6 +2056,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The Variance indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public Variance VAR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"VAR({period})", resolution);
|
||||
@@ -1971,6 +2080,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The VolumeWeightedAveragePrice for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public VolumeWeightedAveragePriceIndicator VWAP(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"VWAP({period})", resolution);
|
||||
@@ -1991,6 +2101,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol whose VWAP we want</param>
|
||||
/// <returns>The IntradayVWAP for the specified symbol</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public IntradayVwap VWAP(Symbol symbol)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, "VWAP", null);
|
||||
@@ -2009,6 +2120,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The Williams %R indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public WilliamsPercentR WILR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"WILR({period})", resolution);
|
||||
@@ -2033,6 +2145,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The WilderMovingAverage for the given parameters</returns>
|
||||
/// <remarks>WWMA for Welles Wilder Moving Average</remarks>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public WilderMovingAverage WWMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, $"WWMA({period})", resolution);
|
||||
@@ -2056,6 +2169,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <returns>The WilderSwingIndex for the given parameters</returns>
|
||||
/// <remarks>SI for Wilder Swing Index</remarks>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public WilderSwingIndex SI(Symbol symbol, decimal limitMove, Resolution? resolution = Resolution.Daily)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, "SI", resolution);
|
||||
@@ -2079,6 +2193,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <returns>The WilderAccumulativeSwingIndex for the given parameters</returns>
|
||||
/// <remarks>ASI for Wilder Accumulative Swing Index</remarks>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public WilderAccumulativeSwingIndex ASI(Symbol symbol, decimal limitMove, Resolution? resolution = Resolution.Daily)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, "ASI", resolution);
|
||||
@@ -2099,6 +2214,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbols">The symbols whose Arms Index we want</param>
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <returns>The Arms Index indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public ArmsIndex TRIN(IEnumerable<Symbol> symbols, Resolution? resolution = null)
|
||||
{
|
||||
return TRIN(symbols.ToArray(), resolution);
|
||||
@@ -2110,6 +2226,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbols">The symbols whose Arms Index we want</param>
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <returns>The Arms Index indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public ArmsIndex TRIN(Symbol[] symbols, Resolution? resolution = null)
|
||||
{
|
||||
var name = CreateIndicatorName(QuantConnect.Symbol.None, "TRIN", resolution ?? GetSubscription(symbols.First()).Resolution);
|
||||
@@ -2134,6 +2251,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbols">The symbols whose A/D Ratio we want</param>
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <returns>The Advance/Decline Ratio indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public AdvanceDeclineRatio ADR(IEnumerable<Symbol> symbols, Resolution? resolution = null)
|
||||
{
|
||||
var name = CreateIndicatorName(QuantConnect.Symbol.None, "A/D Ratio", resolution ?? GetSubscription(symbols.First()).Resolution);
|
||||
@@ -2158,6 +2276,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbols">The symbol whose A/D Volume Rate we want</param>
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <returns>The Advance/Decline Volume Ratio indicator for the requested symbol over the specified period</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public AdvanceDeclineVolumeRatio ADVR(IEnumerable<Symbol> symbols, Resolution? resolution = null)
|
||||
{
|
||||
var name = CreateIndicatorName(QuantConnect.Symbol.None, "A/D Volume Rate", resolution ?? GetSubscription(symbols.First()).Resolution);
|
||||
@@ -2183,6 +2302,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="type">The indicator type, for example, 'SMA(5)'</param>
|
||||
/// <param name="resolution">The resolution requested</param>
|
||||
/// <returns>A unique for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public string CreateIndicatorName(Symbol symbol, FormattableString type, Resolution? resolution)
|
||||
{
|
||||
return CreateIndicatorName(symbol, Invariant(type), resolution);
|
||||
@@ -2195,6 +2315,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="type">The indicator type, for example, 'SMA(5)'</param>
|
||||
/// <param name="resolution">The resolution requested</param>
|
||||
/// <returns>A unique for the given parameters</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public string CreateIndicatorName(Symbol symbol, string type, Resolution? resolution)
|
||||
{
|
||||
if (!resolution.HasValue)
|
||||
@@ -2285,6 +2406,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="indicator">The indicator to receive data from the consolidator</param>
|
||||
/// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public void RegisterIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution), selector ?? (x => x.Value));
|
||||
@@ -2298,6 +2421,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="indicator">The indicator to receive data from the consolidator</param>
|
||||
/// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public void RegisterIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, TimeSpan? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution), selector ?? (x => x.Value));
|
||||
@@ -2311,6 +2436,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="indicator">The indicator to receive data from the consolidator</param>
|
||||
/// <param name="consolidator">The consolidator to receive raw subscription data</param>
|
||||
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public void RegisterIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, IDataConsolidator consolidator, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
// default our selector to the Value property on BaseData
|
||||
@@ -2334,6 +2461,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">The symbol to register against</param>
|
||||
/// <param name="indicator">The indicator to receive data from the consolidator</param>
|
||||
/// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, Resolution? resolution = null)
|
||||
where T : IBaseData
|
||||
{
|
||||
@@ -2348,6 +2477,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="indicator">The indicator to receive data from the consolidator</param>
|
||||
/// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
|
||||
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, Resolution? resolution, Func<IBaseData, T> selector)
|
||||
where T : IBaseData
|
||||
{
|
||||
@@ -2362,6 +2493,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="indicator">The indicator to receive data from the consolidator</param>
|
||||
/// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
|
||||
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, TimeSpan? resolution, Func<IBaseData, T> selector = null)
|
||||
where T : IBaseData
|
||||
{
|
||||
@@ -2376,6 +2509,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="indicator">The indicator to receive data from the consolidator</param>
|
||||
/// <param name="consolidator">The consolidator to receive raw subscription data</param>
|
||||
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, IDataConsolidator consolidator, Func<IBaseData, T> selector = null)
|
||||
where T : IBaseData
|
||||
{
|
||||
@@ -2419,6 +2554,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The given indicator</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public IndicatorBase<IndicatorDataPoint> WarmUpIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
resolution = GetResolution(symbol, resolution);
|
||||
@@ -2434,6 +2571,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="period">The necessary period to warm up the indicator</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The given indicator</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public IndicatorBase<IndicatorDataPoint> WarmUpIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, TimeSpan period, Func<IBaseData, decimal> selector = null)
|
||||
{
|
||||
var history = GetIndicatorWarmUpHistory(symbol, indicator, period);
|
||||
@@ -2460,6 +2599,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The given indicator</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public IndicatorBase<T> WarmUpIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, Resolution? resolution = null, Func<IBaseData, T> selector = null)
|
||||
where T : class, IBaseData
|
||||
{
|
||||
@@ -2476,6 +2617,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="period">The necessary period to warm up the indicator</param>
|
||||
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
|
||||
/// <returns>The given indicator</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public IndicatorBase<T> WarmUpIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, TimeSpan period, Func<IBaseData, T> selector = null)
|
||||
where T : class, IBaseData
|
||||
{
|
||||
@@ -2586,6 +2729,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The resolution for the consolidator, if null, uses the resolution from subscription</param>
|
||||
/// <param name="dataType">The data type for this consolidator, if null, uses TradeBar over QuoteBar if present</param>
|
||||
/// <returns>The new default consolidator</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public IDataConsolidator ResolveConsolidator(Symbol symbol, Resolution? resolution, Type dataType = null)
|
||||
{
|
||||
TimeSpan? timeSpan = null;
|
||||
@@ -2603,6 +2748,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="timeSpan">The requested time span for the consolidator, if null, uses the resolution from subscription</param>
|
||||
/// <param name="dataType">The data type for this consolidator, if null, uses TradeBar over QuoteBar if present</param>
|
||||
/// <returns>The new default consolidator</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public IDataConsolidator ResolveConsolidator(Symbol symbol, TimeSpan? timeSpan, Type dataType = null)
|
||||
{
|
||||
var tickType = dataType != null ? LeanData.GetCommonTickTypeForCommonDataTypes(dataType, symbol.SecurityType) : (TickType?)null;
|
||||
@@ -2633,6 +2780,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="consolidatorInputType">The desired input type of the consolidator, such as TradeBar or QuoteBar</param>
|
||||
/// <param name="tickType">Trade or Quote. Optional, defaults to trade</param>
|
||||
/// <returns>A new consolidator matching the requested parameters</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public static IDataConsolidator CreateConsolidator(TimeSpan period, Type consolidatorInputType, TickType? tickType = null)
|
||||
{
|
||||
// if our type can be used as a trade bar, then let's just make one of those
|
||||
@@ -2689,6 +2837,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="period">The consolidation period</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate(Symbol symbol, Resolution period, Action<TradeBar> handler)
|
||||
{
|
||||
return Consolidate(symbol, period.ToTimeSpan(), TickType.Trade, handler);
|
||||
@@ -2701,6 +2850,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="period">The consolidation period</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, Action<TradeBar> handler)
|
||||
{
|
||||
return Consolidate(symbol, period, TickType.Trade, handler);
|
||||
@@ -2713,6 +2863,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="period">The consolidation period</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate(Symbol symbol, Resolution period, Action<QuoteBar> handler)
|
||||
{
|
||||
return Consolidate(symbol, period.ToTimeSpan(), TickType.Quote, handler);
|
||||
@@ -2725,6 +2876,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="period">The consolidation period</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, Action<QuoteBar> handler)
|
||||
{
|
||||
return Consolidate(symbol, period, TickType.Quote, handler);
|
||||
@@ -2738,6 +2890,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="period">The consolidation period</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate<T>(Symbol symbol, TimeSpan period, Action<T> handler)
|
||||
where T : class, IBaseData
|
||||
{
|
||||
@@ -2757,6 +2910,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate<T>(Symbol symbol, Resolution period, TickType? tickType, Action<T> handler)
|
||||
where T : class, IBaseData
|
||||
{
|
||||
@@ -2772,6 +2926,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate<T>(Symbol symbol, TimeSpan period, TickType? tickType, Action<T> handler)
|
||||
where T : class, IBaseData
|
||||
{
|
||||
@@ -2792,6 +2947,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="calendar">The consolidation calendar</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate(Symbol symbol, Func<DateTime, CalendarInfo> calendar, Action<QuoteBar> handler)
|
||||
{
|
||||
return Consolidate(symbol, calendar, TickType.Quote, handler);
|
||||
@@ -2804,6 +2960,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="calendar">The consolidation calendar</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate(Symbol symbol, Func<DateTime, CalendarInfo> calendar, Action<TradeBar> handler)
|
||||
{
|
||||
return Consolidate(symbol, calendar, TickType.Trade, handler);
|
||||
@@ -2817,6 +2974,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="calendar">The consolidation calendar</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate<T>(Symbol symbol, Func<DateTime, CalendarInfo> calendar, Action<T> handler)
|
||||
where T : class, IBaseData
|
||||
{
|
||||
@@ -2836,6 +2994,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
private IDataConsolidator Consolidate<T>(Symbol symbol, Func<DateTime, CalendarInfo> calendar, TickType? tickType, Action<T> handler)
|
||||
where T : class, IBaseData
|
||||
{
|
||||
@@ -2853,6 +3012,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Adds the provided consolidator and asserts the handler T type is assignable from the consolidator output,
|
||||
/// if not will throw <see cref="ArgumentException"/>
|
||||
/// </summary>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
private void AddConsolidator<T>(Symbol symbol, IDataConsolidator consolidator, Action<T> handler)
|
||||
{
|
||||
if (!typeof(T).IsAssignableFrom(consolidator.OutputType))
|
||||
@@ -2876,6 +3036,7 @@ namespace QuantConnect.Algorithm
|
||||
SubscriptionManager.AddConsolidator(symbol, consolidator);
|
||||
}
|
||||
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
private IDataConsolidator CreateConsolidator(Func<DateTime, CalendarInfo> calendar, Type consolidatorInputType, TickType tickType)
|
||||
{
|
||||
// if our type can be used as a trade bar, then let's just make one of those
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Access to the runtime statistics property. User provided statistics.
|
||||
/// </summary>
|
||||
/// <remarks> RuntimeStatistics are displayed in the head banner in live trading</remarks>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public ConcurrentDictionary<string, string> RuntimeStatistics { get; } = new ConcurrentDictionary<string, string>();
|
||||
|
||||
/// <summary>
|
||||
@@ -52,6 +53,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="chart">Chart object to add to collection.</param>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void AddChart(Chart chart)
|
||||
{
|
||||
_charts.TryAdd(chart.Name, chart);
|
||||
@@ -63,6 +65,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="series">Name of the plot series</param>
|
||||
/// <param name="value">Value to plot</param>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string series, decimal value)
|
||||
{
|
||||
//By default plot to the primary chart:
|
||||
@@ -74,6 +77,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <remarks> Record(string series, int value)</remarks>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Record(string series, int value)
|
||||
{
|
||||
Plot(series, value);
|
||||
@@ -83,6 +87,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Plot a chart using string series name, with double value. Alias of Plot();
|
||||
/// </summary>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Record(string series, double value)
|
||||
{
|
||||
Plot(series, value);
|
||||
@@ -94,6 +99,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="series"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Record(string series, decimal value)
|
||||
{
|
||||
//By default plot to the primary chart:
|
||||
@@ -104,6 +110,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Plot a chart using string series name, with double value.
|
||||
/// </summary>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string series, double value) {
|
||||
Plot(series, value.SafeDecimalCast());
|
||||
}
|
||||
@@ -112,6 +119,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Plot a chart using string series name, with int value.
|
||||
/// </summary>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string series, int value)
|
||||
{
|
||||
Plot(series, (decimal)value);
|
||||
@@ -121,6 +129,7 @@ namespace QuantConnect.Algorithm
|
||||
///Plot a chart using string series name, with float value.
|
||||
/// </summary>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string series, float value)
|
||||
{
|
||||
Plot(series, (decimal)value);
|
||||
@@ -130,6 +139,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Plot a chart to string chart name, using string series name, with double value.
|
||||
/// </summary>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, string series, double value)
|
||||
{
|
||||
Plot(chart, series, value.SafeDecimalCast());
|
||||
@@ -139,6 +149,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Plot a chart to string chart name, using string series name, with int value
|
||||
/// </summary>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, string series, int value)
|
||||
{
|
||||
Plot(chart, series, (decimal)value);
|
||||
@@ -148,6 +159,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Plot a chart to string chart name, using string series name, with float value
|
||||
/// </summary>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, string series, float value)
|
||||
{
|
||||
Plot(chart, series, (decimal)value);
|
||||
@@ -159,6 +171,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="chart">Chart name</param>
|
||||
/// <param name="series">Series name</param>
|
||||
/// <param name="value">Value of the point</param>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, string series, decimal value)
|
||||
{
|
||||
// Check if chart/series names are reserved
|
||||
@@ -209,6 +222,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="series">The series name</param>
|
||||
/// <param name="seriesType">The type of series, i.e, Scatter</param>
|
||||
/// <param name="unit">The unit of the y axis, usually $</param>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void AddSeries(string chart, string series, SeriesType seriesType, string unit = "$")
|
||||
{
|
||||
Chart c;
|
||||
@@ -226,6 +240,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="chart">The chart's name</param>
|
||||
/// <param name="indicators">The indicatorsto plot</param>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot<T>(string chart, params IndicatorBase<T>[] indicators)
|
||||
where T : IBaseData
|
||||
{
|
||||
@@ -238,6 +253,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Automatically plots each indicator when a new value is available
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Charting)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public void PlotIndicator<T>(string chart, params IndicatorBase<T>[] indicators)
|
||||
where T : IBaseData
|
||||
{
|
||||
@@ -257,6 +274,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Automatically plots each indicator when a new value is available, optionally waiting for indicator.IsReady to return true
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Charting)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public void PlotIndicator<T>(string chart, bool waitForReady, params IndicatorBase<T>[] indicators)
|
||||
where T : IBaseData
|
||||
{
|
||||
@@ -282,6 +301,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="name">Name of your runtime statistic</param>
|
||||
/// <param name="value">String value of your runtime statistic</param>
|
||||
/// <seealso cref="LiveMode"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void SetRuntimeStatistic(string name, string value)
|
||||
{
|
||||
RuntimeStatistics.AddOrUpdate(name, value);
|
||||
@@ -292,6 +312,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="name">Name of your runtime statistic</param>
|
||||
/// <param name="value">Decimal value of your runtime statistic</param>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void SetRuntimeStatistic(string name, decimal value)
|
||||
{
|
||||
SetRuntimeStatistic(name, value.ToString(CultureInfo.InvariantCulture));
|
||||
@@ -302,6 +323,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="name">Name of your runtime statistic</param>
|
||||
/// <param name="value">Int value of your runtime statistic</param>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void SetRuntimeStatistic(string name, int value)
|
||||
{
|
||||
SetRuntimeStatistic(name, value.ToStringInvariant());
|
||||
@@ -312,17 +334,19 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="name">Name of your runtime statistic</param>
|
||||
/// <param name="value">Double value of your runtime statistic</param>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void SetRuntimeStatistic(string name, double value)
|
||||
{
|
||||
SetRuntimeStatistic(name, value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the chart updates by fetch the recent points added and return for dynamic plotting.
|
||||
/// Get the chart updates by fetch the recent points added and return for dynamic Charting.
|
||||
/// </summary>
|
||||
/// <param name="clearChartData"></param>
|
||||
/// <returns>List of chart updates since the last request</returns>
|
||||
/// <remarks>GetChartUpdates returns the latest updates since previous request.</remarks>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public List<Chart> GetChartUpdates(bool clearChartData = false)
|
||||
{
|
||||
var updates = _charts.Select(x => x.Value).Select(chart => chart.GetUpdates()).ToList();
|
||||
|
||||
@@ -59,6 +59,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="ticker">Key/Ticker for data</param>
|
||||
/// <param name="resolution">Resolution of the data</param>
|
||||
/// <returns>The new <see cref="Security"/></returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
public Security AddData(PyObject type, string ticker, Resolution? resolution = null)
|
||||
{
|
||||
return AddData(type, ticker, resolution, null, false, 1m);
|
||||
@@ -82,6 +83,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Adding the three unused parameters makes it choose the correct method when using a string or Symbol. This is
|
||||
/// due to pythonnet's method precedence, as viewable here: https://github.com/QuantConnect/pythonnet/blob/9e29755c54e6008cb016e3dd9d75fbd8cd19fcf7/src/runtime/methodbinder.cs#L215
|
||||
/// </remarks>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
public Security AddData(PyObject type, Symbol underlying, Resolution? resolution = null)
|
||||
{
|
||||
return AddData(type, underlying, resolution, null, false, 1m);
|
||||
@@ -99,6 +101,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="fillDataForward">When no data available on a tradebar, return the last data that was generated</param>
|
||||
/// <param name="leverage">Custom leverage per security</param>
|
||||
/// <returns>The new <see cref="Security"/></returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
public Security AddData(PyObject type, string ticker, Resolution? resolution, DateTimeZone timeZone, bool fillDataForward = false, decimal leverage = 1.0m)
|
||||
{
|
||||
return AddData(type.CreateType(), ticker, resolution, timeZone, fillDataForward, leverage);
|
||||
@@ -124,6 +127,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Adding the three unused parameters makes it choose the correct method when using a string or Symbol. This is
|
||||
/// due to pythonnet's method precedence, as viewable here: https://github.com/QuantConnect/pythonnet/blob/9e29755c54e6008cb016e3dd9d75fbd8cd19fcf7/src/runtime/methodbinder.cs#L215
|
||||
/// </remarks>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
public Security AddData(PyObject type, Symbol underlying, Resolution? resolution, DateTimeZone timeZone, bool fillDataForward = false, decimal leverage = 1.0m)
|
||||
{
|
||||
return AddData(type.CreateType(), underlying, resolution, timeZone, fillDataForward, leverage);
|
||||
@@ -141,6 +145,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="fillDataForward">When no data available on a tradebar, return the last data that was generated</param>
|
||||
/// <param name="leverage">Custom leverage per security</param>
|
||||
/// <returns>The new <see cref="Security"/></returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
public Security AddData(Type dataType, string ticker, Resolution? resolution, DateTimeZone timeZone, bool fillDataForward = false, decimal leverage = 1.0m)
|
||||
{
|
||||
// NOTE: Invoking methods on BaseData w/out setting the symbol may provide unexpected behavior
|
||||
@@ -185,6 +190,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Adding the three unused parameters makes it choose the correct method when using a string or Symbol. This is
|
||||
/// due to pythonnet's method precedence, as viewable here: https://github.com/QuantConnect/pythonnet/blob/9e29755c54e6008cb016e3dd9d75fbd8cd19fcf7/src/runtime/methodbinder.cs#L215
|
||||
/// </remarks>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
public Security AddData(Type dataType, Symbol underlying, Resolution? resolution = null, DateTimeZone timeZone = null, bool fillDataForward = false, decimal leverage = 1.0m)
|
||||
{
|
||||
var symbol = QuantConnect.Symbol.CreateBase(dataType, underlying, Market.USA);
|
||||
@@ -204,6 +210,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="fillDataForward">When no data available on a tradebar, return the last data that was generated</param>
|
||||
/// <param name="leverage">Custom leverage per security</param>
|
||||
/// <returns>The new <see cref="Security"/></returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
public Security AddData(PyObject type, string ticker, SymbolProperties properties, SecurityExchangeHours exchangeHours, Resolution? resolution = null, bool fillDataForward = false, decimal leverage = 1.0m)
|
||||
{
|
||||
// Get the right key for storage of base type symbols
|
||||
@@ -224,6 +231,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="optionFilter">Filter to apply to option contracts loaded as part of the universe</param>
|
||||
/// <returns>The new Option security, containing a Future as its underlying.</returns>
|
||||
/// <exception cref="ArgumentException">The symbol provided is not canonical.</exception>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
public void AddFutureOption(Symbol futureSymbol, PyObject optionFilter)
|
||||
{
|
||||
Func<OptionFilterUniverse, OptionFilterUniverse> optionFilterUniverse;
|
||||
@@ -276,6 +284,7 @@ namespace QuantConnect.Algorithm
|
||||
/// will be executed on day changes in the NewYork time zone (<see cref="TimeZones.NewYork"/>
|
||||
/// </summary>
|
||||
/// <param name="pyObject">Defines an initial coarse selection</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(PyObject pyObject)
|
||||
{
|
||||
Func<IEnumerable<CoarseFundamental>, object> coarseFunc;
|
||||
@@ -309,6 +318,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="pyObject">Defines an initial coarse selection or a universe</param>
|
||||
/// <param name="pyfine">Defines a more detailed selection with access to more data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(PyObject pyObject, PyObject pyfine)
|
||||
{
|
||||
Func<IEnumerable<CoarseFundamental>, object> coarseFunc;
|
||||
@@ -340,6 +350,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The resolution this universe should be triggered on</param>
|
||||
/// <param name="pySelector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(string name, Resolution resolution, PyObject pySelector)
|
||||
{
|
||||
var selector = pySelector.ConvertToDelegate<Func<DateTime, object>>();
|
||||
@@ -352,6 +363,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="pySelector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(string name, PyObject pySelector)
|
||||
{
|
||||
var selector = pySelector.ConvertToDelegate<Func<DateTime, object>>();
|
||||
@@ -367,6 +379,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="market">The market of the universe</param>
|
||||
/// <param name="universeSettings">The subscription settings used for securities added from this universe</param>
|
||||
/// <param name="pySelector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, PyObject pySelector)
|
||||
{
|
||||
var selector = pySelector.ConvertToDelegate<Func<DateTime, object>>();
|
||||
@@ -381,6 +394,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="T">The data type</param>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(PyObject T, string name, PyObject selector)
|
||||
{
|
||||
return AddUniverse(T.CreateType(), SecurityType.Equity, name, Resolution.Daily, Market.USA, UniverseSettings, selector);
|
||||
@@ -395,6 +409,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The epected resolution of the universe data</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(PyObject T, string name, Resolution resolution, PyObject selector)
|
||||
{
|
||||
return AddUniverse(T.CreateType(), SecurityType.Equity, name, resolution, Market.USA, UniverseSettings, selector);
|
||||
@@ -410,6 +425,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The epected resolution of the universe data</param>
|
||||
/// <param name="universeSettings">The settings used for securities added by this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(PyObject T, string name, Resolution resolution, UniverseSettings universeSettings, PyObject selector)
|
||||
{
|
||||
return AddUniverse(T.CreateType(), SecurityType.Equity, name, resolution, Market.USA, universeSettings, selector);
|
||||
@@ -424,6 +440,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="universeSettings">The settings used for securities added by this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(PyObject T, string name, UniverseSettings universeSettings, PyObject selector)
|
||||
{
|
||||
return AddUniverse(T.CreateType(), SecurityType.Equity, name, Resolution.Daily, Market.USA, universeSettings, selector);
|
||||
@@ -439,6 +456,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The epected resolution of the universe data</param>
|
||||
/// <param name="market">The market for selected symbols</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(PyObject T, SecurityType securityType, string name, Resolution resolution, string market, PyObject selector)
|
||||
{
|
||||
return AddUniverse(T.CreateType(), securityType, name, resolution, market, UniverseSettings, selector);
|
||||
@@ -454,6 +472,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="market">The market for selected symbols</param>
|
||||
/// <param name="universeSettings">The subscription settings to use for newly created subscriptions</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(PyObject T, SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, PyObject selector)
|
||||
{
|
||||
return AddUniverse(T.CreateType(), securityType, name, resolution, market, universeSettings, selector);
|
||||
@@ -469,6 +488,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="market">The market for selected symbols</param>
|
||||
/// <param name="universeSettings">The subscription settings to use for newly created subscriptions</param>
|
||||
/// <param name="pySelector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(Type dataType, SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, PyObject pySelector)
|
||||
{
|
||||
var marketHoursDbEntry = MarketHoursDatabase.GetEntry(market, name, securityType);
|
||||
@@ -495,6 +515,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="universe">The universe we want to chain an option universe selection model too</param>
|
||||
/// <param name="optionFilter">The option filter universe to use</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void AddUniverseOptions(PyObject universe, PyObject optionFilter)
|
||||
{
|
||||
Func<OptionFilterUniverse, OptionFilterUniverse> convertedOptionChain;
|
||||
@@ -521,6 +542,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="indicator">The indicator to receive data from the consolidator</param>
|
||||
/// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
|
||||
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public void RegisterIndicator(Symbol symbol, PyObject indicator, Resolution? resolution = null, PyObject selector = null)
|
||||
{
|
||||
RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution), selector);
|
||||
@@ -534,6 +557,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="indicator">The indicator to receive data from the consolidator</param>
|
||||
/// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
|
||||
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public void RegisterIndicator(Symbol symbol, PyObject indicator, TimeSpan? resolution = null, PyObject selector = null)
|
||||
{
|
||||
RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution), selector);
|
||||
@@ -547,6 +572,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="indicator">The indicator to receive data from the consolidator</param>
|
||||
/// <param name="pyObject">The python object that it is trying to register with, could be consolidator or a timespan</param>
|
||||
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public void RegisterIndicator(Symbol symbol, PyObject indicator, PyObject pyObject, PyObject selector = null)
|
||||
{
|
||||
try
|
||||
@@ -594,6 +621,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="indicator">The indicator to receive data from the consolidator</param>
|
||||
/// <param name="consolidator">The consolidator to receive raw subscription data</param>
|
||||
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public void RegisterIndicator(Symbol symbol, PyObject indicator, IDataConsolidator consolidator, PyObject selector = null)
|
||||
{
|
||||
// TODO: to be removed when https://github.com/QuantConnect/pythonnet/issues/62 is solved
|
||||
@@ -627,6 +656,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="indicator">The indicator we want to warm up</param>
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public void WarmUpIndicator(Symbol symbol, PyObject indicator, Resolution? resolution = null, PyObject selector = null)
|
||||
{
|
||||
// TODO: to be removed when https://github.com/QuantConnect/pythonnet/issues/62 is solved
|
||||
@@ -659,6 +690,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="series">Name of the plot series</param>
|
||||
/// <param name="pyObject">PyObject with the value to plot</param>
|
||||
/// <seealso cref="Plot(string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string series, PyObject pyObject)
|
||||
{
|
||||
using (Py.GIL())
|
||||
@@ -685,6 +717,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="third">The third indicator to plot</param>
|
||||
/// <param name="fourth">The fourth indicator to plot</param>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, Indicator first, Indicator second = null, Indicator third = null, Indicator fourth = null)
|
||||
{
|
||||
Plot(chart, new[] { first, second, third, fourth }.Where(x => x != null).ToArray());
|
||||
@@ -699,6 +732,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="third">The third indicator to plot</param>
|
||||
/// <param name="fourth">The fourth indicator to plot</param>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, BarIndicator first, BarIndicator second = null, BarIndicator third = null, BarIndicator fourth = null)
|
||||
{
|
||||
Plot(chart, new[] { first, second, third, fourth }.Where(x => x != null).ToArray());
|
||||
@@ -713,6 +747,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="third">The third indicator to plot</param>
|
||||
/// <param name="fourth">The fourth indicator to plot</param>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, TradeBarIndicator first, TradeBarIndicator second = null, TradeBarIndicator third = null, TradeBarIndicator fourth = null)
|
||||
{
|
||||
Plot(chart, new[] { first, second, third, fourth }.Where(x => x != null).ToArray());
|
||||
@@ -721,6 +756,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Automatically plots each indicator when a new value is available
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Charting)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public void PlotIndicator(string chart, PyObject first, PyObject second = null, PyObject third = null, PyObject fourth = null)
|
||||
{
|
||||
var array = GetIndicatorArray(first, second, third, fourth);
|
||||
@@ -730,6 +767,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Automatically plots each indicator when a new value is available
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Charting)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public void PlotIndicator(string chart, bool waitForReady, PyObject first, PyObject second = null, PyObject third = null, PyObject fourth = null)
|
||||
{
|
||||
var array = GetIndicatorArray(first, second, third, fourth);
|
||||
@@ -745,6 +784,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
|
||||
/// <param name="fieldName">The name of the field being selected</param>
|
||||
/// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public FilteredIdentity FilteredIdentity(Symbol symbol, PyObject selector = null, PyObject filter = null, string fieldName = null)
|
||||
{
|
||||
var resolution = GetSubscription(symbol).Resolution;
|
||||
@@ -761,6 +801,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
|
||||
/// <param name="fieldName">The name of the field being selected</param>
|
||||
/// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public FilteredIdentity FilteredIdentity(Symbol symbol, Resolution resolution, PyObject selector = null, PyObject filter = null, string fieldName = null)
|
||||
{
|
||||
var name = CreateIndicatorName(symbol, fieldName ?? "close", resolution);
|
||||
@@ -781,6 +822,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
|
||||
/// <param name="fieldName">The name of the field being selected</param>
|
||||
/// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public FilteredIdentity FilteredIdentity(Symbol symbol, TimeSpan resolution, PyObject selector = null, PyObject filter = null, string fieldName = null)
|
||||
{
|
||||
var name = $"{symbol}({fieldName ?? "close"}_{resolution.ToStringInvariant(null)})";
|
||||
@@ -799,6 +841,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="periods">The number of bars to request</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>A python dictionary with pandas DataFrame containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public PyObject History(PyObject tickers, int periods, Resolution? resolution = null)
|
||||
{
|
||||
var symbols = tickers.ConvertToSymbolEnumerable();
|
||||
@@ -813,6 +856,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="span">The span over which to retrieve recent historical data</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>A python dictionary with pandas DataFrame containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public PyObject History(PyObject tickers, TimeSpan span, Resolution? resolution = null)
|
||||
{
|
||||
var symbols = tickers.ConvertToSymbolEnumerable();
|
||||
@@ -827,6 +871,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="end">The end time in the algorithm's time zone</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>A python dictionary with pandas DataFrame containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public PyObject History(PyObject tickers, DateTime start, DateTime end, Resolution? resolution = null)
|
||||
{
|
||||
var symbols = tickers.ConvertToSymbolEnumerable();
|
||||
@@ -842,6 +887,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="end">The end time in the algorithm's time zone</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>pandas.DataFrame containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public PyObject History(PyObject type, PyObject tickers, DateTime start, DateTime end, Resolution? resolution = null)
|
||||
{
|
||||
var symbols = tickers.ConvertToSymbolEnumerable();
|
||||
@@ -870,6 +916,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="periods">The number of bars to request</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>pandas.DataFrame containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public PyObject History(PyObject type, PyObject tickers, int periods, Resolution? resolution = null)
|
||||
{
|
||||
var symbols = tickers.ConvertToSymbolEnumerable();
|
||||
@@ -900,6 +947,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="span">The span over which to retrieve recent historical data</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>pandas.DataFrame containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public PyObject History(PyObject type, PyObject tickers, TimeSpan span, Resolution? resolution = null)
|
||||
{
|
||||
return History(type, tickers, Time - span, Time, resolution);
|
||||
@@ -914,6 +962,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="end">The end time in the algorithm's time zone</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>pandas.DataFrame containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public PyObject History(PyObject type, Symbol symbol, DateTime start, DateTime end, Resolution? resolution = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
@@ -941,6 +990,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="periods">The number of bars to request</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>pandas.DataFrame containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public PyObject History(PyObject type, Symbol symbol, int periods, Resolution? resolution = null)
|
||||
{
|
||||
if (resolution == Resolution.Tick) throw new ArgumentException("History functions that accept a 'periods' parameter can not be used with Resolution.Tick");
|
||||
@@ -960,6 +1010,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="span">The span over which to retrieve recent historical data</param>
|
||||
/// <param name="resolution">The resolution to request</param>
|
||||
/// <returns>pandas.DataFrame containing the requested historical data</returns>
|
||||
[DocumentationAttribute(HistoricalData)]
|
||||
public PyObject History(PyObject type, Symbol symbol, TimeSpan span, Resolution? resolution = null)
|
||||
{
|
||||
return History(type, symbol, Time - span, Time, resolution);
|
||||
@@ -970,6 +1021,9 @@ namespace QuantConnect.Algorithm
|
||||
/// the benchmark at each date/time requested
|
||||
/// </summary>
|
||||
/// <param name="benchmark">The benchmark producing function</param>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
[DocumentationAttribute(SecuritiesAndPortfolio)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public void SetBenchmark(PyObject benchmark)
|
||||
{
|
||||
using (Py.GIL())
|
||||
@@ -989,6 +1043,7 @@ namespace QuantConnect.Algorithm
|
||||
/// This can be used to set a custom brokerage model.
|
||||
/// </summary>
|
||||
/// <param name="model">The brokerage model to use</param>
|
||||
[DocumentationAttribute(Modeling)]
|
||||
public void SetBrokerageModel(PyObject model)
|
||||
{
|
||||
IBrokerageModel brokerageModel;
|
||||
@@ -1004,6 +1059,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Sets the security initializer function, used to initialize/configure securities after creation
|
||||
/// </summary>
|
||||
/// <param name="securityInitializer">The security initializer function or class</param>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
[DocumentationAttribute(Modeling)]
|
||||
public void SetSecurityInitializer(PyObject securityInitializer)
|
||||
{
|
||||
var securityInitializer1 = PythonUtil.ToAction<Security>(securityInitializer);
|
||||
@@ -1023,6 +1080,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="address">A string containing the URI to download</param>
|
||||
/// <param name="headers">Defines header values to add to the request</param>
|
||||
/// <returns>The requested resource as a <see cref="string"/></returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
[DocumentationAttribute(MachineLearning)]
|
||||
public string Download(string address, PyObject headers) => Download(address, headers, null, null);
|
||||
|
||||
/// <summary>
|
||||
@@ -1034,6 +1093,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="userName">The user name associated with the credentials</param>
|
||||
/// <param name="password">The password for the user name associated with the credentials</param>
|
||||
/// <returns>The requested resource as a <see cref="string"/></returns>
|
||||
[DocumentationAttribute(AddingData)]
|
||||
[DocumentationAttribute(MachineLearning)]
|
||||
public string Download(string address, PyObject headers, string userName, string password)
|
||||
{
|
||||
var dict = new Dictionary<string, string>();
|
||||
@@ -1068,6 +1129,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="message">Message to send to debug console</param>
|
||||
/// <seealso cref="Log(PyObject)"/>
|
||||
/// <seealso cref="Error(PyObject)"/>
|
||||
[DocumentationAttribute(Logging)]
|
||||
public void Debug(PyObject message)
|
||||
{
|
||||
Debug(message.ToSafeString());
|
||||
@@ -1079,6 +1141,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="message">Message to display in errors grid</param>
|
||||
/// <seealso cref="Debug(PyObject)"/>
|
||||
/// <seealso cref="Log(PyObject)"/>
|
||||
[DocumentationAttribute(Logging)]
|
||||
public void Error(PyObject message)
|
||||
{
|
||||
Error(message.ToSafeString());
|
||||
@@ -1090,6 +1153,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="message">String message to log.</param>
|
||||
/// <seealso cref="Debug(PyObject)"/>
|
||||
/// <seealso cref="Error(PyObject)"/>
|
||||
[DocumentationAttribute(Logging)]
|
||||
public void Log(PyObject message)
|
||||
{
|
||||
Log(message.ToSafeString());
|
||||
@@ -1099,6 +1163,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Terminate the algorithm after processing the current event handler.
|
||||
/// </summary>
|
||||
/// <param name="message">Exit message to display on quitting</param>
|
||||
[DocumentationAttribute(Logging)]
|
||||
public void Quit(PyObject message)
|
||||
{
|
||||
Quit(message.ToSafeString());
|
||||
@@ -1111,6 +1176,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="period">The consolidation period</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate(Symbol symbol, Resolution period, PyObject handler)
|
||||
{
|
||||
return Consolidate(symbol, period.ToTimeSpan(), null, handler);
|
||||
@@ -1124,6 +1190,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate(Symbol symbol, Resolution period, TickType? tickType, PyObject handler)
|
||||
{
|
||||
return Consolidate(symbol, period.ToTimeSpan(), tickType, handler);
|
||||
@@ -1136,6 +1203,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="period">The consolidation period</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, PyObject handler)
|
||||
{
|
||||
return Consolidate(symbol, period, null, handler);
|
||||
@@ -1149,6 +1217,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, TickType? tickType, PyObject handler)
|
||||
{
|
||||
// resolve consolidator input subscription
|
||||
@@ -1174,6 +1243,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="calendar">The consolidation calendar</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
public IDataConsolidator Consolidate(Symbol symbol, Func<DateTime, CalendarInfo> calendar, PyObject handler)
|
||||
{
|
||||
return Consolidate(symbol, calendar, null, handler);
|
||||
@@ -1183,6 +1253,8 @@ namespace QuantConnect.Algorithm
|
||||
/// Schedules the provided training code to execute immediately
|
||||
/// </summary>
|
||||
/// <param name="trainingCode">The training code to be invoked</param>
|
||||
[DocumentationAttribute(MachineLearning)]
|
||||
[DocumentationAttribute(ScheduledEvents)]
|
||||
public ScheduledEvent Train(PyObject trainingCode)
|
||||
{
|
||||
return Schedule.TrainingNow(trainingCode);
|
||||
@@ -1194,6 +1266,8 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="dateRule">Specifies what dates the event should run</param>
|
||||
/// <param name="timeRule">Specifies the times on those dates the event should run</param>
|
||||
/// <param name="trainingCode">The training code to be invoked</param>
|
||||
[DocumentationAttribute(MachineLearning)]
|
||||
[DocumentationAttribute(ScheduledEvents)]
|
||||
public ScheduledEvent Train(IDateRule dateRule, ITimeRule timeRule, PyObject trainingCode)
|
||||
{
|
||||
return Schedule.Training(dateRule, timeRule, trainingCode);
|
||||
@@ -1207,6 +1281,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
|
||||
/// <param name="handler">Data handler receives new consolidated data when generated</param>
|
||||
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
|
||||
[DocumentationAttribute(ConsolidatingData)]
|
||||
private IDataConsolidator Consolidate(Symbol symbol, Func<DateTime, CalendarInfo> calendar, TickType? tickType, PyObject handler)
|
||||
{
|
||||
// resolve consolidator input subscription
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
@@ -33,6 +33,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Transaction Manager - Process transaction fills and order management.
|
||||
/// </summary>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public SecurityTransactionManager Transactions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -42,6 +43,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">int Quantity of the asset to trade</param>
|
||||
/// <seealso cref="Buy(Symbol, double)"/>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Buy(Symbol symbol, int quantity)
|
||||
{
|
||||
return Order(symbol, (decimal)Math.Abs(quantity));
|
||||
@@ -54,6 +56,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">double Quantity of the asset to trade</param>
|
||||
/// <seealso cref="Buy(Symbol, decimal)"/>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Buy(Symbol symbol, double quantity)
|
||||
{
|
||||
return Order(symbol, Math.Abs(quantity).SafeDecimalCast());
|
||||
@@ -66,6 +69,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">decimal Quantity of the asset to trade</param>
|
||||
/// <seealso cref="Order(Symbol, int)"/>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Buy(Symbol symbol, decimal quantity)
|
||||
{
|
||||
return Order(symbol, Math.Abs(quantity));
|
||||
@@ -78,6 +82,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">float Quantity of the asset to trade</param>
|
||||
/// <seealso cref="Buy(Symbol, decimal)"/>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Buy(Symbol symbol, float quantity)
|
||||
{
|
||||
return Order(symbol, (decimal)Math.Abs(quantity));
|
||||
@@ -91,6 +96,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">int Quantity of the asset to trade</param>
|
||||
/// <seealso cref="Sell(Symbol, decimal)"/>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Sell(Symbol symbol, int quantity)
|
||||
{
|
||||
return Order(symbol, (decimal)Math.Abs(quantity) * -1);
|
||||
@@ -102,6 +108,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">String symbol to sell</param>
|
||||
/// <param name="quantity">Quantity to order</param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Sell(Symbol symbol, double quantity)
|
||||
{
|
||||
return Order(symbol, Math.Abs(quantity).SafeDecimalCast() * -1m);
|
||||
@@ -113,6 +120,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">String symbol</param>
|
||||
/// <param name="quantity">Quantity to sell</param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Sell(Symbol symbol, float quantity)
|
||||
{
|
||||
return Order(symbol, (decimal)Math.Abs(quantity) * -1m);
|
||||
@@ -124,6 +132,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">String symbol to sell</param>
|
||||
/// <param name="quantity">Quantity to sell</param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Sell(Symbol symbol, decimal quantity)
|
||||
{
|
||||
return Order(symbol, Math.Abs(quantity) * -1);
|
||||
@@ -136,6 +145,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Quantity to order</param>
|
||||
/// <seealso cref="Order(Symbol, decimal)"/>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Order(Symbol symbol, double quantity)
|
||||
{
|
||||
return Order(symbol, quantity.SafeDecimalCast());
|
||||
@@ -147,6 +157,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">Symbol to order</param>
|
||||
/// <param name="quantity">Quantity to order</param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Order(Symbol symbol, int quantity)
|
||||
{
|
||||
return MarketOrder(symbol, (decimal)quantity);
|
||||
@@ -158,6 +169,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">Symbol to order</param>
|
||||
/// <param name="quantity">Quantity to order</param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Order(Symbol symbol, decimal quantity)
|
||||
{
|
||||
return MarketOrder(symbol, quantity);
|
||||
@@ -173,6 +185,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
/// <seealso cref="MarketOrder(Symbol, decimal, bool, string)"/>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Order(Symbol symbol, decimal quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return MarketOrder(symbol, quantity, asynchronous, tag, orderProperties);
|
||||
@@ -187,6 +200,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket MarketOrder(Symbol symbol, int quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return MarketOrder(symbol, (decimal)quantity, asynchronous, tag, orderProperties);
|
||||
@@ -201,6 +215,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket MarketOrder(Symbol symbol, double quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return MarketOrder(symbol, quantity.SafeDecimalCast(), asynchronous, tag, orderProperties);
|
||||
@@ -215,6 +230,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket MarketOrder(Symbol symbol, decimal quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
@@ -230,6 +246,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket MarketOrder(Security security, decimal quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
// check the exchange is open before sending a market order, if it's not open
|
||||
@@ -284,6 +301,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket MarketOnOpenOrder(Symbol symbol, double quantity, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return MarketOnOpenOrder(symbol, quantity.SafeDecimalCast(), tag, orderProperties);
|
||||
@@ -297,6 +315,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket MarketOnOpenOrder(Symbol symbol, int quantity, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return MarketOnOpenOrder(symbol, (decimal)quantity, tag, orderProperties);
|
||||
@@ -310,6 +329,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket MarketOnOpenOrder(Symbol symbol, decimal quantity, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
@@ -331,6 +351,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket MarketOnCloseOrder(Symbol symbol, int quantity, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return MarketOnCloseOrder(symbol, (decimal)quantity, tag, orderProperties);
|
||||
@@ -344,6 +365,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket MarketOnCloseOrder(Symbol symbol, double quantity, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return MarketOnCloseOrder(symbol, quantity.SafeDecimalCast(), tag, orderProperties);
|
||||
@@ -357,6 +379,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket MarketOnCloseOrder(Symbol symbol, decimal quantity, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
@@ -379,6 +402,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket LimitOrder(Symbol symbol, int quantity, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return LimitOrder(symbol, (decimal)quantity, limitPrice, tag, orderProperties);
|
||||
@@ -393,6 +417,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket LimitOrder(Symbol symbol, double quantity, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return LimitOrder(symbol, quantity.SafeDecimalCast(), limitPrice, tag, orderProperties);
|
||||
@@ -407,6 +432,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket LimitOrder(Symbol symbol, decimal quantity, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
@@ -429,6 +455,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Optional string data tag for the order</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket StopMarketOrder(Symbol symbol, int quantity, decimal stopPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return StopMarketOrder(symbol, (decimal)quantity, stopPrice, tag, orderProperties);
|
||||
@@ -443,6 +470,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Optional string data tag for the order</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket StopMarketOrder(Symbol symbol, double quantity, decimal stopPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return StopMarketOrder(symbol, quantity.SafeDecimalCast(), stopPrice, tag, orderProperties);
|
||||
@@ -457,6 +485,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Optional string data tag for the order</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket StopMarketOrder(Symbol symbol, decimal quantity, decimal stopPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
@@ -480,6 +509,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket StopLimitOrder(Symbol symbol, int quantity, decimal stopPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return StopLimitOrder(symbol, (decimal)quantity, stopPrice, limitPrice, tag, orderProperties);
|
||||
@@ -495,6 +525,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket StopLimitOrder(Symbol symbol, double quantity, decimal stopPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return StopLimitOrder(symbol, quantity.SafeDecimalCast(), stopPrice, limitPrice, tag, orderProperties);
|
||||
@@ -510,6 +541,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket StopLimitOrder(Symbol symbol, decimal quantity, decimal stopPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
@@ -534,6 +566,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket LimitIfTouchedOrder(Symbol symbol, int quantity, decimal triggerPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return LimitIfTouchedOrder(symbol, (decimal)quantity, triggerPrice, limitPrice, tag, orderProperties);
|
||||
@@ -549,6 +582,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket LimitIfTouchedOrder(Symbol symbol, double quantity, decimal triggerPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return LimitIfTouchedOrder(symbol, quantity.SafeDecimalCast(), triggerPrice, limitPrice, tag, orderProperties);
|
||||
@@ -564,6 +598,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket LimitIfTouchedOrder(Symbol symbol, decimal quantity, decimal triggerPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
@@ -587,6 +622,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket ExerciseOption(Symbol optionSymbol, int quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var option = (Option) Securities[optionSymbol];
|
||||
@@ -629,6 +665,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Quantity of the strategy to trade</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>Sequence of order tickets</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public IEnumerable<OrderTicket> Buy(OptionStrategy strategy, int quantity, IOrderProperties orderProperties = null)
|
||||
{
|
||||
return Order(strategy, Math.Abs(quantity), orderProperties);
|
||||
@@ -641,6 +678,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Quantity of the strategy to trade</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>Sequence of order tickets</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public IEnumerable<OrderTicket> Sell(OptionStrategy strategy, int quantity, IOrderProperties orderProperties = null)
|
||||
{
|
||||
return Order(strategy, Math.Abs(quantity) * -1, orderProperties);
|
||||
@@ -653,6 +691,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Quantity of the strategy to trade</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>Sequence of order tickets</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public IEnumerable<OrderTicket> Order(OptionStrategy strategy, int quantity, IOrderProperties orderProperties = null)
|
||||
{
|
||||
return GenerateOrders(strategy, quantity, orderProperties);
|
||||
@@ -925,6 +964,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Custom tag to know who is calling this.</param>
|
||||
/// <returns>Array of order ids for liquidated symbols</returns>
|
||||
/// <seealso cref="MarketOrder(QuantConnect.Symbol,decimal,bool,string)"/>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public List<int> Liquidate(Symbol symbolToLiquidate = null, string tag = "Liquidated")
|
||||
{
|
||||
var orderIdList = new List<int>();
|
||||
@@ -997,6 +1037,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Maximum number of orders for the algorithm
|
||||
/// </summary>
|
||||
/// <param name="max"></param>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetMaximumOrders(int max)
|
||||
{
|
||||
if (!_locked)
|
||||
@@ -1015,6 +1056,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Tag the order with a short string.</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <seealso cref="MarketOrder(QuantConnect.Symbol,decimal,bool,string)"/>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetHoldings(List<PortfolioTarget> targets, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
foreach (var portfolioTarget in targets
|
||||
@@ -1035,6 +1077,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Tag the order with a short string.</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <seealso cref="MarketOrder(QuantConnect.Symbol,decimal,bool,string)"/>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetHoldings(Symbol symbol, double percentage, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
SetHoldings(symbol, percentage.SafeDecimalCast(), liquidateExistingHoldings, tag, orderProperties);
|
||||
@@ -1049,6 +1092,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Tag the order with a short string.</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <seealso cref="MarketOrder(QuantConnect.Symbol,decimal,bool,string)"/>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetHoldings(Symbol symbol, float percentage, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
SetHoldings(symbol, (decimal)percentage, liquidateExistingHoldings, tag, orderProperties);
|
||||
@@ -1063,6 +1107,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Tag the order with a short string.</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <seealso cref="MarketOrder(QuantConnect.Symbol,decimal,bool,string)"/>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetHoldings(Symbol symbol, int percentage, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
SetHoldings(symbol, (decimal)percentage, liquidateExistingHoldings, tag, orderProperties);
|
||||
@@ -1080,6 +1125,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="tag">Tag the order with a short string.</param>
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <seealso cref="MarketOrder(QuantConnect.Symbol,decimal,bool,string)"/>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetHoldings(Symbol symbol, decimal percentage, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
SetHoldingsImpl(symbol, CalculateOrderQuantity(symbol, percentage), liquidateExistingHoldings, tag, orderProperties);
|
||||
@@ -1142,6 +1188,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">Security object we're asking for</param>
|
||||
/// <param name="target">Target percentage holdings</param>
|
||||
/// <returns>Order quantity to achieve this percentage</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public decimal CalculateOrderQuantity(Symbol symbol, double target)
|
||||
{
|
||||
return CalculateOrderQuantity(symbol, target.SafeDecimalCast());
|
||||
@@ -1155,6 +1202,7 @@ namespace QuantConnect.Algorithm
|
||||
/// if you have 2x leverage and request 100% holdings, it will utilize half of the
|
||||
/// available margin</param>
|
||||
/// <returns>Order quantity to achieve this percentage</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public decimal CalculateOrderQuantity(Symbol symbol, decimal target)
|
||||
{
|
||||
var percent = PortfolioTarget.Percent(this, symbol, target, true);
|
||||
@@ -1178,6 +1226,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[Obsolete("This Order method has been made obsolete, use Order(string, int, bool, string) method instead. Calls to the obsolete method will only generate market orders.")]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Order(Symbol symbol, int quantity, OrderType type, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return Order(symbol, quantity, asynchronous, tag, orderProperties);
|
||||
@@ -1191,6 +1240,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="type">The order type</param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[Obsolete("This Order method has been made obsolete, use the specialized Order helper methods instead. Calls to the obsolete method will only generate market orders.")]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Order(Symbol symbol, decimal quantity, OrderType type)
|
||||
{
|
||||
return Order(symbol, quantity);
|
||||
@@ -1204,6 +1254,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="type">The order type</param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
[Obsolete("This Order method has been made obsolete, use the specialized Order helper methods instead. Calls to the obsolete method will only generate market orders.")]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public OrderTicket Order(Symbol symbol, int quantity, OrderType type)
|
||||
{
|
||||
return Order(symbol, (decimal)quantity);
|
||||
@@ -1214,6 +1265,8 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol</param>
|
||||
/// <returns>True if the exchange is considered open at the current time, false otherwise</returns>
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
[DocumentationAttribute(SecuritiesAndPortfolio)]
|
||||
public bool IsMarketOpen(Symbol symbol)
|
||||
{
|
||||
var exchangeHours = MarketHoursDatabase
|
||||
|
||||
@@ -16,13 +16,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NodaTime;
|
||||
using QuantConnect.Algorithm.Selection;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Fundamental;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Future;
|
||||
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Algorithm
|
||||
@@ -43,6 +44,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Gets universe manager which holds universes keyed by their symbol
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public UniverseManager UniverseManager
|
||||
{
|
||||
get;
|
||||
@@ -52,6 +54,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Gets the universe settings to be used when adding securities via universe selection
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public UniverseSettings UniverseSettings
|
||||
{
|
||||
get;
|
||||
@@ -62,6 +65,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Invoked at the end of every time step. This allows the algorithm
|
||||
/// to process events before advancing to the next time step.
|
||||
/// </summary>
|
||||
[DocumentationAttribute(HandlingData)]
|
||||
public void OnEndOfTimeStep()
|
||||
{
|
||||
if (_pendingUniverseAdditions.Count + _pendingUserDefinedUniverseSecurityAdditions.Count == 0)
|
||||
@@ -186,6 +190,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Gets a helper that provides pre-defined universe definitions, such as top dollar volume
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public UniverseDefinitions Universe
|
||||
{
|
||||
get;
|
||||
@@ -196,6 +201,7 @@ namespace QuantConnect.Algorithm
|
||||
/// Adds the universe to the algorithm
|
||||
/// </summary>
|
||||
/// <param name="universe">The universe to be added</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(Universe universe)
|
||||
{
|
||||
// The universe will be added at the end of time step, same as the AddData user defined universes.
|
||||
@@ -213,6 +219,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, Func<IEnumerable<T>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
return AddUniverse(SecurityType.Equity, name, Resolution.Daily, Market.USA, UniverseSettings, selector);
|
||||
@@ -226,6 +233,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, Func<IEnumerable<T>, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverse(SecurityType.Equity, name, Resolution.Daily, Market.USA, UniverseSettings, selector);
|
||||
@@ -240,6 +248,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="universeSettings">The settings used for securities added by this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, UniverseSettings universeSettings, Func<IEnumerable<T>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
return AddUniverse(SecurityType.Equity, name, Resolution.Daily, Market.USA, universeSettings, selector);
|
||||
@@ -254,6 +263,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="universeSettings">The settings used for securities added by this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, UniverseSettings universeSettings, Func<IEnumerable<T>, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverse(SecurityType.Equity, name, Resolution.Daily, Market.USA, universeSettings, selector);
|
||||
@@ -268,6 +278,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The epected resolution of the universe data</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, Resolution resolution, Func<IEnumerable<T>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
return AddUniverse(SecurityType.Equity, name, resolution, Market.USA, UniverseSettings, selector);
|
||||
@@ -282,6 +293,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The epected resolution of the universe data</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, Resolution resolution, Func<IEnumerable<T>, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverse(SecurityType.Equity, name, resolution, Market.USA, UniverseSettings, selector);
|
||||
@@ -297,6 +309,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The epected resolution of the universe data</param>
|
||||
/// <param name="universeSettings">The settings used for securities added by this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, Resolution resolution, UniverseSettings universeSettings, Func<IEnumerable<T>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
return AddUniverse(SecurityType.Equity, name, resolution, Market.USA, universeSettings, selector);
|
||||
@@ -312,6 +325,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The epected resolution of the universe data</param>
|
||||
/// <param name="universeSettings">The settings used for securities added by this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, Resolution resolution, UniverseSettings universeSettings, Func<IEnumerable<T>, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverse(SecurityType.Equity, name, resolution, Market.USA, universeSettings, selector);
|
||||
@@ -327,6 +341,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The epected resolution of the universe data</param>
|
||||
/// <param name="market">The market for selected symbols</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(SecurityType securityType, string name, Resolution resolution, string market, Func<IEnumerable<T>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
return AddUniverse(securityType, name, resolution, market, UniverseSettings, selector);
|
||||
@@ -342,6 +357,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="resolution">The epected resolution of the universe data</param>
|
||||
/// <param name="market">The market for selected symbols</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(SecurityType securityType, string name, Resolution resolution, string market, Func<IEnumerable<T>, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverse(securityType, name, resolution, market, UniverseSettings, selector);
|
||||
@@ -357,6 +373,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="market">The market for selected symbols</param>
|
||||
/// <param name="universeSettings">The subscription settings to use for newly created subscriptions</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, Func<IEnumerable<T>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
var marketHoursDbEntry = MarketHoursDatabase.GetEntry(market, name, securityType);
|
||||
@@ -377,6 +394,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="market">The market for selected symbols</param>
|
||||
/// <param name="universeSettings">The subscription settings to use for newly created subscriptions</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, Func<IEnumerable<T>, IEnumerable<string>> selector)
|
||||
{
|
||||
var marketHoursDbEntry = MarketHoursDatabase.GetEntry(market, name, securityType);
|
||||
@@ -394,6 +412,7 @@ namespace QuantConnect.Algorithm
|
||||
/// will be executed on day changes in the NewYork time zone (<see cref="TimeZones.NewYork"/>
|
||||
/// </summary>
|
||||
/// <param name="selector">Defines an initial coarse selection</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(Func<IEnumerable<CoarseFundamental>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
return AddUniverse(new CoarseFundamentalUniverse(UniverseSettings, selector));
|
||||
@@ -405,6 +424,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="coarseSelector">Defines an initial coarse selection</param>
|
||||
/// <param name="fineSelector">Defines a more detailed selection with access to more data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(Func<IEnumerable<CoarseFundamental>, IEnumerable<Symbol>> coarseSelector, Func<IEnumerable<FineFundamental>, IEnumerable<Symbol>> fineSelector)
|
||||
{
|
||||
var coarse = new CoarseFundamentalUniverse(UniverseSettings, coarseSelector);
|
||||
@@ -418,6 +438,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="universe">The universe to be filtered with fine fundamental selection</param>
|
||||
/// <param name="fineSelector">Defines a more detailed selection with access to more data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(Universe universe, Func<IEnumerable<FineFundamental>, IEnumerable<Symbol>> fineSelector)
|
||||
{
|
||||
return AddUniverse(new FineFundamentalFilteredUniverse(universe, fineSelector));
|
||||
@@ -429,6 +450,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(string name, Func<DateTime, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverse(SecurityType.Equity, name, Resolution.Daily, Market.USA, UniverseSettings, selector);
|
||||
@@ -441,6 +463,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The resolution this universe should be triggered on</param>
|
||||
/// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(string name, Resolution resolution, Func<DateTime, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverse(SecurityType.Equity, name, resolution, Market.USA, UniverseSettings, selector);
|
||||
@@ -455,6 +478,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="market">The market of the universe</param>
|
||||
/// <param name="universeSettings">The subscription settings used for securities added from this universe</param>
|
||||
/// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, Func<DateTime, IEnumerable<string>> selector)
|
||||
{
|
||||
var marketHoursDbEntry = MarketHoursDatabase.GetEntry(market, name, securityType);
|
||||
@@ -472,6 +496,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="underlyingSymbol">Underlying Symbol to add as an option. For Futures, the option chain constructed will be per-contract, as long as a canonical Symbol is provided.</param>
|
||||
/// <param name="optionFilter">User-defined filter used to select the options we want out of the option chain provided.</param>
|
||||
/// <exception cref="InvalidOperationException">The underlying Symbol's universe is not found.</exception>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void AddUniverseOptions(Symbol underlyingSymbol, Func<OptionFilterUniverse, OptionFilterUniverse> optionFilter)
|
||||
{
|
||||
// We need to load the universe associated with the provided Symbol and provide that universe to the option filter universe.
|
||||
@@ -507,6 +532,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="universe">The universe we want to chain an option universe selection model too</param>
|
||||
/// <param name="optionFilter">The option filter universe to use</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void AddUniverseOptions(Universe universe, Func<OptionFilterUniverse, OptionFilterUniverse> optionFilter)
|
||||
{
|
||||
AddUniverseSelection(new OptionChainedUniverseSelectionModel(universe, optionFilter));
|
||||
@@ -557,14 +583,15 @@ namespace QuantConnect.Algorithm
|
||||
{
|
||||
// create a new universe, these subscription settings don't currently get used
|
||||
// since universe selection proper is never invoked on this type of universe
|
||||
var uconfig = new SubscriptionDataConfig(subscription, symbol: universeSymbol, isInternalFeed: true, fillForward: false);
|
||||
var uconfig = new SubscriptionDataConfig(subscription, symbol: universeSymbol, isInternalFeed: true, fillForward: false,
|
||||
exchangeTimeZone: DateTimeZone.Utc,
|
||||
dataTimeZone: DateTimeZone.Utc);
|
||||
|
||||
if (security.Type == SecurityType.Base)
|
||||
{
|
||||
// set entry in market hours database for the universe subscription to match the custom data
|
||||
var symbolString = MarketHoursDatabase.GetDatabaseSymbolKey(uconfig.Symbol);
|
||||
MarketHoursDatabase.SetEntry(uconfig.Market, symbolString, uconfig.SecurityType, security.Exchange.Hours, uconfig.DataTimeZone);
|
||||
}
|
||||
// this is the universe symbol, has no real entry in the mhdb, will default to market and security type
|
||||
// set entry in market hours database for the universe subscription to match the config
|
||||
var symbolString = MarketHoursDatabase.GetDatabaseSymbolKey(uconfig.Symbol);
|
||||
MarketHoursDatabase.SetEntry(uconfig.Market, symbolString, uconfig.SecurityType,
|
||||
SecurityExchangeHours.AlwaysOpen(uconfig.ExchangeTimeZone), uconfig.DataTimeZone);
|
||||
|
||||
universe = new UserDefinedUniverse(uconfig,
|
||||
new UniverseSettings(
|
||||
@@ -593,7 +620,7 @@ namespace QuantConnect.Algorithm
|
||||
else
|
||||
{
|
||||
// should never happen, someone would need to add a non-user defined universe with this symbol
|
||||
throw new Exception("Expected universe with symbol '" + universeSymbol.Value + "' to be of type UserDefinedUniverse.");
|
||||
throw new Exception($"Expected universe with symbol '{universeSymbol.Value}' to be of type {nameof(UserDefinedUniverse)} but was {universe.GetType().Name}.");
|
||||
}
|
||||
|
||||
return security;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
220
Api/Api.cs
220
Api/Api.cs
@@ -21,10 +21,14 @@ using System.Net;
|
||||
using System.Net.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RestSharp;
|
||||
using RestSharp.Extensions;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Logging;
|
||||
using QuantConnect.Optimizer.Objectives;
|
||||
using QuantConnect.Optimizer.Parameters;
|
||||
using QuantConnect.Orders;
|
||||
using RestSharp;
|
||||
using QuantConnect.Statistics;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Api
|
||||
@@ -1184,6 +1188,220 @@ namespace QuantConnect.Api
|
||||
return response.Organization;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Estimate optimization with the specified parameters via QuantConnect.com API
|
||||
/// </summary>
|
||||
/// <param name="projectId">Project ID of the project the optimization belongs to</param>
|
||||
/// <param name="name">Name of the optimization</param>
|
||||
/// <param name="target">Target of the optimization, see examples in <see cref="PortfolioStatistics"/></param>
|
||||
/// <param name="targetTo">Target extremum of the optimization, for example "max" or "min"</param>
|
||||
/// <param name="targetValue">Optimization target value</param>
|
||||
/// <param name="strategy">Optimization strategy, <see cref="GridSearchOptimizationStrategy"/></param>
|
||||
/// <param name="compileId">Optimization compile ID</param>
|
||||
/// <param name="parameters">Optimization parameters</param>
|
||||
/// <param name="constraints">Optimization constraints</param>
|
||||
/// <returns>Estimate object from the API.</returns>
|
||||
public Estimate EstimateOptimization(
|
||||
int projectId,
|
||||
string name,
|
||||
string target,
|
||||
string targetTo,
|
||||
decimal? targetValue,
|
||||
string strategy,
|
||||
string compileId,
|
||||
HashSet<OptimizationParameter> parameters,
|
||||
IReadOnlyList<Constraint> constraints)
|
||||
{
|
||||
var request = new RestRequest("optimizations/estimate", Method.POST)
|
||||
{
|
||||
RequestFormat = DataFormat.Json
|
||||
};
|
||||
|
||||
request.AddParameter("application/json", JsonConvert.SerializeObject(new
|
||||
{
|
||||
projectId,
|
||||
name,
|
||||
target,
|
||||
targetTo,
|
||||
targetValue,
|
||||
strategy,
|
||||
compileId,
|
||||
parameters,
|
||||
constraints
|
||||
}), ParameterType.RequestBody);
|
||||
|
||||
ApiConnection.TryRequest(request, out EstimateResponseWrapper response);
|
||||
return response.Estimate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an optimization with the specified parameters via QuantConnect.com API
|
||||
/// </summary>
|
||||
/// <param name="projectId">Project ID of the project the optimization belongs to</param>
|
||||
/// <param name="name">Name of the optimization</param>
|
||||
/// <param name="target">Target of the optimization, see examples in <see cref="PortfolioStatistics"/></param>
|
||||
/// <param name="targetTo">Target extremum of the optimization, for example "max" or "min"</param>
|
||||
/// <param name="targetValue">Optimization target value</param>
|
||||
/// <param name="strategy">Optimization strategy, <see cref="GridSearchOptimizationStrategy"/></param>
|
||||
/// <param name="compileId">Optimization compile ID</param>
|
||||
/// <param name="parameters">Optimization parameters</param>
|
||||
/// <param name="constraints">Optimization constraints</param>
|
||||
/// <param name="estimatedCost">Estimated cost for optimization</param>
|
||||
/// <param name="nodeType">Optimization node type <see cref="OptimizationNodes"/></param>
|
||||
/// <param name="parallelNodes">Number of parallel nodes for optimization</param>
|
||||
/// <returns>BaseOptimization object from the API.</returns>
|
||||
public BaseOptimization CreateOptimization(
|
||||
int projectId,
|
||||
string name,
|
||||
string target,
|
||||
string targetTo,
|
||||
decimal? targetValue,
|
||||
string strategy,
|
||||
string compileId,
|
||||
HashSet<OptimizationParameter> parameters,
|
||||
IReadOnlyList<Constraint> constraints,
|
||||
decimal estimatedCost,
|
||||
string nodeType,
|
||||
int parallelNodes)
|
||||
{
|
||||
var request = new RestRequest("optimizations/create", Method.POST)
|
||||
{
|
||||
RequestFormat = DataFormat.Json
|
||||
};
|
||||
|
||||
request.AddParameter("application/json", JsonConvert.SerializeObject(new
|
||||
{
|
||||
projectId,
|
||||
name,
|
||||
target,
|
||||
targetTo,
|
||||
targetValue,
|
||||
strategy,
|
||||
compileId,
|
||||
parameters,
|
||||
constraints,
|
||||
estimatedCost,
|
||||
nodeType,
|
||||
parallelNodes
|
||||
}), ParameterType.RequestBody);
|
||||
|
||||
ApiConnection.TryRequest(request, out OptimizationList result);
|
||||
return result.Optimizations.FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all the optimizations for a project
|
||||
/// </summary>
|
||||
/// <param name="projectId">Project id we'd like to get a list of optimizations for</param>
|
||||
/// <returns>A list of BaseOptimization objects, <see cref="BaseOptimization"/></returns>
|
||||
public List<BaseOptimization> ListOptimizations(int projectId)
|
||||
{
|
||||
var request = new RestRequest("optimizations/list", Method.POST)
|
||||
{
|
||||
RequestFormat = DataFormat.Json
|
||||
};
|
||||
|
||||
request.AddParameter("application/json", JsonConvert.SerializeObject(new
|
||||
{
|
||||
projectId,
|
||||
}), ParameterType.RequestBody);
|
||||
|
||||
ApiConnection.TryRequest(request, out OptimizationList result);
|
||||
return result.Optimizations;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an optimization
|
||||
/// </summary>
|
||||
/// <param name="optimizationId">Optimization id for the optimization we want to read</param>
|
||||
/// <returns><see cref="Optimization"/></returns>
|
||||
public Optimization ReadOptimization(string optimizationId)
|
||||
{
|
||||
var request = new RestRequest("optimizations/read", Method.POST)
|
||||
{
|
||||
RequestFormat = DataFormat.Json
|
||||
};
|
||||
|
||||
request.AddParameter("application/json", JsonConvert.SerializeObject(new
|
||||
{
|
||||
optimizationId
|
||||
}), ParameterType.RequestBody);
|
||||
|
||||
ApiConnection.TryRequest(request, out OptimizationResponseWrapper response);
|
||||
return response.Optimization;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abort an optimization
|
||||
/// </summary>
|
||||
/// <param name="optimizationId">Optimization id for the optimization we want to abort</param>
|
||||
/// <returns><see cref="RestResponse"/></returns>
|
||||
public RestResponse AbortOptimization(string optimizationId)
|
||||
{
|
||||
var request = new RestRequest("optimizations/abort", Method.POST)
|
||||
{
|
||||
RequestFormat = DataFormat.Json
|
||||
};
|
||||
|
||||
request.AddParameter("application/json", JsonConvert.SerializeObject(new
|
||||
{
|
||||
optimizationId
|
||||
}), ParameterType.RequestBody);
|
||||
|
||||
ApiConnection.TryRequest(request, out RestResponse result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update an optimization
|
||||
/// </summary>
|
||||
/// <param name="optimizationId">Optimization id we want to update</param>
|
||||
/// <param name="name">Name we'd like to assign to the optimization</param>
|
||||
/// <returns><see cref="RestResponse"/></returns>
|
||||
public RestResponse UpdateOptimization(string optimizationId, string name = null)
|
||||
{
|
||||
var request = new RestRequest("optimizations/update", Method.POST)
|
||||
{
|
||||
RequestFormat = DataFormat.Json
|
||||
};
|
||||
|
||||
var obj = new JObject
|
||||
{
|
||||
{ "optimizationId", optimizationId }
|
||||
};
|
||||
|
||||
if (name.HasValue())
|
||||
{
|
||||
obj.Add("name", name);
|
||||
}
|
||||
|
||||
request.AddParameter("application/json", JsonConvert.SerializeObject(obj), ParameterType.RequestBody);
|
||||
|
||||
ApiConnection.TryRequest(request, out RestResponse result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete an optimization
|
||||
/// </summary>
|
||||
/// <param name="optimizationId">Optimization id for the optimization we want to delete</param>
|
||||
/// <returns><see cref="RestResponse"/></returns>
|
||||
public RestResponse DeleteOptimization(string optimizationId)
|
||||
{
|
||||
var request = new RestRequest("optimizations/delete", Method.POST)
|
||||
{
|
||||
RequestFormat = DataFormat.Json
|
||||
};
|
||||
|
||||
request.AddParameter("application/json", JsonConvert.SerializeObject(new
|
||||
{
|
||||
optimizationId
|
||||
}), ParameterType.RequestBody);
|
||||
|
||||
ApiConnection.TryRequest(request, out RestResponse result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to normalize path for api data requests
|
||||
/// </summary>
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
<Message Text="SelectedOptimization $(SelectedOptimization)" Importance="high" />
|
||||
</Target>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DotNetZip" Version="1.13.3" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -255,7 +255,7 @@ namespace QuantConnect.Brokerages.Backtesting
|
||||
var stillNeedsScan = false;
|
||||
|
||||
// process each pending order to produce fills/fire events
|
||||
foreach (var kvp in _pending.OrderBy(x => x.Key))
|
||||
foreach (var kvp in _pending.OrderBySafe(x => x.Key))
|
||||
{
|
||||
var order = kvp.Value;
|
||||
if (order == null)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
@@ -33,52 +33,61 @@ namespace QuantConnect.Brokerages
|
||||
{
|
||||
private const int ConnectionTimeout = 30000;
|
||||
|
||||
/// <summary>
|
||||
/// True if the current brokerage is already initialized
|
||||
/// </summary>
|
||||
protected bool IsInitialized { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The websockets client instance
|
||||
/// </summary>
|
||||
protected readonly IWebSocket WebSocket;
|
||||
protected IWebSocket WebSocket { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The rest client instance
|
||||
/// </summary>
|
||||
protected readonly IRestClient RestClient;
|
||||
protected IRestClient RestClient { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// standard json parsing settings
|
||||
/// </summary>
|
||||
protected readonly JsonSerializerSettings JsonSettings;
|
||||
protected JsonSerializerSettings JsonSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of currently active orders
|
||||
/// </summary>
|
||||
public readonly ConcurrentDictionary<int, Orders.Order> CachedOrderIDs;
|
||||
public ConcurrentDictionary<int, Orders.Order> CachedOrderIDs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The api secret
|
||||
/// </summary>
|
||||
protected readonly string ApiSecret;
|
||||
protected string ApiSecret { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The api key
|
||||
/// </summary>
|
||||
protected readonly string ApiKey;
|
||||
protected string ApiKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Count subscribers for each (symbol, tickType) combination
|
||||
/// </summary>
|
||||
protected DataQueueHandlerSubscriptionManager SubscriptionManager;
|
||||
protected DataQueueHandlerSubscriptionManager SubscriptionManager { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of a websockets brokerage
|
||||
/// Initialize the instance of this class
|
||||
/// </summary>
|
||||
/// <param name="wssUrl">Websockets base url</param>
|
||||
/// <param name="websocket">Websocket client instance</param>
|
||||
/// <param name="restClient">Rest client instance</param>
|
||||
/// <param name="apiKey">Brokerage api auth key</param>
|
||||
/// <param name="apiSecret">Brokerage api auth secret</param>
|
||||
/// <param name="name">Name of brokerage</param>
|
||||
protected BaseWebsocketsBrokerage(string wssUrl, IWebSocket websocket, IRestClient restClient, string apiKey, string apiSecret, string name) : base(name)
|
||||
/// <param name="wssUrl">The web socket base url</param>
|
||||
/// <param name="websocket">instance of websockets client</param>
|
||||
/// <param name="restClient">instance of rest client</param>
|
||||
/// <param name="apiKey">api key</param>
|
||||
/// <param name="apiSecret">api secret</param>
|
||||
protected void Initialize(string wssUrl, IWebSocket websocket, IRestClient restClient, string apiKey, string apiSecret)
|
||||
{
|
||||
if (IsInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
IsInitialized = true;
|
||||
JsonSettings = new JsonSerializerSettings { FloatParseHandling = FloatParseHandling.Decimal };
|
||||
CachedOrderIDs = new ConcurrentDictionary<int, Orders.Order>();
|
||||
|
||||
@@ -97,6 +106,14 @@ namespace QuantConnect.Brokerages
|
||||
ApiKey = apiKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of a websockets brokerage
|
||||
/// </summary>
|
||||
/// <param name="name">Name of brokerage</param>
|
||||
protected BaseWebsocketsBrokerage(string name) : base(name)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles websocket received messages
|
||||
/// </summary>
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace QuantConnect.Brokerages.Binance
|
||||
{
|
||||
public partial class BinanceBrokerage
|
||||
{
|
||||
private readonly IDataAggregator _aggregator;
|
||||
private IDataAggregator _aggregator;
|
||||
|
||||
/// <summary>
|
||||
/// Locking object for the Ticks list in the data queue handler
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
@@ -20,14 +23,11 @@ using QuantConnect.Logging;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Packets;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Util;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Util;
|
||||
using Timer = System.Timers.Timer;
|
||||
|
||||
namespace QuantConnect.Brokerages.Binance
|
||||
@@ -38,24 +38,31 @@ namespace QuantConnect.Brokerages.Binance
|
||||
[BrokerageFactory(typeof(BinanceBrokerageFactory))]
|
||||
public partial class BinanceBrokerage : BaseWebsocketsBrokerage, IDataQueueHandler
|
||||
{
|
||||
|
||||
private readonly IAlgorithm _algorithm;
|
||||
private IAlgorithm _algorithm;
|
||||
private readonly SymbolPropertiesDatabaseSymbolMapper _symbolMapper = new SymbolPropertiesDatabaseSymbolMapper(Market.Binance);
|
||||
|
||||
// Binance allows 5 messages per second, but we still get rate limited if we send a lot of messages at that rate
|
||||
// By sending 3 messages per second, evenly spaced out, we can keep sending messages without being limited
|
||||
private readonly RateGate _webSocketRateLimiter = new RateGate(1, TimeSpan.FromMilliseconds(330));
|
||||
|
||||
private long _lastRequestId;
|
||||
|
||||
private LiveNodePacket _job;
|
||||
private string _webSocketBaseUrl;
|
||||
private readonly Timer _keepAliveTimer;
|
||||
private readonly Timer _reconnectTimer;
|
||||
private readonly BinanceRestApiClient _apiClient;
|
||||
private readonly BrokerageConcurrentMessageHandler<WebSocketMessage> _messageHandler;
|
||||
private Timer _keepAliveTimer;
|
||||
private Timer _reconnectTimer;
|
||||
private BinanceRestApiClient _apiClient;
|
||||
private BrokerageConcurrentMessageHandler<WebSocketMessage> _messageHandler;
|
||||
|
||||
private const int MaximumSymbolsPerConnection = 512;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for brokerage
|
||||
/// </summary>
|
||||
public BinanceBrokerage() : base("Binance")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for brokerage
|
||||
/// </summary>
|
||||
@@ -67,67 +74,17 @@ namespace QuantConnect.Brokerages.Binance
|
||||
/// <param name="aggregator">the aggregator for consolidating ticks</param>
|
||||
/// <param name="job">The live job packet</param>
|
||||
public BinanceBrokerage(string apiKey, string apiSecret, string restApiUrl, string webSocketBaseUrl, IAlgorithm algorithm, IDataAggregator aggregator, LiveNodePacket job)
|
||||
: base(webSocketBaseUrl, new WebSocketClientWrapper(), null, apiKey, apiSecret, "Binance")
|
||||
: base("Binance")
|
||||
{
|
||||
_job = job;
|
||||
_algorithm = algorithm;
|
||||
_aggregator = aggregator;
|
||||
_webSocketBaseUrl = webSocketBaseUrl;
|
||||
_messageHandler = new BrokerageConcurrentMessageHandler<WebSocketMessage>(OnUserMessage);
|
||||
|
||||
var maximumWebSocketConnections = Config.GetInt("binance-maximum-websocket-connections");
|
||||
var symbolWeights = maximumWebSocketConnections > 0 ? FetchSymbolWeights() : null;
|
||||
|
||||
var subscriptionManager = new BrokerageMultiWebSocketSubscriptionManager(
|
||||
webSocketBaseUrl,
|
||||
MaximumSymbolsPerConnection,
|
||||
maximumWebSocketConnections,
|
||||
symbolWeights,
|
||||
() => new BinanceWebSocketWrapper(null),
|
||||
Subscribe,
|
||||
Unsubscribe,
|
||||
OnDataMessage,
|
||||
new TimeSpan(23, 45, 0));
|
||||
|
||||
SubscriptionManager = subscriptionManager;
|
||||
|
||||
_apiClient = new BinanceRestApiClient(_symbolMapper,
|
||||
algorithm?.Portfolio,
|
||||
apiKey,
|
||||
apiSecret,
|
||||
restApiUrl);
|
||||
|
||||
_apiClient.OrderSubmit += (s, e) => OnOrderSubmit(e);
|
||||
_apiClient.OrderStatusChanged += (s, e) => OnOrderEvent(e);
|
||||
_apiClient.Message += (s, e) => OnMessage(e);
|
||||
|
||||
// User data streams will close after 60 minutes. It's recommended to send a ping about every 30 minutes.
|
||||
// Source: https://github.com/binance-exchange/binance-official-api-docs/blob/master/user-data-stream.md#pingkeep-alive-a-listenkey
|
||||
_keepAliveTimer = new Timer
|
||||
{
|
||||
// 30 minutes
|
||||
Interval = 30 * 60 * 1000
|
||||
};
|
||||
_keepAliveTimer.Elapsed += (s, e) => _apiClient.SessionKeepAlive();
|
||||
|
||||
WebSocket.Open += (s, e) => { _keepAliveTimer.Start(); };
|
||||
WebSocket.Closed += (s, e) => { _keepAliveTimer.Stop(); };
|
||||
|
||||
// A single connection to stream.binance.com is only valid for 24 hours; expect to be disconnected at the 24 hour mark
|
||||
// Source: https://github.com/binance-exchange/binance-official-api-docs/blob/master/web-socket-streams.md#general-wss-information
|
||||
_reconnectTimer = new Timer
|
||||
{
|
||||
// 23.5 hours
|
||||
Interval = 23.5 * 60 * 60 * 1000
|
||||
};
|
||||
_reconnectTimer.Elapsed += (s, e) =>
|
||||
{
|
||||
Log.Trace("Daily websocket restart: disconnect");
|
||||
Disconnect();
|
||||
|
||||
Log.Trace("Daily websocket restart: connect");
|
||||
Connect();
|
||||
};
|
||||
Initialize(
|
||||
wssUrl: webSocketBaseUrl,
|
||||
restApiUrl: restApiUrl,
|
||||
apiKey: apiKey,
|
||||
apiSecret: apiSecret,
|
||||
algorithm: algorithm,
|
||||
aggregator: aggregator,
|
||||
job: job
|
||||
);
|
||||
}
|
||||
|
||||
#region IBrokerage
|
||||
@@ -209,18 +166,22 @@ namespace QuantConnect.Brokerages.Binance
|
||||
case "MARKET":
|
||||
order = new MarketOrder { Price = item.Price };
|
||||
break;
|
||||
|
||||
case "LIMIT":
|
||||
case "LIMIT_MAKER":
|
||||
order = new LimitOrder { LimitPrice = item.Price };
|
||||
break;
|
||||
|
||||
case "STOP_LOSS":
|
||||
case "TAKE_PROFIT":
|
||||
order = new StopMarketOrder { StopPrice = item.StopPrice, Price = item.Price };
|
||||
break;
|
||||
|
||||
case "STOP_LOSS_LIMIT":
|
||||
case "TAKE_PROFIT_LIMIT":
|
||||
order = new StopLimitOrder { StopPrice = item.StopPrice, LimitPrice = item.Price };
|
||||
break;
|
||||
|
||||
default:
|
||||
OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Error, -1,
|
||||
"BinanceBrokerage.GetOpenOrders: Unsupported order type returned from brokerage: " + item.Type));
|
||||
@@ -344,7 +305,7 @@ namespace QuantConnect.Brokerages.Binance
|
||||
_messageHandler.HandleNewMessage(e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion IBrokerage
|
||||
|
||||
#region IDataQueueHandler
|
||||
|
||||
@@ -354,6 +315,27 @@ namespace QuantConnect.Brokerages.Binance
|
||||
/// <param name="job">Job we're subscribing for</param>
|
||||
public void SetJob(LiveNodePacket job)
|
||||
{
|
||||
var webSocketBaseUrl = job.BrokerageData["binance-websocket-url"];
|
||||
var restApiUrl = job.BrokerageData["binance-api-url"];
|
||||
var apiKey = job.BrokerageData["binance-api-key"];
|
||||
var apiSecret = job.BrokerageData["binance-api-secret"];
|
||||
var aggregator = Composer.Instance.GetExportedValueByTypeName<IDataAggregator>(
|
||||
Config.Get("data-aggregator", "QuantConnect.Lean.Engine.DataFeeds.AggregationManager"));
|
||||
|
||||
Initialize(
|
||||
wssUrl: webSocketBaseUrl,
|
||||
restApiUrl: restApiUrl,
|
||||
apiKey: apiKey,
|
||||
apiSecret: apiSecret,
|
||||
algorithm: null,
|
||||
aggregator: aggregator,
|
||||
job: job
|
||||
);
|
||||
|
||||
if (!IsConnected)
|
||||
{
|
||||
Connect();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -366,7 +348,7 @@ namespace QuantConnect.Brokerages.Binance
|
||||
{
|
||||
if (!CanSubscribe(dataConfig.Symbol))
|
||||
{
|
||||
return Enumerable.Empty<BaseData>().GetEnumerator();
|
||||
return null;
|
||||
}
|
||||
|
||||
var enumerator = _aggregator.Add(dataConfig, newDataAvailableHandler);
|
||||
@@ -393,10 +375,11 @@ namespace QuantConnect.Brokerages.Binance
|
||||
private static bool CanSubscribe(Symbol symbol)
|
||||
{
|
||||
return !symbol.Value.Contains("UNIVERSE") &&
|
||||
symbol.SecurityType == SecurityType.Crypto;
|
||||
symbol.SecurityType == SecurityType.Crypto &&
|
||||
symbol.ID.Market == Market.Binance;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion IDataQueueHandler
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
@@ -418,6 +401,85 @@ namespace QuantConnect.Brokerages.Binance
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the instance of this class
|
||||
/// </summary>
|
||||
/// <param name="wssUrl">The web socket base url</param>
|
||||
/// <param name="restApiUrl">The rest api url</param>
|
||||
/// <param name="apiKey">api key</param>
|
||||
/// <param name="apiSecret">api secret</param>
|
||||
/// <param name="algorithm">the algorithm instance is required to retrieve account type</param>
|
||||
/// <param name="aggregator">the aggregator for consolidating ticks</param>
|
||||
/// <param name="job">The live job packet</param>
|
||||
private void Initialize(string wssUrl, string restApiUrl,string apiKey, string apiSecret,
|
||||
IAlgorithm algorithm, IDataAggregator aggregator, LiveNodePacket job)
|
||||
{
|
||||
if (IsInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
base.Initialize(wssUrl, new WebSocketClientWrapper(), null, apiKey, apiSecret);
|
||||
_job = job;
|
||||
_algorithm = algorithm;
|
||||
_aggregator = aggregator;
|
||||
_webSocketBaseUrl = wssUrl;
|
||||
_messageHandler = new BrokerageConcurrentMessageHandler<WebSocketMessage>(OnUserMessage);
|
||||
|
||||
var maximumWebSocketConnections = Config.GetInt("binance-maximum-websocket-connections");
|
||||
var symbolWeights = maximumWebSocketConnections > 0 ? FetchSymbolWeights() : null;
|
||||
|
||||
var subscriptionManager = new BrokerageMultiWebSocketSubscriptionManager(
|
||||
wssUrl,
|
||||
MaximumSymbolsPerConnection,
|
||||
maximumWebSocketConnections,
|
||||
symbolWeights,
|
||||
() => new BinanceWebSocketWrapper(null),
|
||||
Subscribe,
|
||||
Unsubscribe,
|
||||
OnDataMessage,
|
||||
new TimeSpan(23, 45, 0));
|
||||
|
||||
SubscriptionManager = subscriptionManager;
|
||||
|
||||
_apiClient = new BinanceRestApiClient(_symbolMapper,
|
||||
algorithm?.Portfolio,
|
||||
apiKey,
|
||||
apiSecret,
|
||||
restApiUrl);
|
||||
|
||||
_apiClient.OrderSubmit += (s, e) => OnOrderSubmit(e);
|
||||
_apiClient.OrderStatusChanged += (s, e) => OnOrderEvent(e);
|
||||
_apiClient.Message += (s, e) => OnMessage(e);
|
||||
|
||||
// User data streams will close after 60 minutes. It's recommended to send a ping about every 30 minutes.
|
||||
// Source: https://github.com/binance-exchange/binance-official-api-docs/blob/master/user-data-stream.md#pingkeep-alive-a-listenkey
|
||||
_keepAliveTimer = new Timer
|
||||
{
|
||||
// 30 minutes
|
||||
Interval = 30 * 60 * 1000
|
||||
};
|
||||
_keepAliveTimer.Elapsed += (s, e) => _apiClient.SessionKeepAlive();
|
||||
|
||||
WebSocket.Open += (s, e) => { _keepAliveTimer.Start(); };
|
||||
WebSocket.Closed += (s, e) => { _keepAliveTimer.Stop(); };
|
||||
|
||||
// A single connection to stream.binance.com is only valid for 24 hours; expect to be disconnected at the 24 hour mark
|
||||
// Source: https://github.com/binance-exchange/binance-official-api-docs/blob/master/web-socket-streams.md#general-wss-information
|
||||
_reconnectTimer = new Timer
|
||||
{
|
||||
// 23.5 hours
|
||||
Interval = 23.5 * 60 * 60 * 1000
|
||||
};
|
||||
_reconnectTimer.Elapsed += (s, e) =>
|
||||
{
|
||||
Log.Trace("Daily websocket restart: disconnect");
|
||||
Disconnect();
|
||||
|
||||
Log.Trace("Daily websocket restart: connect");
|
||||
Connect();
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to the requested symbol (using an individual streaming channel)
|
||||
/// </summary>
|
||||
|
||||
@@ -15,13 +15,16 @@
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using QuantConnect.Brokerages.Bitfinex.Messages;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Logging;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using QuantConnect.Packets;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Crypto;
|
||||
using QuantConnect.Util;
|
||||
using RestSharp;
|
||||
using System;
|
||||
@@ -29,9 +32,6 @@ using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using QuantConnect.Brokerages.Bitfinex.Messages;
|
||||
using QuantConnect.Packets;
|
||||
using QuantConnect.Securities.Crypto;
|
||||
using Order = QuantConnect.Orders.Order;
|
||||
|
||||
namespace QuantConnect.Brokerages.Bitfinex
|
||||
@@ -45,26 +45,34 @@ namespace QuantConnect.Brokerages.Bitfinex
|
||||
private const string RestApiUrl = "https://api.bitfinex.com";
|
||||
private const string WebSocketUrl = "wss://api.bitfinex.com/ws/2";
|
||||
|
||||
private readonly LiveNodePacket _job;
|
||||
private readonly IAlgorithm _algorithm;
|
||||
private LiveNodePacket _job;
|
||||
private IAlgorithm _algorithm;
|
||||
private readonly RateGate _restRateLimiter = new RateGate(10, TimeSpan.FromMinutes(1));
|
||||
private readonly ConcurrentDictionary<int, decimal> _fills = new ConcurrentDictionary<int, decimal>();
|
||||
private readonly SymbolPropertiesDatabase _symbolPropertiesDatabase;
|
||||
private readonly IDataAggregator _aggregator;
|
||||
private SymbolPropertiesDatabase _symbolPropertiesDatabase;
|
||||
private IDataAggregator _aggregator;
|
||||
|
||||
// map Bitfinex ClientOrderId -> LEAN order (only used for orders submitted in PlaceOrder, not for existing orders)
|
||||
private readonly ConcurrentDictionary<long, Order> _orderMap = new ConcurrentDictionary<long, Order>();
|
||||
|
||||
private readonly object _clientOrderIdLocker = new object();
|
||||
private long _nextClientOrderId;
|
||||
|
||||
// map Bitfinex currency to LEAN currency
|
||||
private readonly Dictionary<string, string> _currencyMap;
|
||||
private Dictionary<string, string> _currencyMap;
|
||||
|
||||
/// <summary>
|
||||
/// Locking object for the Ticks list in the data queue handler
|
||||
/// </summary>
|
||||
public readonly object TickLocker = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for brokerage
|
||||
/// </summary>
|
||||
public BitfinexBrokerage() : base("Bitfinex")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for brokerage
|
||||
/// </summary>
|
||||
@@ -91,39 +99,18 @@ namespace QuantConnect.Brokerages.Bitfinex
|
||||
/// <param name="aggregator">consolidate ticks</param>
|
||||
/// <param name="job">The live job packet</param>
|
||||
public BitfinexBrokerage(IWebSocket websocket, IRestClient restClient, string apiKey, string apiSecret, IAlgorithm algorithm, IPriceProvider priceProvider, IDataAggregator aggregator, LiveNodePacket job)
|
||||
: base(WebSocketUrl, websocket, restClient, apiKey, apiSecret, "Bitfinex")
|
||||
: base("Bitfinex")
|
||||
{
|
||||
_job = job;
|
||||
|
||||
SubscriptionManager = new BrokerageMultiWebSocketSubscriptionManager(
|
||||
WebSocketUrl,
|
||||
MaximumSymbolsPerConnection,
|
||||
0,
|
||||
null,
|
||||
() => new BitfinexWebSocketWrapper(null),
|
||||
Subscribe,
|
||||
Unsubscribe,
|
||||
OnDataMessage,
|
||||
TimeSpan.Zero,
|
||||
_connectionRateLimiter);
|
||||
|
||||
_symbolPropertiesDatabase = SymbolPropertiesDatabase.FromDataFolder();
|
||||
_algorithm = algorithm;
|
||||
_aggregator = aggregator;
|
||||
|
||||
// load currency map
|
||||
using (var wc = new WebClient())
|
||||
{
|
||||
var json = wc.DownloadString("https://api-pub.bitfinex.com/v2/conf/pub:map:currency:sym");
|
||||
var rows = JsonConvert.DeserializeObject<List<List<List<string>>>>(json)[0];
|
||||
_currencyMap = rows
|
||||
.ToDictionary(row => row[0], row => row[1].ToUpperInvariant());
|
||||
}
|
||||
|
||||
WebSocket.Open += (sender, args) =>
|
||||
{
|
||||
SubscribeAuth();
|
||||
};
|
||||
Initialize(
|
||||
wssUrl: WebSocketUrl,
|
||||
websocket: websocket,
|
||||
restClient: restClient,
|
||||
apiKey: apiKey,
|
||||
apiSecret: apiSecret,
|
||||
algorithm: algorithm,
|
||||
aggregator: aggregator,
|
||||
job: job
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -169,6 +156,57 @@ namespace QuantConnect.Brokerages.Bitfinex
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the instance of this class
|
||||
/// </summary>
|
||||
/// <param name="wssUrl">The web socket base url</param>
|
||||
/// <param name="websocket">instance of websockets client</param>
|
||||
/// <param name="restClient">instance of rest client</param>
|
||||
/// <param name="apiKey">api key</param>
|
||||
/// <param name="apiSecret">api secret</param>
|
||||
/// <param name="algorithm">the algorithm instance is required to retrieve account type</param>
|
||||
/// <param name="aggregator">the aggregator for consolidating ticks</param>
|
||||
/// <param name="job">The live job packet</param>
|
||||
private void Initialize(string wssUrl, IWebSocket websocket, IRestClient restClient, string apiKey,
|
||||
string apiSecret, IAlgorithm algorithm, IDataAggregator aggregator, LiveNodePacket job)
|
||||
{
|
||||
if (IsInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
base.Initialize(wssUrl, websocket, restClient, apiKey, apiSecret);
|
||||
_job = job;
|
||||
SubscriptionManager = new BrokerageMultiWebSocketSubscriptionManager(
|
||||
WebSocketUrl,
|
||||
MaximumSymbolsPerConnection,
|
||||
0,
|
||||
null,
|
||||
() => new BitfinexWebSocketWrapper(null),
|
||||
Subscribe,
|
||||
Unsubscribe,
|
||||
OnDataMessage,
|
||||
TimeSpan.Zero,
|
||||
_connectionRateLimiter);
|
||||
|
||||
_symbolPropertiesDatabase = SymbolPropertiesDatabase.FromDataFolder();
|
||||
_algorithm = algorithm;
|
||||
_aggregator = aggregator;
|
||||
|
||||
// load currency map
|
||||
using (var wc = new WebClient())
|
||||
{
|
||||
var json = wc.DownloadString("https://api-pub.bitfinex.com/v2/conf/pub:map:currency:sym");
|
||||
var rows = JsonConvert.DeserializeObject<List<List<List<string>>>>(json)[0];
|
||||
_currencyMap = rows
|
||||
.ToDictionary(row => row[0], row => row[1].ToUpperInvariant());
|
||||
}
|
||||
|
||||
WebSocket.Open += (sender, args) =>
|
||||
{
|
||||
SubscribeAuth();
|
||||
};
|
||||
}
|
||||
|
||||
private long GetNextClientOrderId()
|
||||
{
|
||||
lock (_clientOrderIdLocker)
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
*/
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using QuantConnect.Brokerages.Bitfinex.Messages;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
@@ -21,13 +23,13 @@ using QuantConnect.Logging;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Packets;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Crypto;
|
||||
using QuantConnect.Util;
|
||||
using RestSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using QuantConnect.Brokerages.Bitfinex.Messages;
|
||||
using QuantConnect.Securities.Crypto;
|
||||
using Order = QuantConnect.Orders.Order;
|
||||
|
||||
namespace QuantConnect.Brokerages.Bitfinex
|
||||
@@ -41,6 +43,7 @@ namespace QuantConnect.Brokerages.Bitfinex
|
||||
private readonly SymbolPropertiesDatabaseSymbolMapper _symbolMapper = new SymbolPropertiesDatabaseSymbolMapper(Market.Bitfinex);
|
||||
|
||||
#region IBrokerage
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the websocket connection is connected or in the process of connecting
|
||||
/// </summary>
|
||||
@@ -427,7 +430,7 @@ namespace QuantConnect.Brokerages.Bitfinex
|
||||
} while (startTimeStamp < endTimeStamp);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion IBrokerage
|
||||
|
||||
#region IDataQueueHandler
|
||||
|
||||
@@ -437,6 +440,26 @@ namespace QuantConnect.Brokerages.Bitfinex
|
||||
/// <param name="job">Job we're subscribing for</param>
|
||||
public void SetJob(LiveNodePacket job)
|
||||
{
|
||||
var apiKey = job.BrokerageData["bitfinex-api-key"];
|
||||
var apiSecret = job.BrokerageData["bitfinex-api-secret"];
|
||||
var aggregator = Composer.Instance.GetExportedValueByTypeName<IDataAggregator>(
|
||||
Config.Get("data-aggregator", "QuantConnect.Lean.Engine.DataFeeds.AggregationManager"));
|
||||
|
||||
Initialize(
|
||||
wssUrl: WebSocketUrl,
|
||||
websocket: new WebSocketClientWrapper(),
|
||||
restClient: new RestClient(RestApiUrl),
|
||||
apiKey: apiKey,
|
||||
apiSecret: apiSecret,
|
||||
algorithm: null,
|
||||
aggregator: aggregator,
|
||||
job: job
|
||||
);
|
||||
|
||||
if (!IsConnected)
|
||||
{
|
||||
Connect();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -447,11 +470,9 @@ namespace QuantConnect.Brokerages.Bitfinex
|
||||
/// <returns>The new enumerator for this subscription request</returns>
|
||||
public IEnumerator<BaseData> Subscribe(SubscriptionDataConfig dataConfig, EventHandler newDataAvailableHandler)
|
||||
{
|
||||
var symbol = dataConfig.Symbol;
|
||||
if (symbol.Value.Contains("UNIVERSE") ||
|
||||
!_symbolMapper.IsKnownLeanSymbol(symbol))
|
||||
if (!CanSubscribe(dataConfig.Symbol))
|
||||
{
|
||||
return Enumerable.Empty<BaseData>().GetEnumerator();
|
||||
return null;
|
||||
}
|
||||
|
||||
var enumerator = _aggregator.Add(dataConfig, newDataAvailableHandler);
|
||||
@@ -470,7 +491,7 @@ namespace QuantConnect.Brokerages.Bitfinex
|
||||
_aggregator.Remove(dataConfig);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion IDataQueueHandler
|
||||
|
||||
/// <summary>
|
||||
/// Event invocator for the Message event
|
||||
@@ -492,5 +513,14 @@ namespace QuantConnect.Brokerages.Bitfinex
|
||||
_onSubscribeEvent.Dispose();
|
||||
_onUnsubscribeEvent.Dispose();
|
||||
}
|
||||
|
||||
private bool CanSubscribe(Symbol symbol)
|
||||
{
|
||||
if (symbol.Value.Contains("UNIVERSE") || !_symbolMapper.IsKnownLeanSymbol(symbol))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return symbol.ID.Market == Market.Bitfinex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,25 +14,25 @@
|
||||
*/
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Logging;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using QuantConnect.Packets;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Util;
|
||||
using RestSharp;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using RestSharp;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Logging;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Util;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Packets;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace QuantConnect.Brokerages.GDAX
|
||||
{
|
||||
@@ -44,40 +44,50 @@ namespace QuantConnect.Brokerages.GDAX
|
||||
/// Collection of partial split messages
|
||||
/// </summary>
|
||||
public ConcurrentDictionary<long, GDAXFill> FillSplit { get; set; }
|
||||
private readonly string _passPhrase;
|
||||
private readonly IAlgorithm _algorithm;
|
||||
|
||||
private string _passPhrase;
|
||||
private IAlgorithm _algorithm;
|
||||
private readonly CancellationTokenSource _canceller = new CancellationTokenSource();
|
||||
private readonly ConcurrentDictionary<Symbol, DefaultOrderBook> _orderBooks = new ConcurrentDictionary<Symbol, DefaultOrderBook>();
|
||||
private readonly SymbolPropertiesDatabaseSymbolMapper _symbolMapper = new SymbolPropertiesDatabaseSymbolMapper(Market.GDAX);
|
||||
private readonly bool _isDataQueueHandler;
|
||||
private bool _isDataQueueHandler;
|
||||
private LiveNodePacket _job;
|
||||
|
||||
/// <summary>
|
||||
/// Data Aggregator
|
||||
/// </summary>
|
||||
protected readonly IDataAggregator _aggregator;
|
||||
protected IDataAggregator _aggregator;
|
||||
|
||||
// GDAX has different rate limits for public and private endpoints
|
||||
// https://docs.gdax.com/#rate-limits
|
||||
internal enum GdaxEndpointType { Public, Private }
|
||||
|
||||
private readonly RateGate _publicEndpointRateLimiter = new RateGate(6, TimeSpan.FromSeconds(1));
|
||||
private readonly RateGate _privateEndpointRateLimiter = new RateGate(10, TimeSpan.FromSeconds(1));
|
||||
|
||||
private readonly IPriceProvider _priceProvider;
|
||||
private IPriceProvider _priceProvider;
|
||||
|
||||
private readonly CancellationTokenSource _ctsFillMonitor = new CancellationTokenSource();
|
||||
private readonly Task _fillMonitorTask;
|
||||
private Task _fillMonitorTask;
|
||||
private readonly AutoResetEvent _fillMonitorResetEvent = new AutoResetEvent(false);
|
||||
private readonly int _fillMonitorTimeout = Config.GetInt("gdax-fill-monitor-timeout", 500);
|
||||
private readonly ConcurrentDictionary<string, PendingOrder> _pendingOrders = new ConcurrentDictionary<string, PendingOrder>();
|
||||
|
||||
#endregion
|
||||
#endregion Declarations
|
||||
|
||||
/// <summary>
|
||||
/// The list of websocket channels to subscribe
|
||||
/// </summary>
|
||||
protected virtual string[] ChannelNames { get; } = { "heartbeat" };
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for brokerage
|
||||
/// </summary>
|
||||
/// <param name="name">Name of brokerage</param>
|
||||
public GDAXBrokerage(string name) : base(name)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for brokerage
|
||||
/// </summary>
|
||||
@@ -93,18 +103,20 @@ namespace QuantConnect.Brokerages.GDAX
|
||||
/// <param name="job">The live job packet</param>
|
||||
public GDAXBrokerage(string wssUrl, IWebSocket websocket, IRestClient restClient, string apiKey, string apiSecret, string passPhrase, IAlgorithm algorithm,
|
||||
IPriceProvider priceProvider, IDataAggregator aggregator, LiveNodePacket job)
|
||||
: base(wssUrl, websocket, restClient, apiKey, apiSecret, "GDAX")
|
||||
: base("GDAX")
|
||||
{
|
||||
_job = job;
|
||||
FillSplit = new ConcurrentDictionary<long, GDAXFill>();
|
||||
_passPhrase = passPhrase;
|
||||
_algorithm = algorithm;
|
||||
_priceProvider = priceProvider;
|
||||
_aggregator = aggregator;
|
||||
|
||||
_isDataQueueHandler = this is GDAXDataQueueHandler;
|
||||
|
||||
_fillMonitorTask = Task.Factory.StartNew(FillMonitorAction, _ctsFillMonitor.Token);
|
||||
Initialize(
|
||||
wssUrl: wssUrl,
|
||||
websocket: websocket,
|
||||
restClient: restClient,
|
||||
apiKey: apiKey,
|
||||
apiSecret: apiSecret,
|
||||
passPhrase: passPhrase,
|
||||
algorithm: algorithm,
|
||||
priceProvider: priceProvider,
|
||||
aggregator: aggregator,
|
||||
job: job
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -167,6 +179,49 @@ namespace QuantConnect.Brokerages.GDAX
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the instance of this class
|
||||
/// </summary>
|
||||
/// <param name="wssUrl">The web socket base url</param>
|
||||
/// <param name="websocket">instance of websockets client</param>
|
||||
/// <param name="restClient">instance of rest client</param>
|
||||
/// <param name="apiKey">api key</param>
|
||||
/// <param name="apiSecret">api secret</param>
|
||||
/// <param name="passPhrase">pass phrase</param>
|
||||
/// <param name="algorithm">the algorithm instance is required to retrieve account type</param>
|
||||
/// <param name="priceProvider">The price provider for missing FX conversion rates</param>
|
||||
/// <param name="aggregator">the aggregator for consolidating ticks</param>
|
||||
/// <param name="job">The live job packet</param>
|
||||
protected void Initialize(string wssUrl, IWebSocket websocket, IRestClient restClient, string apiKey, string apiSecret,
|
||||
string passPhrase, IAlgorithm algorithm, IPriceProvider priceProvider, IDataAggregator aggregator, LiveNodePacket job)
|
||||
{
|
||||
if (IsInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
base.Initialize(wssUrl, websocket, restClient, apiKey, apiSecret);
|
||||
_job = job;
|
||||
FillSplit = new ConcurrentDictionary<long, GDAXFill>();
|
||||
_passPhrase = passPhrase;
|
||||
_algorithm = algorithm;
|
||||
_priceProvider = priceProvider;
|
||||
_aggregator = aggregator;
|
||||
|
||||
_isDataQueueHandler = this is GDAXDataQueueHandler;
|
||||
|
||||
_fillMonitorTask = Task.Factory.StartNew(FillMonitorAction, _ctsFillMonitor.Token);
|
||||
|
||||
var subscriptionManager = new EventBasedDataQueueHandlerSubscriptionManager();
|
||||
subscriptionManager.SubscribeImpl += (s, t) =>
|
||||
{
|
||||
Subscribe(s);
|
||||
return true;
|
||||
};
|
||||
subscriptionManager.UnsubscribeImpl += (s, t) => Unsubscribe(s);
|
||||
|
||||
SubscriptionManager = subscriptionManager;
|
||||
}
|
||||
|
||||
private void OnSnapshot(string data)
|
||||
{
|
||||
try
|
||||
@@ -259,7 +314,6 @@ namespace QuantConnect.Brokerages.GDAX
|
||||
orderBook.UpdateAskRow(price, size);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace QuantConnect.Brokerages.GDAX
|
||||
var aggregator = Composer.Instance.GetExportedValueByTypeName<IDataAggregator>(Config.Get("data-aggregator", "QuantConnect.Lean.Engine.DataFeeds.AggregationManager"));
|
||||
|
||||
IBrokerage brokerage;
|
||||
if (job.DataQueueHandler.EndsWith("GDAXDataQueueHandler"))
|
||||
if (job.DataQueueHandler.Contains("GDAXDataQueueHandler"))
|
||||
{
|
||||
var dataQueueHandler = new GDAXDataQueueHandler(job.BrokerageData["gdax-url"], webSocketClient,
|
||||
restClient, job.BrokerageData["gdax-api-key"], job.BrokerageData["gdax-api-secret"],
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Packets;
|
||||
using QuantConnect.Util;
|
||||
using RestSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Brokerages.GDAX
|
||||
{
|
||||
@@ -29,6 +30,13 @@ namespace QuantConnect.Brokerages.GDAX
|
||||
[BrokerageFactory(typeof(GDAXBrokerageFactory))]
|
||||
public class GDAXDataQueueHandler : GDAXBrokerage, IDataQueueHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor for brokerage
|
||||
/// </summary>
|
||||
public GDAXDataQueueHandler() : base("GDAX")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GDAXDataQueueHandler"/> class
|
||||
/// </summary>
|
||||
@@ -36,15 +44,18 @@ namespace QuantConnect.Brokerages.GDAX
|
||||
IPriceProvider priceProvider, IDataAggregator aggregator, LiveNodePacket job)
|
||||
: base(wssUrl, websocket, restClient, apiKey, apiSecret, passPhrase, algorithm, priceProvider, aggregator, job)
|
||||
{
|
||||
var subscriptionManager = new EventBasedDataQueueHandlerSubscriptionManager();
|
||||
subscriptionManager.SubscribeImpl += (s,t) =>
|
||||
{
|
||||
Subscribe(s);
|
||||
return true;
|
||||
};
|
||||
subscriptionManager.UnsubscribeImpl += (s, t) => Unsubscribe(s);
|
||||
|
||||
SubscriptionManager = subscriptionManager;
|
||||
Initialize(
|
||||
wssUrl: wssUrl,
|
||||
websocket: websocket,
|
||||
restClient: restClient,
|
||||
apiKey: apiKey,
|
||||
apiSecret: apiSecret,
|
||||
passPhrase: passPhrase,
|
||||
algorithm: algorithm,
|
||||
priceProvider: priceProvider,
|
||||
aggregator: aggregator,
|
||||
job: job
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -62,7 +73,7 @@ namespace QuantConnect.Brokerages.GDAX
|
||||
{
|
||||
if (!CanSubscribe(dataConfig.Symbol))
|
||||
{
|
||||
return Enumerable.Empty<BaseData>().GetEnumerator();
|
||||
return null;
|
||||
}
|
||||
|
||||
var enumerator = _aggregator.Add(dataConfig, newDataAvailableHandler);
|
||||
@@ -77,6 +88,34 @@ namespace QuantConnect.Brokerages.GDAX
|
||||
/// <param name="job">Job we're subscribing for</param>
|
||||
public void SetJob(LiveNodePacket job)
|
||||
{
|
||||
var wssUrl = job.BrokerageData["gdax-url"];
|
||||
var restApi = job.BrokerageData["gdax-rest-api"];
|
||||
var restClient = new RestClient(restApi);
|
||||
var webSocketClient = new WebSocketClientWrapper();
|
||||
var passPhrase = job.BrokerageData["gdax-passphrase"];
|
||||
var apiKey = job.BrokerageData["gdax-api-key"];
|
||||
var apiSecret = job.BrokerageData["gdax-api-secret"];
|
||||
var priceProvider = new ApiPriceProvider(job.UserId, job.UserToken);
|
||||
var aggregator = Composer.Instance.GetExportedValueByTypeName<IDataAggregator>(
|
||||
Config.Get("data-aggregator", "QuantConnect.Lean.Engine.DataFeeds.AggregationManager"));
|
||||
|
||||
Initialize(
|
||||
wssUrl: wssUrl,
|
||||
websocket: webSocketClient,
|
||||
restClient: restClient,
|
||||
apiKey: apiKey,
|
||||
apiSecret: apiSecret,
|
||||
passPhrase: passPhrase,
|
||||
algorithm: null,
|
||||
priceProvider: priceProvider,
|
||||
aggregator: aggregator,
|
||||
job: job
|
||||
);
|
||||
|
||||
if (!IsConnected)
|
||||
{
|
||||
Connect();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -102,7 +141,7 @@ namespace QuantConnect.Brokerages.GDAX
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return symbol.ID.Market == Market.GDAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,24 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using IBApi;
|
||||
using NodaTime;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.IBAutomater;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Logging;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using QuantConnect.Orders.TimeInForces;
|
||||
using QuantConnect.Packets;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.FutureOption;
|
||||
using QuantConnect.Securities.Index;
|
||||
using QuantConnect.Securities.IndexOption;
|
||||
using QuantConnect.Securities.Option;
|
||||
using QuantConnect.Util;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@@ -21,28 +39,10 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Logging;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Packets;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Util;
|
||||
using Order = QuantConnect.Orders.Order;
|
||||
using IB = QuantConnect.Brokerages.InteractiveBrokers.Client;
|
||||
using IBApi;
|
||||
using NodaTime;
|
||||
using QuantConnect.IBAutomater;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using QuantConnect.Orders.TimeInForces;
|
||||
using QuantConnect.Securities.FutureOption;
|
||||
using QuantConnect.Securities.Index;
|
||||
using QuantConnect.Securities.IndexOption;
|
||||
using QuantConnect.Securities.Option;
|
||||
using Bar = QuantConnect.Data.Market.Bar;
|
||||
using HistoryRequest = QuantConnect.Data.HistoryRequest;
|
||||
using IB = QuantConnect.Brokerages.InteractiveBrokers.Client;
|
||||
using Order = QuantConnect.Orders.Order;
|
||||
|
||||
namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
{
|
||||
@@ -57,28 +57,30 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
/// </summary>
|
||||
public static string DefaultVersion { get; } = "985";
|
||||
|
||||
private readonly IBAutomater.IBAutomater _ibAutomater;
|
||||
private IBAutomater.IBAutomater _ibAutomater;
|
||||
|
||||
// Existing orders created in TWS can *only* be cancelled/modified when connected with ClientId = 0
|
||||
private const int ClientId = 0;
|
||||
|
||||
private const string _futuresCmeCrypto = "CMECRYPTO";
|
||||
|
||||
// next valid order id (or request id, or ticker id) for this client
|
||||
private int _nextValidId;
|
||||
|
||||
private readonly object _nextValidIdLocker = new object();
|
||||
|
||||
private readonly int _port;
|
||||
private readonly string _account;
|
||||
private readonly string _host;
|
||||
private readonly IAlgorithm _algorithm;
|
||||
private readonly bool _loadExistingHoldings;
|
||||
private readonly IOrderProvider _orderProvider;
|
||||
private readonly ISecurityProvider _securityProvider;
|
||||
private readonly IDataAggregator _aggregator;
|
||||
private readonly IB.InteractiveBrokersClient _client;
|
||||
private readonly int _ibVersion;
|
||||
private readonly string _agentDescription;
|
||||
private readonly EventBasedDataQueueHandlerSubscriptionManager _subscriptionManager;
|
||||
private int _port;
|
||||
private string _account;
|
||||
private string _host;
|
||||
private IAlgorithm _algorithm;
|
||||
private bool _loadExistingHoldings;
|
||||
private IOrderProvider _orderProvider;
|
||||
private ISecurityProvider _securityProvider;
|
||||
private IDataAggregator _aggregator;
|
||||
private IB.InteractiveBrokersClient _client;
|
||||
private int _ibVersion;
|
||||
private string _agentDescription;
|
||||
private EventBasedDataQueueHandlerSubscriptionManager _subscriptionManager;
|
||||
|
||||
private Thread _messageProcessingThread;
|
||||
|
||||
@@ -92,8 +94,10 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
|
||||
// tracks requested order updates, so we can flag Submitted order events as updates
|
||||
private readonly ConcurrentDictionary<int, int> _orderUpdates = new ConcurrentDictionary<int, int>();
|
||||
|
||||
// tracks executions before commission reports, map: execId -> execution
|
||||
private readonly ConcurrentDictionary<string, IB.ExecutionDetailsEventArgs> _orderExecutions = new ConcurrentDictionary<string, IB.ExecutionDetailsEventArgs>();
|
||||
|
||||
// tracks commission reports before executions, map: execId -> commission report
|
||||
private readonly ConcurrentDictionary<string, CommissionReport> _commissionReports = new ConcurrentDictionary<string, CommissionReport>();
|
||||
|
||||
@@ -107,7 +111,7 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
|
||||
private readonly ConcurrentDictionary<string, ContractDetails> _contractDetails = new ConcurrentDictionary<string, ContractDetails>();
|
||||
|
||||
private readonly InteractiveBrokersSymbolMapper _symbolMapper;
|
||||
private InteractiveBrokersSymbolMapper _symbolMapper;
|
||||
|
||||
// Prioritized list of exchanges used to find right futures contract
|
||||
private readonly Dictionary<string, string> _futuresExchanges = new Dictionary<string, string>
|
||||
@@ -134,11 +138,13 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
// when unsubscribing symbols immediately after subscribing IB returns an error (Can't find EId with tickerId:nnn),
|
||||
// so we track subscription times to ensure symbols are not unsubscribed before a minimum time span has elapsed
|
||||
private readonly Dictionary<int, DateTime> _subscriptionTimes = new Dictionary<int, DateTime>();
|
||||
|
||||
private readonly TimeSpan _minimumTimespanBeforeUnsubscribe = TimeSpan.FromMilliseconds(500);
|
||||
|
||||
private readonly bool _enableDelayedStreamingData = Config.GetBool("ib-enable-delayed-streaming-data");
|
||||
|
||||
private volatile bool _isDisposeCalled;
|
||||
private bool _isInitialized;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if we're currently connected to the broker
|
||||
@@ -160,6 +166,13 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
return account.Contains("F");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new InteractiveBrokersBrokerage using values from configuration
|
||||
/// </summary>
|
||||
public InteractiveBrokersBrokerage() : base("Interactive Brokers Brokerage")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new InteractiveBrokersBrokerage using values from configuration:
|
||||
/// ib-account (required)
|
||||
@@ -242,78 +255,22 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
bool loadExistingHoldings = true)
|
||||
: base("Interactive Brokers Brokerage")
|
||||
{
|
||||
_loadExistingHoldings = loadExistingHoldings;
|
||||
_algorithm = algorithm;
|
||||
_orderProvider = orderProvider;
|
||||
_securityProvider = securityProvider;
|
||||
_aggregator = aggregator;
|
||||
_account = account;
|
||||
_host = host;
|
||||
_port = port;
|
||||
_ibVersion = Convert.ToInt32(ibVersion, CultureInfo.InvariantCulture);
|
||||
_agentDescription = agentDescription;
|
||||
|
||||
_symbolMapper = new InteractiveBrokersSymbolMapper(mapFileProvider);
|
||||
|
||||
_subscriptionManager = new EventBasedDataQueueHandlerSubscriptionManager();
|
||||
_subscriptionManager.SubscribeImpl += (s, t) => Subscribe(s);
|
||||
_subscriptionManager.UnsubscribeImpl += (s, t) => Unsubscribe(s);
|
||||
|
||||
Log.Trace("InteractiveBrokersBrokerage.InteractiveBrokersBrokerage(): Starting IB Automater...");
|
||||
|
||||
// start IB Gateway
|
||||
var exportIbGatewayLogs = Config.GetBool("ib-export-ibgateway-logs");
|
||||
_ibAutomater = new IBAutomater.IBAutomater(ibDirectory, ibVersion, userName, password, tradingMode, port, exportIbGatewayLogs);
|
||||
_ibAutomater.OutputDataReceived += OnIbAutomaterOutputDataReceived;
|
||||
_ibAutomater.ErrorDataReceived += OnIbAutomaterErrorDataReceived;
|
||||
_ibAutomater.Exited += OnIbAutomaterExited;
|
||||
_ibAutomater.Restarted += OnIbAutomaterRestarted;
|
||||
|
||||
CheckIbAutomaterError(_ibAutomater.Start(false));
|
||||
|
||||
Log.Trace($"InteractiveBrokersBrokerage.InteractiveBrokersBrokerage(): Host: {host}, Port: {port}, Account: {account}, AgentDescription: {agentDescription}");
|
||||
|
||||
_client = new IB.InteractiveBrokersClient(_signal);
|
||||
|
||||
// set up event handlers
|
||||
_client.UpdatePortfolio += HandlePortfolioUpdates;
|
||||
_client.OrderStatus += HandleOrderStatusUpdates;
|
||||
_client.OpenOrder += HandleOpenOrder;
|
||||
_client.OpenOrderEnd += HandleOpenOrderEnd;
|
||||
_client.UpdateAccountValue += HandleUpdateAccountValue;
|
||||
_client.AccountSummary += HandleAccountSummary;
|
||||
_client.ManagedAccounts += HandleManagedAccounts;
|
||||
_client.FamilyCodes += HandleFamilyCodes;
|
||||
_client.ExecutionDetails += HandleExecutionDetails;
|
||||
_client.CommissionReport += HandleCommissionReport;
|
||||
_client.Error += HandleError;
|
||||
_client.TickPrice += HandleTickPrice;
|
||||
_client.TickSize += HandleTickSize;
|
||||
_client.CurrentTimeUtc += HandleBrokerTime;
|
||||
|
||||
// we need to wait until we receive the next valid id from the server
|
||||
_client.NextValidId += (sender, e) =>
|
||||
{
|
||||
lock (_nextValidIdLocker)
|
||||
{
|
||||
Log.Trace($"InteractiveBrokersBrokerage.HandleNextValidID(): updating nextValidId from {_nextValidId} to {e.OrderId}");
|
||||
|
||||
_nextValidId = e.OrderId;
|
||||
_waitForNextValidId.Set();
|
||||
}
|
||||
};
|
||||
|
||||
_client.ConnectAck += (sender, e) =>
|
||||
{
|
||||
Log.Trace($"InteractiveBrokersBrokerage.HandleConnectAck(): API client connected [Server Version: {_client.ClientSocket.ServerVersion}].");
|
||||
_connectEvent.Set();
|
||||
};
|
||||
|
||||
_client.ConnectionClosed += (sender, e) =>
|
||||
{
|
||||
Log.Trace($"InteractiveBrokersBrokerage.HandleConnectionClosed(): API client disconnected [Server Version: {_client.ClientSocket.ServerVersion}].");
|
||||
_connectEvent.Set();
|
||||
};
|
||||
Initialize(
|
||||
algorithm,
|
||||
orderProvider,
|
||||
securityProvider,
|
||||
aggregator,
|
||||
mapFileProvider,
|
||||
account,
|
||||
host,
|
||||
port,
|
||||
ibDirectory,
|
||||
ibVersion,
|
||||
userName,
|
||||
password,
|
||||
tradingMode,
|
||||
agentDescription = IB.AgentDescription.Individual,
|
||||
loadExistingHoldings = true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -831,6 +788,9 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
{
|
||||
Log.Trace("InteractiveBrokersBrokerage.Connect(): Restoring data subscriptions...");
|
||||
RestoreDataSubscriptions();
|
||||
|
||||
// we need to tell the DefaultBrokerageMessageHandler we are connected else he will kill us
|
||||
OnMessage(BrokerageMessageEvent.Reconnected("Connect() finished successfully"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -955,6 +915,120 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
_messagingRateLimiter.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the instance of this class
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="orderProvider">An instance of IOrderProvider used to fetch Order objects by brokerage ID</param>
|
||||
/// <param name="securityProvider">The security provider used to give access to algorithm securities</param>
|
||||
/// <param name="aggregator">consolidate ticks</param>
|
||||
/// <param name="mapFileProvider">representing all the map files</param>
|
||||
/// <param name="account">The Interactive Brokers account name</param>
|
||||
/// <param name="host">host name or IP address of the machine where TWS is running. Leave blank to connect to the local host.</param>
|
||||
/// <param name="port">must match the port specified in TWS on the Configure>API>Socket Port field.</param>
|
||||
/// <param name="ibDirectory">The IB Gateway root directory</param>
|
||||
/// <param name="ibVersion">The IB Gateway version</param>
|
||||
/// <param name="userName">The login user name</param>
|
||||
/// <param name="password">The login password</param>
|
||||
/// <param name="tradingMode">The trading mode: 'live' or 'paper'</param>
|
||||
/// <param name="agentDescription">Used for Rule 80A describes the type of trader.</param>
|
||||
/// <param name="loadExistingHoldings">False will ignore existing security holdings from being loaded.</param>
|
||||
private void Initialize(
|
||||
IAlgorithm algorithm,
|
||||
IOrderProvider orderProvider,
|
||||
ISecurityProvider securityProvider,
|
||||
IDataAggregator aggregator,
|
||||
IMapFileProvider mapFileProvider,
|
||||
string account,
|
||||
string host,
|
||||
int port,
|
||||
string ibDirectory,
|
||||
string ibVersion,
|
||||
string userName,
|
||||
string password,
|
||||
string tradingMode,
|
||||
string agentDescription = IB.AgentDescription.Individual,
|
||||
bool loadExistingHoldings = true)
|
||||
{
|
||||
if (_isInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_isInitialized = true;
|
||||
_loadExistingHoldings = loadExistingHoldings;
|
||||
_algorithm = algorithm;
|
||||
_orderProvider = orderProvider;
|
||||
_securityProvider = securityProvider;
|
||||
_aggregator = aggregator;
|
||||
_account = account;
|
||||
_host = host;
|
||||
_port = port;
|
||||
_ibVersion = Convert.ToInt32(ibVersion, CultureInfo.InvariantCulture);
|
||||
_agentDescription = agentDescription;
|
||||
|
||||
_symbolMapper = new InteractiveBrokersSymbolMapper(mapFileProvider);
|
||||
|
||||
_subscriptionManager = new EventBasedDataQueueHandlerSubscriptionManager();
|
||||
_subscriptionManager.SubscribeImpl += (s, t) => Subscribe(s);
|
||||
_subscriptionManager.UnsubscribeImpl += (s, t) => Unsubscribe(s);
|
||||
|
||||
Log.Trace("InteractiveBrokersBrokerage.InteractiveBrokersBrokerage(): Starting IB Automater...");
|
||||
|
||||
// start IB Gateway
|
||||
var exportIbGatewayLogs = Config.GetBool("ib-export-ibgateway-logs");
|
||||
_ibAutomater = new IBAutomater.IBAutomater(ibDirectory, ibVersion, userName, password, tradingMode, port, exportIbGatewayLogs);
|
||||
_ibAutomater.OutputDataReceived += OnIbAutomaterOutputDataReceived;
|
||||
_ibAutomater.ErrorDataReceived += OnIbAutomaterErrorDataReceived;
|
||||
_ibAutomater.Exited += OnIbAutomaterExited;
|
||||
_ibAutomater.Restarted += OnIbAutomaterRestarted;
|
||||
|
||||
CheckIbAutomaterError(_ibAutomater.Start(false));
|
||||
|
||||
Log.Trace($"InteractiveBrokersBrokerage.InteractiveBrokersBrokerage(): Host: {host}, Port: {port}, Account: {account}, AgentDescription: {agentDescription}");
|
||||
|
||||
_client = new IB.InteractiveBrokersClient(_signal);
|
||||
|
||||
// set up event handlers
|
||||
_client.UpdatePortfolio += HandlePortfolioUpdates;
|
||||
_client.OrderStatus += HandleOrderStatusUpdates;
|
||||
_client.OpenOrder += HandleOpenOrder;
|
||||
_client.OpenOrderEnd += HandleOpenOrderEnd;
|
||||
_client.UpdateAccountValue += HandleUpdateAccountValue;
|
||||
_client.AccountSummary += HandleAccountSummary;
|
||||
_client.ManagedAccounts += HandleManagedAccounts;
|
||||
_client.FamilyCodes += HandleFamilyCodes;
|
||||
_client.ExecutionDetails += HandleExecutionDetails;
|
||||
_client.CommissionReport += HandleCommissionReport;
|
||||
_client.Error += HandleError;
|
||||
_client.TickPrice += HandleTickPrice;
|
||||
_client.TickSize += HandleTickSize;
|
||||
_client.CurrentTimeUtc += HandleBrokerTime;
|
||||
|
||||
// we need to wait until we receive the next valid id from the server
|
||||
_client.NextValidId += (sender, e) =>
|
||||
{
|
||||
lock (_nextValidIdLocker)
|
||||
{
|
||||
Log.Trace($"InteractiveBrokersBrokerage.HandleNextValidID(): updating nextValidId from {_nextValidId} to {e.OrderId}");
|
||||
|
||||
_nextValidId = e.OrderId;
|
||||
_waitForNextValidId.Set();
|
||||
}
|
||||
};
|
||||
|
||||
_client.ConnectAck += (sender, e) =>
|
||||
{
|
||||
Log.Trace($"InteractiveBrokersBrokerage.HandleConnectAck(): API client connected [Server Version: {_client.ClientSocket.ServerVersion}].");
|
||||
_connectEvent.Set();
|
||||
};
|
||||
|
||||
_client.ConnectionClosed += (sender, e) =>
|
||||
{
|
||||
Log.Trace($"InteractiveBrokersBrokerage.HandleConnectionClosed(): API client disconnected [Server Version: {_client.ClientSocket.ServerVersion}].");
|
||||
_connectEvent.Set();
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Places the order with InteractiveBrokers
|
||||
/// </summary>
|
||||
@@ -1850,7 +1924,6 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
{
|
||||
// order for an account profile
|
||||
ibOrder.FaProfile = orderProperties.FaProfile;
|
||||
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(orderProperties.FaGroup))
|
||||
{
|
||||
@@ -1965,12 +2038,18 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
var securityType = ConvertSecurityType(symbol.SecurityType);
|
||||
var ibSymbol = _symbolMapper.GetBrokerageSymbol(symbol);
|
||||
|
||||
var symbolProperties = _symbolPropertiesDatabase.GetSymbolProperties(
|
||||
symbol.ID.Market,
|
||||
symbol,
|
||||
symbol.SecurityType,
|
||||
Currencies.USD);
|
||||
|
||||
var contract = new Contract
|
||||
{
|
||||
Symbol = ibSymbol,
|
||||
Exchange = exchange ?? GetSymbolExchange(symbol),
|
||||
SecType = securityType,
|
||||
Currency = Currencies.USD
|
||||
Currency = symbolProperties.QuoteCurrency
|
||||
};
|
||||
if (symbol.ID.SecurityType == SecurityType.Forex)
|
||||
{
|
||||
@@ -2036,12 +2115,6 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
contract.LastTradeDateOrContractMonth = symbol.ID.Date.ToStringInvariant(DateFormat.EightCharacter);
|
||||
contract.Exchange = GetSymbolExchange(symbol);
|
||||
|
||||
var symbolProperties = _symbolPropertiesDatabase.GetSymbolProperties(
|
||||
symbol.ID.Market,
|
||||
symbol,
|
||||
symbol.SecurityType,
|
||||
Currencies.USD);
|
||||
|
||||
contract.Multiplier = Convert.ToInt32(symbolProperties.ContractMultiplier).ToStringInvariant();
|
||||
|
||||
contract.IncludeExpired = includeExpired;
|
||||
@@ -2072,7 +2145,7 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case OrderDirection.Buy: return IB.ActionSide.Buy;
|
||||
case OrderDirection.Buy: return IB.ActionSide.Buy;
|
||||
case OrderDirection.Sell: return IB.ActionSide.Sell;
|
||||
case OrderDirection.Hold: return IB.ActionSide.Undefined;
|
||||
default:
|
||||
@@ -2087,13 +2160,13 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case OrderType.Market: return IB.OrderType.Market;
|
||||
case OrderType.Limit: return IB.OrderType.Limit;
|
||||
case OrderType.StopMarket: return IB.OrderType.Stop;
|
||||
case OrderType.StopLimit: return IB.OrderType.StopLimit;
|
||||
case OrderType.LimitIfTouched: return IB.OrderType.LimitIfTouched;
|
||||
case OrderType.MarketOnOpen: return IB.OrderType.Market;
|
||||
case OrderType.MarketOnClose: return IB.OrderType.MarketOnClose;
|
||||
case OrderType.Market: return IB.OrderType.Market;
|
||||
case OrderType.Limit: return IB.OrderType.Limit;
|
||||
case OrderType.StopMarket: return IB.OrderType.Stop;
|
||||
case OrderType.StopLimit: return IB.OrderType.StopLimit;
|
||||
case OrderType.LimitIfTouched: return IB.OrderType.LimitIfTouched;
|
||||
case OrderType.MarketOnOpen: return IB.OrderType.Market;
|
||||
case OrderType.MarketOnClose: return IB.OrderType.MarketOnClose;
|
||||
default:
|
||||
throw new InvalidEnumArgumentException(nameof(type), (int)type, typeof(OrderType));
|
||||
}
|
||||
@@ -2106,11 +2179,11 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
{
|
||||
switch (order.OrderType)
|
||||
{
|
||||
case IB.OrderType.Limit: return OrderType.Limit;
|
||||
case IB.OrderType.Stop: return OrderType.StopMarket;
|
||||
case IB.OrderType.StopLimit: return OrderType.StopLimit;
|
||||
case IB.OrderType.LimitIfTouched: return OrderType.LimitIfTouched;
|
||||
case IB.OrderType.MarketOnClose: return OrderType.MarketOnClose;
|
||||
case IB.OrderType.Limit: return OrderType.Limit;
|
||||
case IB.OrderType.Stop: return OrderType.StopMarket;
|
||||
case IB.OrderType.StopLimit: return OrderType.StopLimit;
|
||||
case IB.OrderType.LimitIfTouched: return OrderType.LimitIfTouched;
|
||||
case IB.OrderType.MarketOnClose: return OrderType.MarketOnClose;
|
||||
|
||||
case IB.OrderType.Market:
|
||||
if (order.Tif == IB.TimeInForce.MarketOnOpen)
|
||||
@@ -2267,7 +2340,7 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
|
||||
case SecurityType.Option:
|
||||
case SecurityType.IndexOption:
|
||||
return IB.SecurityType.Option;
|
||||
return IB.SecurityType.Option;
|
||||
|
||||
case SecurityType.Index:
|
||||
return IB.SecurityType.Index;
|
||||
@@ -2520,6 +2593,44 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
/// <param name="job">Job we're subscribing for</param>
|
||||
public void SetJob(LiveNodePacket job)
|
||||
{
|
||||
// read values from the brokerage datas
|
||||
var port = Config.GetInt("ib-port", 4001);
|
||||
var host = Config.Get("ib-host", "127.0.0.1");
|
||||
var twsDirectory = Config.Get("ib-tws-dir", "C:\\Jts");
|
||||
var ibVersion = Config.Get("ib-version", DefaultVersion);
|
||||
|
||||
var account = job.BrokerageData["ib-account"];
|
||||
var userId = job.BrokerageData["ib-user-name"];
|
||||
var password = job.BrokerageData["ib-password"];
|
||||
var tradingMode = job.BrokerageData["ib-trading-mode"];
|
||||
var agentDescription = job.BrokerageData["ib-agent-description"];
|
||||
|
||||
var loadExistingHoldings = true;
|
||||
if (job.BrokerageData.ContainsKey("load-existing-holdings"))
|
||||
{
|
||||
loadExistingHoldings = Convert.ToBoolean(job.BrokerageData["load-existing-holdings"]);
|
||||
}
|
||||
|
||||
Initialize(null,
|
||||
null,
|
||||
null,
|
||||
Composer.Instance.GetExportedValueByTypeName<IDataAggregator>(Config.Get("data-aggregator", "QuantConnect.Lean.Engine.DataFeeds.AggregationManager")),
|
||||
Composer.Instance.GetExportedValueByTypeName<IMapFileProvider>(Config.Get("map-file-provider", "QuantConnect.Data.Auxiliary.LocalDiskMapFileProvider")),
|
||||
account,
|
||||
host,
|
||||
port,
|
||||
twsDirectory,
|
||||
ibVersion,
|
||||
userId,
|
||||
password,
|
||||
tradingMode,
|
||||
agentDescription,
|
||||
loadExistingHoldings);
|
||||
|
||||
if (!IsConnected)
|
||||
{
|
||||
Connect();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -2532,7 +2643,7 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
{
|
||||
if (!CanSubscribe(dataConfig.Symbol))
|
||||
{
|
||||
return Enumerable.Empty<BaseData>().GetEnumerator();
|
||||
return null;
|
||||
}
|
||||
|
||||
var enumerator = _aggregator.Add(dataConfig, newDataAvailableHandler);
|
||||
@@ -2811,6 +2922,7 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
case SecurityType.Equity:
|
||||
// Effective in TWS version 985 and later, for US stocks the bid, ask, and last size quotes are shown in shares (not in lots).
|
||||
return _ibVersion < 985 ? size * 100 : size;
|
||||
|
||||
default:
|
||||
return size;
|
||||
}
|
||||
@@ -3009,7 +3121,7 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
SecType = ConvertSecurityType(symbol.SecurityType),
|
||||
IncludeExpired = includeExpired,
|
||||
Multiplier = Convert.ToInt32(symbolProperties.ContractMultiplier).ToStringInvariant()
|
||||
};
|
||||
};
|
||||
|
||||
Log.Trace($"InteractiveBrokersBrokerage.LookupSymbols(): Requesting symbol list for {contract.Symbol} ...");
|
||||
|
||||
@@ -3538,5 +3650,4 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
1100, 1101, 1102, 2103, 2104, 2105, 2106, 2107, 2108, 2119, 2157, 2158, 10197
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
@@ -13,11 +13,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using NodaTime;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
@@ -25,6 +22,11 @@ using QuantConnect.Logging;
|
||||
using QuantConnect.Packets;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Forex;
|
||||
using QuantConnect.Util;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using HistoryRequest = QuantConnect.Data.HistoryRequest;
|
||||
using Order = QuantConnect.Orders.Order;
|
||||
|
||||
@@ -37,13 +39,21 @@ namespace QuantConnect.Brokerages.Oanda
|
||||
public class OandaBrokerage : Brokerage, IDataQueueHandler
|
||||
{
|
||||
private readonly OandaSymbolMapper _symbolMapper = new OandaSymbolMapper();
|
||||
private readonly OandaRestApiBase _api;
|
||||
private OandaRestApiBase _api;
|
||||
private bool _isInitialized;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of bars per historical data request
|
||||
/// </summary>
|
||||
public const int MaxBarsPerRequest = 5000;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OandaBrokerage"/> class.
|
||||
/// </summary>
|
||||
public OandaBrokerage() : base("Oanda Brokerage")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OandaBrokerage"/> class.
|
||||
/// </summary>
|
||||
@@ -57,15 +67,7 @@ namespace QuantConnect.Brokerages.Oanda
|
||||
public OandaBrokerage(IOrderProvider orderProvider, ISecurityProvider securityProvider, IDataAggregator aggregator, Environment environment, string accessToken, string accountId, string agent = OandaRestApiBase.OandaAgentDefaultValue)
|
||||
: base("Oanda Brokerage")
|
||||
{
|
||||
if (environment != Environment.Trade && environment != Environment.Practice)
|
||||
throw new NotSupportedException("Oanda Environment not supported: " + environment);
|
||||
|
||||
_api = new OandaRestApiV20(_symbolMapper, orderProvider, securityProvider, aggregator, environment, accessToken, accountId, agent);
|
||||
|
||||
// forward events received from API
|
||||
_api.OrderStatusChanged += (sender, orderEvent) => OnOrderEvent(orderEvent);
|
||||
_api.AccountChanged += (sender, accountEvent) => OnAccountChanged(accountEvent);
|
||||
_api.Message += (sender, messageEvent) => OnMessage(messageEvent);
|
||||
Initialize(orderProvider, securityProvider, aggregator, environment, accessToken, accountId, agent = OandaRestApiBase.OandaAgentDefaultValue);
|
||||
}
|
||||
|
||||
#region IBrokerage implementation
|
||||
@@ -241,7 +243,7 @@ namespace QuantConnect.Brokerages.Oanda
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion IBrokerage implementation
|
||||
|
||||
#region IDataQueueHandler implementation
|
||||
|
||||
@@ -251,6 +253,25 @@ namespace QuantConnect.Brokerages.Oanda
|
||||
/// <param name="job">Job we're subscribing for</param>
|
||||
public void SetJob(LiveNodePacket job)
|
||||
{
|
||||
Enum.TryParse(job.BrokerageData["oanda-environment"], out Environment environment);
|
||||
var accessToken = job.BrokerageData["oanda-access-token"];
|
||||
var accountId = job.BrokerageData["oanda-account-id"];
|
||||
var agent = job.BrokerageData["oanda-agent"];
|
||||
|
||||
Initialize(
|
||||
null,
|
||||
null,
|
||||
Composer.Instance.GetExportedValueByTypeName<IDataAggregator>(Config.Get("data-aggregator", "QuantConnect.Lean.Engine.DataFeeds.AggregationManager")),
|
||||
environment,
|
||||
accessToken,
|
||||
accountId,
|
||||
agent);
|
||||
|
||||
if (!IsConnected)
|
||||
{
|
||||
Connect();
|
||||
}
|
||||
|
||||
_api.SetJob(job);
|
||||
}
|
||||
|
||||
@@ -274,7 +295,7 @@ namespace QuantConnect.Brokerages.Oanda
|
||||
_api.Unsubscribe(dataConfig);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion IDataQueueHandler implementation
|
||||
|
||||
/// <summary>
|
||||
/// Returns a DateTime from an RFC3339 string (with microsecond resolution)
|
||||
@@ -322,5 +343,34 @@ namespace QuantConnect.Brokerages.Oanda
|
||||
{
|
||||
return _api.DownloadQuoteBars(symbol, startTimeUtc, endTimeUtc, resolution, requestedTimeZone);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the class.
|
||||
/// </summary>
|
||||
/// <param name="orderProvider">The order provider.</param>
|
||||
/// <param name="securityProvider">The holdings provider.</param>
|
||||
/// <param name="aggregator">consolidate ticks</param>
|
||||
/// <param name="environment">The Oanda environment (Trade or Practice)</param>
|
||||
/// <param name="accessToken">The Oanda access token (can be the user's personal access token or the access token obtained with OAuth by QC on behalf of the user)</param>
|
||||
/// <param name="accountId">The account identifier.</param>
|
||||
/// <param name="agent">The Oanda agent string</param>
|
||||
private void Initialize(IOrderProvider orderProvider, ISecurityProvider securityProvider, IDataAggregator aggregator,
|
||||
Environment environment, string accessToken, string accountId, string agent = OandaRestApiBase.OandaAgentDefaultValue)
|
||||
{
|
||||
if (_isInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_isInitialized = true;
|
||||
if (environment != Environment.Trade && environment != Environment.Practice)
|
||||
throw new NotSupportedException("Oanda Environment not supported: " + environment);
|
||||
|
||||
_api = new OandaRestApiV20(_symbolMapper, orderProvider, securityProvider, aggregator, environment, accessToken, accountId, agent);
|
||||
|
||||
// forward events received from API
|
||||
_api.OrderStatusChanged += (sender, orderEvent) => OnOrderEvent(orderEvent);
|
||||
_api.AccountChanged += (sender, accountEvent) => OnAccountChanged(accountEvent);
|
||||
_api.Message += (sender, messageEvent) => OnMessage(messageEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
@@ -367,7 +367,7 @@ namespace QuantConnect.Brokerages.Oanda
|
||||
{
|
||||
if (!CanSubscribe(dataConfig.Symbol))
|
||||
{
|
||||
return Enumerable.Empty<BaseData>().GetEnumerator();
|
||||
return null;
|
||||
}
|
||||
|
||||
var enumerator = Aggregator.Add(dataConfig, newDataAvailableHandler);
|
||||
@@ -404,7 +404,7 @@ namespace QuantConnect.Brokerages.Oanda
|
||||
return false;
|
||||
|
||||
// ignore universe symbols
|
||||
return !symbol.Value.Contains("-UNIVERSE-");
|
||||
return !symbol.Value.Contains("-UNIVERSE-") && symbol.ID.Market == Market.Oanda;
|
||||
}
|
||||
|
||||
private bool Refresh()
|
||||
|
||||
@@ -14,17 +14,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NodaTime;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Packets;
|
||||
using QuantConnect.Util;
|
||||
using RestSharp;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NodaTime;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Packets;
|
||||
using RestSharp;
|
||||
|
||||
namespace QuantConnect.Brokerages.Tradier
|
||||
{
|
||||
@@ -47,6 +49,25 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
/// <param name="job">Job we're subscribing for</param>
|
||||
public void SetJob(LiveNodePacket job)
|
||||
{
|
||||
var useSandbox = bool.Parse(job.BrokerageData["tradier-use-sandbox"]);
|
||||
var accountId = job.BrokerageData["tradier-account-id"];
|
||||
var accessToken = job.BrokerageData["tradier-access-token"];
|
||||
var aggregator = Composer.Instance.GetExportedValueByTypeName<IDataAggregator>(Config.Get("data-aggregator", "QuantConnect.Lean.Engine.DataFeeds.AggregationManager"));
|
||||
|
||||
Initialize(
|
||||
wssUrl: WebSocketUrl,
|
||||
accountId: accountId,
|
||||
accessToken: accessToken,
|
||||
useSandbox: useSandbox,
|
||||
algorithm: null,
|
||||
orderProvider: null,
|
||||
securityProvider: null,
|
||||
aggregator: aggregator);
|
||||
|
||||
if (!IsConnected)
|
||||
{
|
||||
Connect();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -66,7 +87,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
|
||||
if (!CanSubscribe(dataConfig.Symbol))
|
||||
{
|
||||
return Enumerable.Empty<BaseData>().GetEnumerator();
|
||||
return null;
|
||||
}
|
||||
|
||||
var enumerator = _aggregator.Add(dataConfig, newDataAvailableHandler);
|
||||
@@ -164,6 +185,9 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
WebSocket.Send(json);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles websocket received messages
|
||||
/// </summary>
|
||||
protected override void OnMessage(object sender, WebSocketMessage webSocketMessage)
|
||||
{
|
||||
var e = (WebSocketClientWrapper.TextMessage)webSocketMessage.Data;
|
||||
@@ -219,7 +243,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
switch (tsd.Type)
|
||||
{
|
||||
case "trade":
|
||||
return new Tick(time, symbol, "", tsd.TradeExchange, (int) tsd.TradeSize, tsd.TradePrice);
|
||||
return new Tick(time, symbol, "", tsd.TradeExchange, (int)tsd.TradeSize, tsd.TradePrice);
|
||||
|
||||
case "quote":
|
||||
return new Tick(time, symbol, "", "", tsd.BidSize, tsd.BidPrice, tsd.AskSize, tsd.AskPrice);
|
||||
@@ -242,6 +266,6 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
return _streamSession;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion IDataQueueHandler implementation
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,14 +14,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
@@ -33,6 +25,14 @@ using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Equity;
|
||||
using QuantConnect.Util;
|
||||
using RestSharp;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace QuantConnect.Brokerages.Tradier
|
||||
{
|
||||
@@ -47,8 +47,8 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
[BrokerageFactory(typeof(TradierBrokerageFactory))]
|
||||
public partial class TradierBrokerage : BaseWebsocketsBrokerage, IDataQueueHandler, IDataQueueUniverseProvider, IHistoryProvider
|
||||
{
|
||||
private readonly bool _useSandbox;
|
||||
private readonly string _accountId;
|
||||
private bool _useSandbox;
|
||||
private string _accountId;
|
||||
|
||||
// we're reusing the equity exchange here to grab typical exchange hours
|
||||
private static readonly EquityExchange Exchange =
|
||||
@@ -61,36 +61,51 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
private readonly object _lockAccessCredentials = new object();
|
||||
|
||||
// polling timer for checking for fill events
|
||||
private readonly Timer _orderFillTimer;
|
||||
private Timer _orderFillTimer;
|
||||
|
||||
//Tradier Spec:
|
||||
private readonly Dictionary<TradierApiRequestType, RateGate> _rateLimitNextRequest;
|
||||
private Dictionary<TradierApiRequestType, RateGate> _rateLimitNextRequest;
|
||||
|
||||
private readonly IAlgorithm _algorithm;
|
||||
private readonly IOrderProvider _orderProvider;
|
||||
private readonly ISecurityProvider _securityProvider;
|
||||
private readonly IDataAggregator _aggregator;
|
||||
private IAlgorithm _algorithm;
|
||||
private IOrderProvider _orderProvider;
|
||||
private ISecurityProvider _securityProvider;
|
||||
private IDataAggregator _aggregator;
|
||||
|
||||
private readonly object _fillLock = new object();
|
||||
private readonly DateTime _initializationDateTime = DateTime.Now;
|
||||
private readonly ConcurrentDictionary<long, TradierCachedOpenOrder> _cachedOpenOrdersByTradierOrderID;
|
||||
private ConcurrentDictionary<long, TradierCachedOpenOrder> _cachedOpenOrdersByTradierOrderID;
|
||||
|
||||
// this is used to block reentrance when doing look ups for orders with IDs we don't have cached
|
||||
private readonly HashSet<long> _reentranceGuardByTradierOrderID = new HashSet<long>();
|
||||
|
||||
private readonly FixedSizeHashQueue<long> _filledTradierOrderIDs = new FixedSizeHashQueue<long>(10000);
|
||||
|
||||
// this is used to handle the zero crossing case, when the first order is filled we'll submit the next order
|
||||
private readonly ConcurrentDictionary<long, ContingentOrderQueue> _contingentOrdersByQCOrderID = new ConcurrentDictionary<long, ContingentOrderQueue>();
|
||||
|
||||
private readonly ConcurrentDictionary<long, Order> _zeroCrossingOrdersByTradierClosingOrderId = new ConcurrentDictionary<long, Order>();
|
||||
|
||||
// this is used to block reentrance when handling contingent orders
|
||||
private readonly HashSet<long> _contingentReentranceGuardByQCOrderID = new HashSet<long>();
|
||||
|
||||
private readonly HashSet<long> _unknownTradierOrderIDs = new HashSet<long>();
|
||||
private readonly FixedSizeHashQueue<long> _verifiedUnknownTradierOrderIDs = new FixedSizeHashQueue<long>(1000);
|
||||
private readonly FixedSizeHashQueue<int> _cancelledQcOrderIDs = new FixedSizeHashQueue<int>(10000);
|
||||
private string _restApiUrl = "https://api.tradier.com/v1/";
|
||||
private string _restApiSandboxUrl = "https://sandbox.tradier.com/v1/";
|
||||
|
||||
/// <summary>
|
||||
/// Returns the brokerage account's base currency
|
||||
/// </summary>
|
||||
public override string AccountBaseCurrency => Currencies.USD;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new Tradier Object:
|
||||
/// </summary>
|
||||
public TradierBrokerage() : base("Tradier Brokerage")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new Tradier Object:
|
||||
/// </summary>
|
||||
@@ -102,46 +117,18 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
bool useSandbox,
|
||||
string accountId,
|
||||
string accessToken)
|
||||
: base(WebSocketUrl, new WebSocketClientWrapper(),
|
||||
new RestClient(useSandbox ? "https://sandbox.tradier.com/v1/" : "https://api.tradier.com/v1/"),
|
||||
null, null, "Tradier Brokerage")
|
||||
: base("Tradier Brokerage")
|
||||
{
|
||||
_algorithm = algorithm;
|
||||
_orderProvider = orderProvider;
|
||||
_securityProvider = securityProvider;
|
||||
_aggregator = aggregator;
|
||||
_useSandbox = useSandbox;
|
||||
_accountId = accountId;
|
||||
|
||||
RestClient.AddDefaultHeader("Accept", "application/json");
|
||||
RestClient.AddDefaultHeader("Authorization", $"Bearer {accessToken}");
|
||||
|
||||
var subscriptionManager = new EventBasedDataQueueHandlerSubscriptionManager();
|
||||
subscriptionManager.SubscribeImpl += (symbols, _) => Subscribe(symbols);
|
||||
subscriptionManager.UnsubscribeImpl += (symbols, _) => Unsubscribe(symbols);
|
||||
SubscriptionManager = subscriptionManager;
|
||||
|
||||
_cachedOpenOrdersByTradierOrderID = new ConcurrentDictionary<long, TradierCachedOpenOrder>();
|
||||
|
||||
// we can poll orders once a second in sandbox and twice a second in production
|
||||
var interval = _useSandbox ? 1000 : 500;
|
||||
_rateLimitNextRequest = new Dictionary<TradierApiRequestType, RateGate>
|
||||
{
|
||||
{ TradierApiRequestType.Data, new RateGate(1, TimeSpan.FromMilliseconds(interval))},
|
||||
{ TradierApiRequestType.Standard, new RateGate(1, TimeSpan.FromMilliseconds(interval))},
|
||||
{ TradierApiRequestType.Orders, new RateGate(1, TimeSpan.FromMilliseconds(1000))},
|
||||
};
|
||||
|
||||
_orderFillTimer = new Timer(state => CheckForFills(), null, interval, interval);
|
||||
WebSocket.Error += (sender, error) =>
|
||||
{
|
||||
if (!WebSocket.IsOpen)
|
||||
{
|
||||
// on error we clear our state, on Open we will re susbscribe
|
||||
_subscribedTickers.Clear();
|
||||
_streamSession = null;
|
||||
}
|
||||
};
|
||||
Initialize(
|
||||
wssUrl: WebSocketUrl,
|
||||
accountId: accountId,
|
||||
accessToken: accessToken,
|
||||
useSandbox: useSandbox,
|
||||
algorithm: algorithm,
|
||||
orderProvider: orderProvider,
|
||||
securityProvider: securityProvider,
|
||||
aggregator: aggregator
|
||||
);
|
||||
}
|
||||
|
||||
#region Tradier client implementation
|
||||
@@ -391,7 +378,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
/// Place Order through API.
|
||||
/// accounts/{account-id}/orders
|
||||
/// </summary>
|
||||
public TradierOrderResponse PlaceOrder(
|
||||
private TradierOrderResponse PlaceOrder(
|
||||
TradierOrderClass classification,
|
||||
TradierOrderDirection direction,
|
||||
string symbol,
|
||||
@@ -604,7 +591,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
return obj;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion Tradier client implementation
|
||||
|
||||
#region IBrokerage implementation
|
||||
|
||||
@@ -844,7 +831,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
|
||||
// success
|
||||
OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, OrderFee.Zero)
|
||||
{ Status = OrderStatus.UpdateSubmitted });
|
||||
{ Status = OrderStatus.UpdateSubmitted });
|
||||
|
||||
// if we have contingents, update them as well
|
||||
if (contingent != null)
|
||||
@@ -899,7 +886,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
TradierCachedOpenOrder tradierOrder;
|
||||
_cachedOpenOrdersByTradierOrderID.TryRemove(id, out tradierOrder);
|
||||
OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, OrderFee.Zero, "Tradier Order Event")
|
||||
{ Status = OrderStatus.Canceled });
|
||||
{ Status = OrderStatus.Canceled });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1005,7 +992,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
{
|
||||
// invalidate the order, bad request
|
||||
OnOrderEvent(new OrderEvent(order.QCOrder, DateTime.UtcNow, OrderFee.Zero)
|
||||
{ Status = OrderStatus.Invalid });
|
||||
{ Status = OrderStatus.Invalid });
|
||||
|
||||
string message = _previousResponseRaw;
|
||||
if (response != null && response.Errors != null && !response.Errors.Errors.IsNullOrEmpty())
|
||||
@@ -1338,7 +1325,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion IBrokerage implementation
|
||||
|
||||
#region Conversion routines
|
||||
|
||||
@@ -1373,12 +1360,14 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
case TradierOrderDirection.SellToOpen:
|
||||
case TradierOrderDirection.SellToClose:
|
||||
return true;
|
||||
|
||||
case TradierOrderDirection.Buy:
|
||||
case TradierOrderDirection.BuyToCover:
|
||||
case TradierOrderDirection.BuyToClose:
|
||||
case TradierOrderDirection.BuyToOpen:
|
||||
case TradierOrderDirection.None:
|
||||
return false;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("direction", direction, null);
|
||||
}
|
||||
@@ -1396,12 +1385,15 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
case TradierOrderType.Limit:
|
||||
qcOrder = new LimitOrder { LimitPrice = order.Price };
|
||||
break;
|
||||
|
||||
case TradierOrderType.Market:
|
||||
qcOrder = new MarketOrder();
|
||||
break;
|
||||
|
||||
case TradierOrderType.StopMarket:
|
||||
qcOrder = new StopMarketOrder { StopPrice = GetOrder(order.Id).StopPrice };
|
||||
break;
|
||||
|
||||
case TradierOrderType.StopLimit:
|
||||
qcOrder = new StopLimitOrder { LimitPrice = order.Price, StopPrice = GetOrder(order.Id).StopPrice };
|
||||
break;
|
||||
@@ -1773,19 +1765,71 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion Conversion routines
|
||||
|
||||
/// <summary>
|
||||
/// Initailze the instance of this class
|
||||
/// </summary>
|
||||
private void Initialize(string wssUrl,
|
||||
string accountId, string accessToken, bool useSandbox, IAlgorithm algorithm,
|
||||
IOrderProvider orderProvider, ISecurityProvider securityProvider, IDataAggregator aggregator)
|
||||
{
|
||||
if (IsInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var restClient = new RestClient(useSandbox ? _restApiSandboxUrl : _restApiUrl);
|
||||
base.Initialize(wssUrl, new WebSocketClientWrapper(), restClient, null, null);
|
||||
_algorithm = algorithm;
|
||||
_orderProvider = orderProvider;
|
||||
_securityProvider = securityProvider;
|
||||
_aggregator = aggregator;
|
||||
_useSandbox = useSandbox;
|
||||
_accountId = accountId;
|
||||
|
||||
RestClient.AddDefaultHeader("Accept", "application/json");
|
||||
RestClient.AddDefaultHeader("Authorization", $"Bearer {accessToken}");
|
||||
|
||||
var subscriptionManager = new EventBasedDataQueueHandlerSubscriptionManager();
|
||||
subscriptionManager.SubscribeImpl += (symbols, _) => Subscribe(symbols);
|
||||
subscriptionManager.UnsubscribeImpl += (symbols, _) => Unsubscribe(symbols);
|
||||
SubscriptionManager = subscriptionManager;
|
||||
|
||||
_cachedOpenOrdersByTradierOrderID = new ConcurrentDictionary<long, TradierCachedOpenOrder>();
|
||||
|
||||
// we can poll orders once a second in sandbox and twice a second in production
|
||||
var interval = _useSandbox ? 1000 : 500;
|
||||
_rateLimitNextRequest = new Dictionary<TradierApiRequestType, RateGate>
|
||||
{
|
||||
{ TradierApiRequestType.Data, new RateGate(1, TimeSpan.FromMilliseconds(interval))},
|
||||
{ TradierApiRequestType.Standard, new RateGate(1, TimeSpan.FromMilliseconds(interval))},
|
||||
{ TradierApiRequestType.Orders, new RateGate(1, TimeSpan.FromMilliseconds(1000))},
|
||||
};
|
||||
|
||||
_orderFillTimer = new Timer(state => CheckForFills(), null, interval, interval);
|
||||
WebSocket.Error += (sender, error) =>
|
||||
{
|
||||
if (!WebSocket.IsOpen)
|
||||
{
|
||||
// on error we clear our state, on Open we will re susbscribe
|
||||
_subscribedTickers.Clear();
|
||||
_streamSession = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private readonly HashSet<string> ErrorsDuringMarketHours = new HashSet<string>
|
||||
{
|
||||
"CheckForFillsError", "UnknownIdResolution", "ContingentOrderError", "NullResponse", "PendingOrderNotReturned"
|
||||
};
|
||||
|
||||
class ContingentOrderQueue
|
||||
private class ContingentOrderQueue
|
||||
{
|
||||
/// <summary>
|
||||
/// The original order produced by the algorithm
|
||||
/// </summary>
|
||||
public readonly Order QCOrder;
|
||||
|
||||
/// <summary>
|
||||
/// A queue of contingent orders to be placed after fills
|
||||
/// </summary>
|
||||
@@ -1810,7 +1854,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
}
|
||||
}
|
||||
|
||||
class TradierCachedOpenOrder
|
||||
private class TradierCachedOpenOrder
|
||||
{
|
||||
public bool EmittedOrderFee;
|
||||
public TradierOrder Order;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
@@ -13,13 +13,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Packets;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Util;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Brokerages.Tradier
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
@@ -13,11 +13,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Packets;
|
||||
using QuantConnect.Util;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Brokerages.Zerodha
|
||||
{
|
||||
@@ -34,6 +35,20 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
/// <param name="job">Job we're subscribing for</param>
|
||||
public void SetJob(LiveNodePacket job)
|
||||
{
|
||||
Initialize(
|
||||
job.BrokerageData["zerodha-trading-segment"],
|
||||
job.BrokerageData["zerodha-product-type"],
|
||||
job.BrokerageData["zerodha-api-key"],
|
||||
job.BrokerageData["zerodha-access-token"],
|
||||
null,
|
||||
null,
|
||||
Composer.Instance.GetExportedValueByTypeName<IDataAggregator>(Config.Get("data-aggregator", "QuantConnect.Lean.Engine.DataFeeds.AggregationManager"))
|
||||
);
|
||||
|
||||
if (!IsConnected)
|
||||
{
|
||||
Connect();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -47,7 +62,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
var symbol = dataConfig.Symbol;
|
||||
if (!CanSubscribe(symbol))
|
||||
{
|
||||
return Enumerable.Empty<BaseData>().GetEnumerator();
|
||||
return null;
|
||||
}
|
||||
|
||||
var enumerator = _aggregator.Add(dataConfig, newDataAvailableHandler);
|
||||
@@ -66,7 +81,6 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
_aggregator.Remove(dataConfig);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this data provide can handle the specified symbol
|
||||
/// </summary>
|
||||
@@ -82,6 +96,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
return
|
||||
(securityType == SecurityType.Equity) && (market == Market.India);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion IDataQueueHandler implementation
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,29 +14,28 @@
|
||||
*/
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NodaTime;
|
||||
using QuantConnect.Brokerages.Zerodha.Messages;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Logging;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Util;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using System.Threading;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Brokerages.Zerodha.Messages;
|
||||
using Tick = QuantConnect.Data.Market.Tick;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NodaTime;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Util;
|
||||
using System.Threading;
|
||||
using Order = QuantConnect.Orders.Order;
|
||||
using OrderType = QuantConnect.Orders.OrderType;
|
||||
using Tick = QuantConnect.Data.Market.Tick;
|
||||
|
||||
namespace QuantConnect.Brokerages.Zerodha
|
||||
{
|
||||
@@ -47,6 +46,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
public partial class ZerodhaBrokerage : Brokerage, IDataQueueHandler
|
||||
{
|
||||
#region Declarations
|
||||
|
||||
private const int ConnectionTimeout = 30000;
|
||||
|
||||
/// <summary>
|
||||
@@ -74,37 +74,43 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
/// </summary>
|
||||
protected string ApiKey;
|
||||
|
||||
private readonly ISecurityProvider _securityProvider;
|
||||
private ISecurityProvider _securityProvider;
|
||||
|
||||
private readonly IAlgorithm _algorithm;
|
||||
private IAlgorithm _algorithm;
|
||||
private readonly ConcurrentDictionary<int, decimal> _fills = new ConcurrentDictionary<int, decimal>();
|
||||
|
||||
private readonly DataQueueHandlerSubscriptionManager SubscriptionManager;
|
||||
private DataQueueHandlerSubscriptionManager SubscriptionManager;
|
||||
|
||||
private ConcurrentDictionary<string, Symbol> _subscriptionsById = new ConcurrentDictionary<string, Symbol>();
|
||||
|
||||
private readonly IDataAggregator _aggregator;
|
||||
private IDataAggregator _aggregator;
|
||||
|
||||
private readonly ZerodhaSymbolMapper _symbolMapper;
|
||||
private ZerodhaSymbolMapper _symbolMapper;
|
||||
|
||||
private readonly List<string> subscribeInstrumentTokens = new List<string>();
|
||||
private readonly List<string> unSubscribeInstrumentTokens = new List<string>();
|
||||
|
||||
private Kite _kite;
|
||||
private readonly string _apiKey;
|
||||
private readonly string _accessToken;
|
||||
private readonly string _wssUrl = "wss://ws.kite.trade/";
|
||||
private string _apiKey;
|
||||
private string _accessToken;
|
||||
private string _wssUrl = "wss://ws.kite.trade/";
|
||||
|
||||
private readonly string _tradingSegment;
|
||||
private readonly BrokerageConcurrentMessageHandler<WebSocketClientWrapper.MessageData> _messageHandler;
|
||||
private readonly string _zerodhaProductType;
|
||||
private string _tradingSegment;
|
||||
private BrokerageConcurrentMessageHandler<WebSocketClientWrapper.MessageData> _messageHandler;
|
||||
private string _zerodhaProductType;
|
||||
|
||||
private DateTime _lastTradeTickTime;
|
||||
private bool _historyDataTypeErrorFlag;
|
||||
private bool _isInitialized;
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion Declarations
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for brokerage
|
||||
/// </summary>
|
||||
public ZerodhaBrokerage() : base("Zerodha")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for brokerage
|
||||
@@ -119,37 +125,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
public ZerodhaBrokerage(string tradingSegment, string zerodhaProductType, string apiKey, string apiSecret, IAlgorithm algorithm, ISecurityProvider securityProvider, IDataAggregator aggregator)
|
||||
: base("Zerodha")
|
||||
{
|
||||
_tradingSegment = tradingSegment;
|
||||
_zerodhaProductType = zerodhaProductType;
|
||||
_algorithm = algorithm;
|
||||
_aggregator = aggregator;
|
||||
_kite = new Kite(apiKey, apiSecret);
|
||||
_apiKey = apiKey;
|
||||
_accessToken = apiSecret;
|
||||
_securityProvider = securityProvider;
|
||||
_messageHandler = new BrokerageConcurrentMessageHandler<WebSocketClientWrapper.MessageData>(OnMessageImpl);
|
||||
WebSocket = new WebSocketClientWrapper();
|
||||
_wssUrl += string.Format(CultureInfo.InvariantCulture, "?api_key={0}&access_token={1}", _apiKey, _accessToken);
|
||||
WebSocket.Initialize(_wssUrl);
|
||||
WebSocket.Message += OnMessage;
|
||||
WebSocket.Open += (sender, args) =>
|
||||
{
|
||||
Log.Trace($"ZerodhaBrokerage(): WebSocket.Open. Subscribing");
|
||||
Subscribe(GetSubscribed());
|
||||
};
|
||||
WebSocket.Error += OnError;
|
||||
_symbolMapper = new ZerodhaSymbolMapper(_kite);
|
||||
|
||||
var subscriptionManager = new EventBasedDataQueueHandlerSubscriptionManager();
|
||||
subscriptionManager.SubscribeImpl += (s, t) =>
|
||||
{
|
||||
Subscribe(s);
|
||||
return true;
|
||||
};
|
||||
subscriptionManager.UnsubscribeImpl += (s, t) => Unsubscribe(s);
|
||||
SubscriptionManager = subscriptionManager;
|
||||
|
||||
Log.Trace("Start Zerodha Brokerage");
|
||||
Initialize(tradingSegment, zerodhaProductType, apiKey, apiSecret, algorithm, securityProvider, aggregator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -188,7 +164,6 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
WebSocket.Send(requestFullMode);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get list of subscribed symbol
|
||||
/// </summary>
|
||||
@@ -214,7 +189,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
continue;
|
||||
}
|
||||
foreach (var instrumentToken in instrumentTokenList)
|
||||
{
|
||||
{
|
||||
var tokenStringInvariant = instrumentToken.ToStringInvariant();
|
||||
if (!unSubscribeInstrumentTokens.Contains(tokenStringInvariant))
|
||||
{
|
||||
@@ -230,10 +205,8 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets Quote using Zerodha API
|
||||
/// </summary>
|
||||
@@ -346,7 +319,6 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region IBrokerage
|
||||
|
||||
@@ -395,7 +367,6 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Places a new order and assigns a new broker ID to the order
|
||||
/// </summary>
|
||||
@@ -407,9 +378,8 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
|
||||
_messageHandler.WithLockedStream(() =>
|
||||
{
|
||||
|
||||
uint orderQuantity = Convert.ToUInt32(Math.Abs(order.Quantity));
|
||||
JObject orderResponse = new JObject();;
|
||||
JObject orderResponse = new JObject(); ;
|
||||
|
||||
decimal? triggerPrice = GetOrderTriggerPrice(order);
|
||||
decimal? orderPrice = GetOrderPrice(order);
|
||||
@@ -433,7 +403,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
}
|
||||
else if (string.IsNullOrEmpty(zerodhaProductType))
|
||||
{
|
||||
throw new ArgumentException("Please set ProductType in config or provide a value in DefaultOrderProperties");
|
||||
throw new ArgumentException("Please set ProductType in config or provide a value in DefaultOrderProperties");
|
||||
}
|
||||
try
|
||||
{
|
||||
@@ -442,14 +412,12 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
var errorMessage = $"Order failed, Order Id: {order.Id} timestamp: {order.Time} quantity: {order.Quantity} content: {ex.Message}";
|
||||
OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee, "Zerodha Order Event") { Status = OrderStatus.Invalid });
|
||||
OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, -1, errorMessage));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ((string)orderResponse["status"] == "success")
|
||||
{
|
||||
if (string.IsNullOrEmpty((string)orderResponse["data"]["order_id"]))
|
||||
@@ -538,23 +506,25 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
|
||||
private static string ConvertOrderType(OrderType orderType)
|
||||
{
|
||||
|
||||
switch (orderType)
|
||||
{
|
||||
case OrderType.Limit:
|
||||
return "LIMIT";
|
||||
|
||||
case OrderType.Market:
|
||||
return "MARKET";
|
||||
|
||||
case OrderType.StopMarket:
|
||||
return "SL-M";
|
||||
|
||||
case OrderType.StopLimit:
|
||||
return "SL";
|
||||
|
||||
default:
|
||||
throw new NotSupportedException($"ZerodhaBrokerage.ConvertOrderType: Unsupported order type: {orderType}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Updates the order with the same id
|
||||
/// </summary>
|
||||
@@ -566,7 +536,6 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
|
||||
_messageHandler.WithLockedStream(() =>
|
||||
{
|
||||
|
||||
if (!order.Status.IsOpen())
|
||||
{
|
||||
OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, "error", "Order is already being processed"));
|
||||
@@ -574,7 +543,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
}
|
||||
|
||||
var orderProperties = order.Properties as IndiaOrderProperties;
|
||||
var zerodhaProductType = _zerodhaProductType;
|
||||
var zerodhaProductType = _zerodhaProductType;
|
||||
if (orderProperties == null || orderProperties.Exchange == null)
|
||||
{
|
||||
var errorMessage = $"Order failed, Order Id: {order.Id} timestamp: {order.Time} quantity: {order.Quantity} content: Please specify a valid order properties with an exchange value";
|
||||
@@ -587,16 +556,16 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
}
|
||||
else if (string.IsNullOrEmpty(zerodhaProductType))
|
||||
{
|
||||
throw new ArgumentException("Please set ProductType in config or provide a value in DefaultOrderProperties");
|
||||
throw new ArgumentException("Please set ProductType in config or provide a value in DefaultOrderProperties");
|
||||
}
|
||||
uint orderQuantity = Convert.ToUInt32(Math.Abs(order.Quantity));
|
||||
JObject orderResponse = new JObject();;
|
||||
JObject orderResponse = new JObject(); ;
|
||||
decimal? triggerPrice = GetOrderTriggerPrice(order);
|
||||
decimal? orderPrice = GetOrderPrice(order);
|
||||
var kiteOrderType = ConvertOrderType(order.Type);
|
||||
|
||||
var orderFee = OrderFee.Zero;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
orderResponse = _kite.ModifyOrder(order.BrokerId[0].ToStringInvariant(),
|
||||
@@ -615,13 +584,11 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee, "Zerodha Update Order Event") { Status = OrderStatus.Invalid });
|
||||
OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, -1, $"Order failed, Order Id: {order.Id} timestamp: {order.Time} quantity: {order.Quantity} content: {ex.Message}"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ((string)orderResponse["status"] == "success")
|
||||
{
|
||||
if (string.IsNullOrEmpty((string)orderResponse["data"]["order_id"]))
|
||||
@@ -668,12 +635,11 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
/// <param name="order">The order to cancel</param>
|
||||
/// <returns>True if the request was submitted for cancellation, false otherwise</returns>
|
||||
public override bool CancelOrder(Order order)
|
||||
{
|
||||
{
|
||||
var submitted = false;
|
||||
|
||||
_messageHandler.WithLockedStream(() =>
|
||||
{
|
||||
|
||||
JObject orderResponse = new JObject();
|
||||
if (order.Status.IsOpen())
|
||||
{
|
||||
@@ -705,10 +671,8 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
return;
|
||||
});
|
||||
return submitted;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets all orders not yet closed
|
||||
/// </summary>
|
||||
@@ -756,7 +720,6 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
order.Status = ConvertOrderStatus(item);
|
||||
order.Price = item.Price;
|
||||
list.Add(order);
|
||||
|
||||
}
|
||||
foreach (var item in list)
|
||||
{
|
||||
@@ -799,8 +762,6 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
return OrderStatus.None;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets all open postions and account holdings
|
||||
/// </summary>
|
||||
@@ -813,15 +774,13 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
var productTypeNRML = KiteProductType.NRML.ToString().ToUpperInvariant();
|
||||
var productTypeCNC = KiteProductType.CNC.ToString().ToUpperInvariant();
|
||||
// get MIS and NRML Positions
|
||||
if (string.IsNullOrEmpty(_zerodhaProductType) || zerodhaProductTypeUpper == productTypeMIS || zerodhaProductTypeUpper == productTypeNRML)
|
||||
if (string.IsNullOrEmpty(_zerodhaProductType) || zerodhaProductTypeUpper == productTypeMIS || zerodhaProductTypeUpper == productTypeNRML)
|
||||
{
|
||||
var PositionsResponse = _kite.GetPositions();
|
||||
if (PositionsResponse.Day.Count != 0)
|
||||
{
|
||||
|
||||
foreach (var item in PositionsResponse.Day)
|
||||
{
|
||||
|
||||
Holding holding = new Holding
|
||||
{
|
||||
AveragePrice = item.AveragePrice,
|
||||
@@ -831,14 +790,13 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
UnrealizedPnL = item.Unrealised,
|
||||
CurrencySymbol = Currencies.GetCurrencySymbol(AccountBaseCurrency),
|
||||
MarketValue = item.ClosePrice * item.Quantity
|
||||
|
||||
};
|
||||
holdingsList.Add(holding);
|
||||
}
|
||||
}
|
||||
}
|
||||
// get CNC Positions
|
||||
if (string.IsNullOrEmpty(_zerodhaProductType) || zerodhaProductTypeUpper == productTypeCNC )
|
||||
if (string.IsNullOrEmpty(_zerodhaProductType) || zerodhaProductTypeUpper == productTypeCNC)
|
||||
{
|
||||
var HoldingResponse = _kite.GetHoldings();
|
||||
if (HoldingResponse != null)
|
||||
@@ -897,7 +855,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
_historyDataTypeErrorFlag = true;
|
||||
yield break;
|
||||
}
|
||||
|
||||
|
||||
if (request.Symbol.SecurityType != SecurityType.Equity && request.Symbol.SecurityType != SecurityType.Future && request.Symbol.SecurityType != SecurityType.Option)
|
||||
{
|
||||
OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, "InvalidSecurityType",
|
||||
@@ -930,7 +888,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
}
|
||||
|
||||
var history = Enumerable.Empty<BaseData>();
|
||||
|
||||
|
||||
var symbol = request.Symbol;
|
||||
var start = request.StartTimeLocal;
|
||||
var end = request.EndTimeLocal;
|
||||
@@ -961,6 +919,46 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
}
|
||||
}
|
||||
|
||||
private void Initialize(string tradingSegment, string zerodhaProductType, string apiKey, string apiSecret,
|
||||
IAlgorithm algorithm, ISecurityProvider securityProvider, IDataAggregator aggregator)
|
||||
{
|
||||
if (_isInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_isInitialized = true;
|
||||
_tradingSegment = tradingSegment;
|
||||
_zerodhaProductType = zerodhaProductType;
|
||||
_algorithm = algorithm;
|
||||
_aggregator = aggregator;
|
||||
_kite = new Kite(apiKey, apiSecret);
|
||||
_apiKey = apiKey;
|
||||
_accessToken = apiSecret;
|
||||
_securityProvider = securityProvider;
|
||||
_messageHandler = new BrokerageConcurrentMessageHandler<WebSocketClientWrapper.MessageData>(OnMessageImpl);
|
||||
WebSocket = new WebSocketClientWrapper();
|
||||
_wssUrl += string.Format(CultureInfo.InvariantCulture, "?api_key={0}&access_token={1}", _apiKey, _accessToken);
|
||||
WebSocket.Initialize(_wssUrl);
|
||||
WebSocket.Message += OnMessage;
|
||||
WebSocket.Open += (sender, args) =>
|
||||
{
|
||||
Log.Trace($"ZerodhaBrokerage(): WebSocket.Open. Subscribing");
|
||||
Subscribe(GetSubscribed());
|
||||
};
|
||||
WebSocket.Error += OnError;
|
||||
_symbolMapper = new ZerodhaSymbolMapper(_kite);
|
||||
|
||||
var subscriptionManager = new EventBasedDataQueueHandlerSubscriptionManager();
|
||||
subscriptionManager.SubscribeImpl += (s, t) =>
|
||||
{
|
||||
Subscribe(s);
|
||||
return true;
|
||||
};
|
||||
subscriptionManager.UnsubscribeImpl += (s, t) => Unsubscribe(s);
|
||||
SubscriptionManager = subscriptionManager;
|
||||
Log.Trace("ZerodhaBrokerage(): Zerodha Brokerage initialized");
|
||||
}
|
||||
|
||||
private IEnumerable<BaseData> GetHistoryForPeriod(Symbol symbol, DateTime start, DateTime end, DateTimeZone exchangeTimeZone, Resolution resolution, string zerodhaResolution)
|
||||
{
|
||||
Log.Debug("ZerodhaBrokerage.GetHistoryForPeriod();");
|
||||
@@ -981,7 +979,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
|
||||
foreach (var candle in candles)
|
||||
{
|
||||
yield return new TradeBar(candle.TimeStamp.ConvertFromUtc(exchangeTimeZone),symbol,candle.Open,candle.High,candle.Low,candle.Close,candle.Volume,resolution.ToTimeSpan());
|
||||
yield return new TradeBar(candle.TimeStamp.ConvertFromUtc(exchangeTimeZone), symbol, candle.Open, candle.High, candle.Low, candle.Close, candle.Volume, resolution.ToTimeSpan());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1045,7 +1043,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
|
||||
var bestBidQuote = tick.Bids[0];
|
||||
var bestAskQuote = tick.Offers[0];
|
||||
var instrumentTokenValue = tick.InstrumentToken;
|
||||
var instrumentTokenValue = tick.InstrumentToken;
|
||||
|
||||
var time = tick.Timestamp ?? DateTime.UtcNow.ConvertFromUtc(TimeZones.Kolkata);
|
||||
|
||||
@@ -1252,7 +1250,6 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
tick.OIDayLow = ReadInt(b, ref offset);
|
||||
tick.Timestamp = Time.UnixTimeStampToDateTime(ReadInt(b, ref offset));
|
||||
|
||||
|
||||
tick.Bids = new DepthItem[5];
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
@@ -1272,8 +1269,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
}
|
||||
return tick;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion IBrokerage
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using QuantConnect.Optimizer.Parameters;
|
||||
using QuantConnect.Statistics;
|
||||
|
||||
namespace QuantConnect.Api
|
||||
@@ -29,86 +30,92 @@ namespace QuantConnect.Api
|
||||
/// Name of the backtest
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "name")]
|
||||
public string Name;
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Note on the backtest attached by the user
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "note")]
|
||||
public string Note;
|
||||
public string Note { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Assigned backtest Id
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "backtestId")]
|
||||
public string BacktestId;
|
||||
public string BacktestId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Boolean true when the backtest is completed.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "completed")]
|
||||
public bool Completed;
|
||||
public bool Completed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Progress of the backtest in percent 0-1.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "progress")]
|
||||
public decimal Progress;
|
||||
public decimal Progress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Backtest error message
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "error")]
|
||||
public string Error;
|
||||
public string Error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Backtest error stacktrace
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "stacktrace")]
|
||||
public string StackTrace;
|
||||
public string StackTrace { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Backtest creation date and time
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "created")]
|
||||
public DateTime Created;
|
||||
public DateTime Created { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Rolling window detailed statistics.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "rollingWindow", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public Dictionary<string, AlgorithmPerformance> RollingWindow;
|
||||
public Dictionary<string, AlgorithmPerformance> RollingWindow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Rolling window detailed statistics.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "totalPerformance", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public AlgorithmPerformance TotalPerformance;
|
||||
public AlgorithmPerformance TotalPerformance { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Contains population averages scores over the life of the algorithm
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "alphaRuntimeStatistics", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public AlphaRuntimeStatistics AlphaRuntimeStatistics;
|
||||
public AlphaRuntimeStatistics AlphaRuntimeStatistics { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Charts updates for the live algorithm since the last result packet
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "charts", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public IDictionary<string, Chart> Charts;
|
||||
public IDictionary<string, Chart> Charts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Statistics information sent during the algorithm operations.
|
||||
/// </summary>
|
||||
/// <remarks>Intended for update mode -- send updates to the existing statistics in the result GUI. If statistic key does not exist in GUI, create it</remarks>
|
||||
[JsonProperty(PropertyName = "statistics", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public IDictionary<string, string> Statistics;
|
||||
public IDictionary<string, string> Statistics { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Runtime banner/updating statistics in the title banner of the live algorithm GUI.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "runtimeStatistics", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public IDictionary<string, string> RuntimeStatistics;
|
||||
public IDictionary<string, string> RuntimeStatistics { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optimization parameters
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "parameterSet")]
|
||||
public ParameterSet ParameterSet { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -121,7 +128,7 @@ namespace QuantConnect.Api
|
||||
/// Backtest Object
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "backtest")]
|
||||
public Backtest Backtest;
|
||||
public Backtest Backtest { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -133,6 +140,6 @@ namespace QuantConnect.Api
|
||||
/// Collection of summarized backtest objects
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "backtests")]
|
||||
public List<Backtest> Backtests;
|
||||
public List<Backtest> Backtests { get; set; }
|
||||
}
|
||||
}
|
||||
65
Common/Api/BaseOptimization.cs
Normal file
65
Common/Api/BaseOptimization.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 Newtonsoft.Json;
|
||||
using QuantConnect.Optimizer;
|
||||
using QuantConnect.Optimizer.Objectives;
|
||||
|
||||
namespace QuantConnect.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// BaseOptimization item from the QuantConnect.com API.
|
||||
/// </summary>
|
||||
public class BaseOptimization : RestResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Optimization ID
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "optimizationId")]
|
||||
public string OptimizationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Project ID of the project the optimization belongs to
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "projectId")]
|
||||
public int ProjectId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the optimization
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Status of the optimization
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "status")]
|
||||
public OptimizationStatus Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optimization node type
|
||||
/// </summary>
|
||||
/// <remarks><see cref="OptimizationNodes"/></remarks>
|
||||
[JsonProperty(PropertyName = "nodeType")]
|
||||
public string NodeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optimization statistical target
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "criterion")]
|
||||
public Target Criterion { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -28,19 +28,19 @@ namespace QuantConnect.Api
|
||||
/// Compile Id for a sucessful build
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "compileId")]
|
||||
public string CompileId;
|
||||
public string CompileId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True on successful compile
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "state")]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public CompileState State;
|
||||
public CompileState State { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Logs of the compilation request
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "logs")]
|
||||
public List<string> Logs;
|
||||
public List<string> Logs { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
56
Common/Api/Estimate.cs
Normal file
56
Common/Api/Estimate.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 Newtonsoft.Json;
|
||||
|
||||
namespace QuantConnect.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Estimate response packet from the QuantConnect.com API.
|
||||
/// </summary>
|
||||
public class Estimate
|
||||
{
|
||||
/// <summary>
|
||||
/// Estimate id
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "estimateId")]
|
||||
public string EstimateId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Estimate time in seconds
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "time")]
|
||||
public int Time { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Estimate balance in QCC
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "balance")]
|
||||
public int Balance { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper class for Optimizations/* endpoints JSON response
|
||||
/// Currently used by Optimizations/Estimate
|
||||
/// </summary>
|
||||
public class EstimateResponseWrapper : RestResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Estimate object
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "estimate")]
|
||||
public Estimate Estimate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -27,37 +27,37 @@ namespace QuantConnect.Api
|
||||
/// Project id for the live instance
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "projectId")]
|
||||
public int ProjectId;
|
||||
public int ProjectId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Unique live algorithm deployment identifier (similar to a backtest id).
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "deployId")]
|
||||
public string DeployId;
|
||||
public string DeployId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Algorithm status: running, stopped or runtime error.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "status")]
|
||||
public AlgorithmStatus Status;
|
||||
public AlgorithmStatus Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Datetime the algorithm was launched in UTC.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "launched")]
|
||||
public DateTime Launched;
|
||||
public DateTime Launched { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Datetime the algorithm was stopped in UTC, null if its still running.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "stopped")]
|
||||
public DateTime? Stopped;
|
||||
public DateTime? Stopped { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Brokerage
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "brokerage")]
|
||||
public string Brokerage;
|
||||
public string Brokerage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Chart we're subscribed to
|
||||
@@ -66,13 +66,13 @@ namespace QuantConnect.Api
|
||||
/// Data limitations mean we can only stream one chart at a time to the consumer. See which chart you're watching here.
|
||||
/// </remarks>
|
||||
[JsonProperty(PropertyName = "subscription")]
|
||||
public string Subscription;
|
||||
public string Subscription { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Live algorithm error message from a crash or algorithm runtime error.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "error")]
|
||||
public string Error;
|
||||
public string Error { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -84,6 +84,6 @@ namespace QuantConnect.Api
|
||||
/// Algorithm list matching the requested status.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "live")]
|
||||
public List<LiveAlgorithm> Algorithms;
|
||||
public List<LiveAlgorithm> Algorithms { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,18 +73,6 @@ namespace QuantConnect.Api
|
||||
{
|
||||
var jObject = JObject.Load(reader);
|
||||
|
||||
var liveResults = CreateLiveResultsFromJObject(jObject);
|
||||
|
||||
return liveResults;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom parsing of live results data
|
||||
/// </summary>
|
||||
/// <param name="jObject">Json representing LiveResults</param>
|
||||
/// <returns></returns>
|
||||
public static LiveAlgorithmResults CreateLiveResultsFromJObject(JObject jObject)
|
||||
{
|
||||
var liveAlgoResults = new LiveAlgorithmResults
|
||||
{
|
||||
Success = jObject["success"].Value<bool>()
|
||||
|
||||
@@ -103,19 +103,19 @@ namespace QuantConnect.Api
|
||||
/// Collection of backtest nodes
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "backtest")]
|
||||
public List<Node> BacktestNodes;
|
||||
public List<Node> BacktestNodes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Collection of research nodes
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "research")]
|
||||
public List<Node> ResearchNodes;
|
||||
public List<Node> ResearchNodes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Collection of live nodes
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "live")]
|
||||
public List<Node> LiveNodes;
|
||||
public List<Node> LiveNodes { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -143,17 +143,17 @@ namespace QuantConnect.Api
|
||||
/// <summary>
|
||||
/// The number of CPU cores in the node
|
||||
/// </summary>
|
||||
public int Cores;
|
||||
public int Cores { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Size of RAM in GB of the Node
|
||||
/// </summary>
|
||||
public int Memory;
|
||||
public int Memory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Target environment for the node
|
||||
/// </summary>
|
||||
public NodeType Target;
|
||||
public NodeType Target { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a SKU object out of the provided node configuration
|
||||
@@ -234,4 +234,24 @@ namespace QuantConnect.Api
|
||||
public int Yearly { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supported optimization nodes
|
||||
/// </summary>
|
||||
public static class OptimizationNodes
|
||||
{
|
||||
/// <summary>
|
||||
/// 2 CPUs 8 GB ram
|
||||
/// </summary>
|
||||
public static string O2_8 => "O2-8";
|
||||
|
||||
/// <summary>
|
||||
/// 4 CPUs 12 GB ram
|
||||
/// </summary>
|
||||
public static string O4_12 => "O4-12";
|
||||
|
||||
/// <summary>
|
||||
/// 8 CPUs 16 GB ram
|
||||
/// </summary>
|
||||
public static string O8_16 => "O8-16";
|
||||
}
|
||||
}
|
||||
|
||||
95
Common/Api/Optimization.cs
Normal file
95
Common/Api/Optimization.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using QuantConnect.Optimizer.Objectives;
|
||||
using QuantConnect.Optimizer.Parameters;
|
||||
|
||||
namespace QuantConnect.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Optimization response packet from the QuantConnect.com API.
|
||||
/// </summary>
|
||||
public class Optimization : BaseOptimization
|
||||
{
|
||||
/// <summary>
|
||||
/// Runtime banner/updating statistics for the optimization
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "runtimeStatistics", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public IDictionary<string, string> RuntimeStatistics { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optimization constraints
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "constraints", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public IReadOnlyList<Constraint> Constraints { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optimization parameters
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "parameters", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public HashSet<OptimizationParameter> Parameters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of parallel nodes for optimization
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "parallelNodes")]
|
||||
public int ParallelNodes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optimization constraints
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "backtests", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public IDictionary<string, OptimizationBacktest> Backtests { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optimization strategy
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "strategy")]
|
||||
public string Strategy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optimization requested date and time
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "requested")]
|
||||
public DateTime Requested { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper class for Optimizations/Read endpoint JSON response
|
||||
/// </summary>
|
||||
public class OptimizationResponseWrapper : RestResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Optimization object
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "optimization")]
|
||||
public Optimization Optimization { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collection container for a list of summarized optimizations for a project
|
||||
/// </summary>
|
||||
public class OptimizationList : RestResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection of summarized optimization objects
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "optimizations")]
|
||||
public List<BaseOptimization> Optimizations { get; set; }
|
||||
}
|
||||
}
|
||||
81
Common/Api/OptimizationBacktest.cs
Normal file
81
Common/Api/OptimizationBacktest.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using QuantConnect.Optimizer.Parameters;
|
||||
|
||||
namespace QuantConnect.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// OptimizationBacktest object from the QuantConnect.com API.
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(OptimizationBacktestJsonConverter))]
|
||||
public class OptimizationBacktest
|
||||
{
|
||||
/// <summary>
|
||||
/// Progress of the backtest as a percentage from 0-1 based on the days lapsed from start-finish.
|
||||
/// </summary>
|
||||
public decimal Progress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The backtest name
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The backtest host name
|
||||
/// </summary>
|
||||
public string HostName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The backtest id
|
||||
/// </summary>
|
||||
public string BacktestId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Represent a combination as key value of parameters, i.e. order doesn't matter
|
||||
/// </summary>
|
||||
public ParameterSet ParameterSet { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The backtest statistics results
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Statistics { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The backtest equity chart series
|
||||
/// </summary>
|
||||
public Series Equity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The exit code of this backtest
|
||||
/// </summary>
|
||||
public int ExitCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance
|
||||
/// </summary>
|
||||
/// <param name="parameterSet">The parameter set</param>
|
||||
/// <param name="backtestId">The backtest id if any</param>
|
||||
/// <param name="name">The backtest name</param>
|
||||
public OptimizationBacktest(ParameterSet parameterSet, string backtestId, string name)
|
||||
{
|
||||
ParameterSet = parameterSet;
|
||||
BacktestId = backtestId;
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
202
Common/Api/OptimizationBacktestJsonConverter.cs
Normal file
202
Common/Api/OptimizationBacktestJsonConverter.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using QuantConnect.Optimizer.Parameters;
|
||||
using QuantConnect.Statistics;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Json converter for <see cref="OptimizationBacktest"/> which creates a light weight easy to consume serialized version
|
||||
/// </summary>
|
||||
public class OptimizationBacktestJsonConverter : JsonConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(OptimizationBacktest);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
var optimizationBacktest = value as OptimizationBacktest;
|
||||
if (ReferenceEquals(optimizationBacktest, null)) return;
|
||||
|
||||
writer.WriteStartObject();
|
||||
|
||||
if (!string.IsNullOrEmpty(optimizationBacktest.Name))
|
||||
{
|
||||
writer.WritePropertyName("name");
|
||||
writer.WriteValue(optimizationBacktest.Name);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(optimizationBacktest.BacktestId))
|
||||
{
|
||||
writer.WritePropertyName("id");
|
||||
writer.WriteValue(optimizationBacktest.BacktestId);
|
||||
|
||||
writer.WritePropertyName("progress");
|
||||
writer.WriteValue(optimizationBacktest.Progress);
|
||||
|
||||
writer.WritePropertyName("exitCode");
|
||||
writer.WriteValue(optimizationBacktest.ExitCode);
|
||||
}
|
||||
|
||||
if (!optimizationBacktest.Statistics.IsNullOrEmpty())
|
||||
{
|
||||
writer.WritePropertyName("statistics");
|
||||
writer.WriteStartArray();
|
||||
foreach (var keyValuePair in optimizationBacktest.Statistics.OrderBy(pair => pair.Key))
|
||||
{
|
||||
var statistic = keyValuePair.Value.Replace("%", string.Empty).Replace("$", string.Empty);
|
||||
if (string.IsNullOrEmpty(statistic))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
decimal result;
|
||||
if (decimal.TryParse(statistic, NumberStyles.Any, CultureInfo.InvariantCulture, out result))
|
||||
{
|
||||
writer.WriteValue(result);
|
||||
}
|
||||
}
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
|
||||
if (optimizationBacktest.ParameterSet != null)
|
||||
{
|
||||
writer.WritePropertyName("parameterSet");
|
||||
serializer.Serialize(writer, optimizationBacktest.ParameterSet.Value);
|
||||
}
|
||||
|
||||
if (optimizationBacktest.Equity != null)
|
||||
{
|
||||
writer.WritePropertyName("equity");
|
||||
writer.WriteStartArray();
|
||||
foreach (var chartPoint in optimizationBacktest.Equity.Values)
|
||||
{
|
||||
writer.WriteStartArray();
|
||||
writer.WriteValue(chartPoint.x);
|
||||
writer.WriteValue(chartPoint.y);
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>
|
||||
/// The object value.
|
||||
/// </returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
var jObject = JObject.Load(reader);
|
||||
|
||||
var name = jObject["name"].Value<string>();
|
||||
var hostName = jObject["hostName"]?.Value<string>();
|
||||
var backtestId = jObject["id"].Value<string>();
|
||||
var progress = jObject["progress"].Value<decimal>();
|
||||
var exitCode = jObject["exitCode"].Value<int>();
|
||||
|
||||
var jStatistics = jObject["statistics"];
|
||||
var statistics = new Dictionary<string, string>
|
||||
{
|
||||
{ PerformanceMetrics.Alpha, jStatistics[0].Value<string>() },
|
||||
{ PerformanceMetrics.AnnualStandardDeviation, jStatistics[1].Value<string>() },
|
||||
{ PerformanceMetrics.AnnualVariance, jStatistics[2].Value<string>() },
|
||||
{ PerformanceMetrics.AverageLoss, jStatistics[3].Value<string>() },
|
||||
{ PerformanceMetrics.AverageWin, jStatistics[4].Value<string>() },
|
||||
{ PerformanceMetrics.Beta, jStatistics[5].Value<string>() },
|
||||
{ PerformanceMetrics.CompoundingAnnualReturn, jStatistics[6].Value<string>() },
|
||||
{ PerformanceMetrics.Drawdown, jStatistics[7].Value<string>() },
|
||||
{ PerformanceMetrics.EstimatedStrategyCapacity, jStatistics[8].Value<string>() },
|
||||
{ PerformanceMetrics.Expectancy, jStatistics[9].Value<string>() },
|
||||
{ PerformanceMetrics.InformationRatio, jStatistics[10].Value<string>() },
|
||||
{ PerformanceMetrics.LossRate, jStatistics[11].Value<string>() },
|
||||
{ PerformanceMetrics.NetProfit, jStatistics[12].Value<string>() },
|
||||
{ PerformanceMetrics.ProbabilisticSharpeRatio, jStatistics[13].Value<string>() },
|
||||
{ PerformanceMetrics.ProfitLossRatio, jStatistics[14].Value<string>() },
|
||||
{ PerformanceMetrics.SharpeRatio, jStatistics[15].Value<string>() },
|
||||
{ PerformanceMetrics.TotalFees, jStatistics[16].Value<string>() },
|
||||
{ PerformanceMetrics.TotalTrades, jStatistics[17].Value<string>() },
|
||||
{ PerformanceMetrics.TrackingError, jStatistics[18].Value<string>() },
|
||||
{ PerformanceMetrics.TreynorRatio, jStatistics[19].Value<string>() },
|
||||
{ PerformanceMetrics.WinRate, jStatistics[20].Value<string>() },
|
||||
};
|
||||
|
||||
var parameterSet = serializer.Deserialize<ParameterSet>(jObject["parameterSet"].CreateReader());
|
||||
|
||||
var equity = new Series { Values = GetSeriesValues(jObject["equity"]) };
|
||||
|
||||
var optimizationBacktest = new OptimizationBacktest(parameterSet, backtestId, name)
|
||||
{
|
||||
HostName = hostName,
|
||||
Progress = progress,
|
||||
ExitCode = exitCode,
|
||||
Statistics = statistics,
|
||||
Equity = equity
|
||||
};
|
||||
|
||||
return optimizationBacktest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get x and y value pairs that represent series data
|
||||
/// </summary>
|
||||
/// <param name="values">json array of x, y value pairs</param>
|
||||
/// <returns>List of ChartPoints</returns>
|
||||
private static List<ChartPoint> GetSeriesValues(JToken values)
|
||||
{
|
||||
var chartPoints = new List<ChartPoint>();
|
||||
|
||||
foreach (var point in values.Children())
|
||||
{
|
||||
var x = point[0];
|
||||
var y = point[1];
|
||||
|
||||
chartPoints.Add(new ChartPoint((long)x, (decimal)y));
|
||||
}
|
||||
|
||||
return chartPoints;
|
||||
}
|
||||
}
|
||||
}
|
||||
78
Common/Api/ParameterSetJsonConverter.cs
Normal file
78
Common/Api/ParameterSetJsonConverter.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using QuantConnect.Optimizer.Parameters;
|
||||
|
||||
namespace QuantConnect.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Json converter for <see cref="ParameterSet"/> which creates a light weight easy to consume serialized version
|
||||
/// </summary>
|
||||
public class ParameterSetJsonConverter : JsonConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(ParameterSet);
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||
{
|
||||
var parameterSet = value as ParameterSet;
|
||||
if (ReferenceEquals(parameterSet, null)) return;
|
||||
|
||||
writer.WriteStartObject();
|
||||
|
||||
if (parameterSet.Value != null)
|
||||
{
|
||||
writer.WritePropertyName("parameterSet");
|
||||
serializer.Serialize(writer, parameterSet.Value);
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>
|
||||
/// The object value.
|
||||
/// </returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
var jObject = JObject.Load(reader);
|
||||
|
||||
var value = jObject["parameterSet"] ?? jObject;
|
||||
|
||||
var parameterSet = new ParameterSet(-1, value.ToObject<Dictionary<string, string>>());
|
||||
|
||||
return parameterSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,31 +27,31 @@ namespace QuantConnect.Api
|
||||
/// Project id
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "projectId")]
|
||||
public int ProjectId;
|
||||
public int ProjectId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the project
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "name")]
|
||||
public string Name;
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Date the project was created
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "created")]
|
||||
public DateTime Created;
|
||||
public DateTime Created { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Modified date for the project
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "modified")]
|
||||
public DateTime Modified;
|
||||
public DateTime Modified { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Programming language of the project
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "language")]
|
||||
public Language Language;
|
||||
public Language Language { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -63,6 +63,6 @@ namespace QuantConnect.Api
|
||||
/// List of projects for the authenticated user
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "projects")]
|
||||
public List<Project> Projects;
|
||||
public List<Project> Projects { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -28,13 +28,13 @@ namespace QuantConnect.Api
|
||||
/// Name of a project file
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "name")]
|
||||
public string Name;
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Contents of the project file
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "content")]
|
||||
public string Code;
|
||||
public string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// DateTime project file was modified
|
||||
@@ -52,6 +52,6 @@ namespace QuantConnect.Api
|
||||
/// List of project file information
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "files")]
|
||||
public List<ProjectFile> Files;
|
||||
public List<ProjectFile> Files { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -35,12 +35,12 @@ namespace QuantConnect.Api
|
||||
/// Indicate if the API request was successful.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "success")]
|
||||
public bool Success;
|
||||
public bool Success { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of errors with the API call.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "errors")]
|
||||
public List<string> Errors;
|
||||
public List<string> Errors { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -59,11 +59,6 @@ namespace QuantConnect.Brokerages
|
||||
/// <returns>The leverage for the specified security</returns>
|
||||
public override decimal GetLeverage(Security security)
|
||||
{
|
||||
if (AccountType == AccountType.Cash)
|
||||
{
|
||||
return 1m;
|
||||
}
|
||||
|
||||
switch (security.Type)
|
||||
{
|
||||
case SecurityType.Forex:
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace QuantConnect.Brokerages
|
||||
{SecurityType.Future, Market.CME},
|
||||
{SecurityType.FutureOption, Market.CME},
|
||||
{SecurityType.Forex, Market.Oanda},
|
||||
{SecurityType.Cfd, Market.FXCM},
|
||||
{SecurityType.Cfd, Market.Oanda},
|
||||
{SecurityType.Crypto, Market.GDAX},
|
||||
{SecurityType.Index, Market.USA},
|
||||
{SecurityType.IndexOption, Market.USA}
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace QuantConnect.Data
|
||||
var fileData = currentFileData;
|
||||
writeTasks.Enqueue(Task.Run(() =>
|
||||
{
|
||||
WriteFile(file, fileData, data.Time);
|
||||
WriteFile(file, fileData);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace QuantConnect.Data
|
||||
{
|
||||
writeTasks.Enqueue(Task.Run(() =>
|
||||
{
|
||||
WriteFile(outputFile, currentFileData, lastTime);
|
||||
WriteFile(outputFile, currentFileData);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -258,16 +258,19 @@ namespace QuantConnect.Data
|
||||
/// </summary>
|
||||
/// <param name="filePath">The full path to the new file</param>
|
||||
/// <param name="data">The data to write as a list of dates and strings</param>
|
||||
/// <param name="date">The date the data represents</param>
|
||||
/// <remarks>The reason we have the data as IEnumerable(DateTime, string) is to support
|
||||
/// a generic write that works for all resolutions. In order to merge in hour/daily case I need the
|
||||
/// date of the data to correctly merge the two. In order to support writing ticks I need to allow
|
||||
/// two data points to have the same time. Thus I cannot use a single list of just strings nor
|
||||
/// a sorted dictionary of DateTimes and strings. </remarks>
|
||||
private void WriteFile(string filePath, IEnumerable<(DateTime, string)> data, DateTime date)
|
||||
private void WriteFile(string filePath, List<(DateTime, string)> data)
|
||||
{
|
||||
if (data == null || data.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Generate this csv entry name
|
||||
var entryName = LeanData.GenerateZipEntryName(_symbol, date, _resolution, _tickType);
|
||||
var entryName = LeanData.GenerateZipEntryName(_symbol, data[0].Item1, _resolution, _tickType);
|
||||
|
||||
// Check disk once for this file ahead of time, reuse where possible
|
||||
var fileExists = File.Exists(filePath);
|
||||
|
||||
@@ -20,7 +20,6 @@ using System.ComponentModel;
|
||||
using QuantConnect.Securities;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data.Consolidators;
|
||||
using QuantConnect.Data.Market;
|
||||
using static QuantConnect.StringExtensions;
|
||||
|
||||
namespace QuantConnect.Data
|
||||
@@ -30,6 +29,7 @@ namespace QuantConnect.Data
|
||||
/// </summary>
|
||||
public class SubscriptionDataConfig : IEquatable<SubscriptionDataConfig>
|
||||
{
|
||||
private readonly bool _mappedConfig;
|
||||
private readonly SecurityIdentifier _sid;
|
||||
|
||||
/// <summary>
|
||||
@@ -205,7 +205,8 @@ namespace QuantConnect.Data
|
||||
bool isFilteredSubscription = true,
|
||||
DataNormalizationMode dataNormalizationMode = DataNormalizationMode.Adjusted,
|
||||
DataMappingMode dataMappingMode = DataMappingMode.OpenInterest,
|
||||
uint contractDepthOffset = 0)
|
||||
uint contractDepthOffset = 0,
|
||||
bool mappedConfig = false)
|
||||
{
|
||||
if (objectType == null) throw new ArgumentNullException(nameof(objectType));
|
||||
if (symbol == null) throw new ArgumentNullException(nameof(symbol));
|
||||
@@ -222,6 +223,7 @@ namespace QuantConnect.Data
|
||||
IsInternalFeed = isInternalFeed;
|
||||
IsCustomData = isCustom;
|
||||
DataTimeZone = dataTimeZone;
|
||||
_mappedConfig = mappedConfig;
|
||||
DataMappingMode = dataMappingMode;
|
||||
ExchangeTimeZone = exchangeTimeZone;
|
||||
ContractDepthOffset = contractDepthOffset;
|
||||
@@ -276,6 +278,8 @@ namespace QuantConnect.Data
|
||||
/// <param name="dataMappingMode">The contract mapping mode to use for the security</param>
|
||||
/// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
|
||||
/// For example, 0 (default) will use the front month, 1 will use the back month contract</param>
|
||||
/// <param name="mappedConfig">True if this is created as a mapped config. This is useful for continuous contract at live trading
|
||||
/// where we subscribe to the mapped symbol but want to preserve uniqueness</param>
|
||||
public SubscriptionDataConfig(SubscriptionDataConfig config,
|
||||
Type objectType = null,
|
||||
Symbol symbol = null,
|
||||
@@ -290,7 +294,8 @@ namespace QuantConnect.Data
|
||||
bool? isFilteredSubscription = null,
|
||||
DataNormalizationMode? dataNormalizationMode = null,
|
||||
DataMappingMode? dataMappingMode = null,
|
||||
uint? contractDepthOffset = null)
|
||||
uint? contractDepthOffset = null,
|
||||
bool? mappedConfig = null)
|
||||
: this(
|
||||
objectType ?? config.Type,
|
||||
symbol ?? config.Symbol,
|
||||
@@ -305,7 +310,8 @@ namespace QuantConnect.Data
|
||||
isFilteredSubscription ?? config.IsFilteredSubscription,
|
||||
dataNormalizationMode ?? config.DataNormalizationMode,
|
||||
dataMappingMode ?? config.DataMappingMode,
|
||||
contractDepthOffset ?? config.ContractDepthOffset
|
||||
contractDepthOffset ?? config.ContractDepthOffset,
|
||||
mappedConfig ?? false
|
||||
)
|
||||
{
|
||||
PriceScaleFactor = config.PriceScaleFactor;
|
||||
@@ -335,7 +341,8 @@ namespace QuantConnect.Data
|
||||
&& DataMappingMode == other.DataMappingMode
|
||||
&& ExchangeTimeZone.Equals(other.ExchangeTimeZone)
|
||||
&& ContractDepthOffset == other.ContractDepthOffset
|
||||
&& IsFilteredSubscription == other.IsFilteredSubscription;
|
||||
&& IsFilteredSubscription == other.IsFilteredSubscription
|
||||
&& _mappedConfig == other._mappedConfig;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -376,6 +383,7 @@ namespace QuantConnect.Data
|
||||
hashCode = (hashCode*397) ^ ExchangeTimeZone.Id.GetHashCode();// timezone hash is expensive, use id instead
|
||||
hashCode = (hashCode*397) ^ ContractDepthOffset.GetHashCode();
|
||||
hashCode = (hashCode*397) ^ IsFilteredSubscription.GetHashCode();
|
||||
hashCode = (hashCode*397) ^ _mappedConfig.GetHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Data.UniverseSelection
|
||||
{
|
||||
|
||||
148
Common/Data/UniverseSelection/ContinuousContractUniverse.cs
Normal file
148
Common/Data/UniverseSelection/ContinuousContractUniverse.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Util;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Configuration;
|
||||
using QuantConnect.Data.Auxiliary;
|
||||
|
||||
namespace QuantConnect.Data.UniverseSelection
|
||||
{
|
||||
/// <summary>
|
||||
/// Continuous contract universe selection that based on the requested mapping mode will select each symbol
|
||||
/// </summary>
|
||||
public class ContinuousContractUniverse : Universe, ITimeTriggeredUniverse
|
||||
{
|
||||
private readonly IMapFileProvider _mapFileProvider;
|
||||
private readonly Security _security;
|
||||
private readonly bool _liveMode;
|
||||
private Symbol _currentSymbol;
|
||||
private string _mappedSymbol;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the settings used for subscriptions added for this universe
|
||||
/// </summary>
|
||||
public override UniverseSettings UniverseSettings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance
|
||||
/// </summary>
|
||||
public ContinuousContractUniverse(Security security, UniverseSettings universeSettings, bool liveMode, SubscriptionDataConfig universeConfig)
|
||||
: base(universeConfig)
|
||||
{
|
||||
_security = security;
|
||||
_liveMode = liveMode;
|
||||
UniverseSettings = universeSettings;
|
||||
var mapFileProviderTypeName = Config.Get("map-file-provider", "LocalDiskMapFileProvider");
|
||||
_mapFileProvider = Composer.Instance.GetExportedValueByTypeName<IMapFileProvider>(mapFileProviderTypeName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs universe selection based on the symbol mapping
|
||||
/// </summary>
|
||||
/// <param name="utcTime">The current utc time</param>
|
||||
/// <param name="data">Empty data</param>
|
||||
/// <returns>The symbols to use</returns>
|
||||
public override IEnumerable<Symbol> SelectSymbols(DateTime utcTime, BaseDataCollection data)
|
||||
{
|
||||
yield return _security.Symbol.Canonical;
|
||||
|
||||
var mapFile = _mapFileProvider.ResolveMapFile(new SubscriptionDataConfig(Configuration,
|
||||
dataMappingMode: UniverseSettings.DataMappingMode,
|
||||
symbol: _security.Symbol.Canonical));
|
||||
|
||||
var mappedSymbol = mapFile.GetMappedSymbol(utcTime.ConvertFromUtc(_security.Exchange.TimeZone));
|
||||
if (!string.IsNullOrEmpty(mappedSymbol) && mappedSymbol != _mappedSymbol)
|
||||
{
|
||||
if (_currentSymbol != null)
|
||||
{
|
||||
// let's emit the old and new for the mapping date
|
||||
yield return _currentSymbol;
|
||||
}
|
||||
_mappedSymbol = mappedSymbol;
|
||||
|
||||
_currentSymbol = _security.Symbol.Canonical
|
||||
.UpdateMappedSymbol(mappedSymbol, Configuration.ContractDepthOffset)
|
||||
.Underlying;
|
||||
}
|
||||
|
||||
if (_currentSymbol != null)
|
||||
{
|
||||
((IContinuousSecurity)_security).Mapped = _currentSymbol;
|
||||
yield return _currentSymbol;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the subscription requests to be added for the specified security
|
||||
/// </summary>
|
||||
/// <param name="security">The security to get subscriptions for</param>
|
||||
/// <param name="currentTimeUtc">The current time in utc. This is the frontier time of the algorithm</param>
|
||||
/// <param name="maximumEndTimeUtc">The max end time</param>
|
||||
/// <param name="subscriptionService">Instance which implements <see cref="ISubscriptionDataConfigService"/> interface</param>
|
||||
/// <returns>All subscriptions required by this security</returns>
|
||||
public override IEnumerable<SubscriptionRequest> GetSubscriptionRequests(Security security,
|
||||
DateTime currentTimeUtc,
|
||||
DateTime maximumEndTimeUtc,
|
||||
ISubscriptionDataConfigService subscriptionService)
|
||||
{
|
||||
var isInternal = !security.Symbol.IsCanonical();
|
||||
var result = subscriptionService.Add(security.Symbol,
|
||||
UniverseSettings.Resolution,
|
||||
UniverseSettings.FillForward,
|
||||
UniverseSettings.ExtendedMarketHours,
|
||||
dataNormalizationMode: UniverseSettings.DataNormalizationMode,
|
||||
subscriptionDataTypes: UniverseSettings.SubscriptionDataTypes,
|
||||
dataMappingMode: UniverseSettings.DataMappingMode,
|
||||
contractDepthOffset: (uint)Math.Abs(UniverseSettings.ContractDepthOffset),
|
||||
isInternalFeed: isInternal);
|
||||
return result.Select(config => new SubscriptionRequest(isUniverseSubscription: false,
|
||||
universe: this,
|
||||
security: security,
|
||||
configuration: new SubscriptionDataConfig(config, isInternalFeed: config.IsInternalFeed || config.TickType == TickType.OpenInterest),
|
||||
startTimeUtc: currentTimeUtc,
|
||||
endTimeUtc: maximumEndTimeUtc));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Each tradeable day of the future we trigger a new selection.
|
||||
/// Allows use to select the current contract
|
||||
/// </summary>
|
||||
public IEnumerable<DateTime> GetTriggerTimes(DateTime startTimeUtc, DateTime endTimeUtc, MarketHoursDatabase marketHoursDatabase)
|
||||
{
|
||||
var startTimeLocal = startTimeUtc.ConvertFromUtc(_security.Exchange.TimeZone);
|
||||
var endTimeLocal = endTimeUtc.ConvertFromUtc(_security.Exchange.TimeZone);
|
||||
|
||||
return Time.EachTradeableDay(_security, startTimeLocal, endTimeLocal)
|
||||
// in live trading we delay selection so that we make sure auxiliary data is ready
|
||||
.Select(time => _liveMode ? time.Add(Time.LiveAuxiliaryDataOffset) : time);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a continuous universe symbol
|
||||
/// </summary>
|
||||
/// <param name="symbol">The associated symbol</param>
|
||||
/// <returns>A symbol for a continuous universe of the specified symbol</returns>
|
||||
public static Symbol CreateSymbol(Symbol symbol)
|
||||
{
|
||||
var ticker = $"qc-universe-continuous-{symbol.ID.Market.ToLowerInvariant()}-{symbol.SecurityType}-{symbol.ID.Symbol}";
|
||||
return UniverseExtensions.CreateSymbol(symbol.SecurityType, symbol.ID.Market, ticker);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,16 +26,12 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
/// </summary>
|
||||
public class FineFundamentalUniverse : Universe
|
||||
{
|
||||
private readonly UniverseSettings _universeSettings;
|
||||
private readonly Func<IEnumerable<FineFundamental>, IEnumerable<Symbol>> _selector;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the settings used for subscriptons added for this universe
|
||||
/// Gets the settings used for subscriptions added for this universe
|
||||
/// </summary>
|
||||
public override UniverseSettings UniverseSettings
|
||||
{
|
||||
get { return _universeSettings; }
|
||||
}
|
||||
public override UniverseSettings UniverseSettings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FineFundamentalUniverse"/> class
|
||||
@@ -45,7 +41,7 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
public FineFundamentalUniverse(UniverseSettings universeSettings, Func<IEnumerable<FineFundamental>, IEnumerable<Symbol>> selector)
|
||||
: base(CreateConfiguration(FineFundamental.CreateUniverseSymbol(QuantConnect.Market.USA)))
|
||||
{
|
||||
_universeSettings = universeSettings;
|
||||
UniverseSettings = universeSettings;
|
||||
_selector = selector;
|
||||
}
|
||||
|
||||
@@ -58,7 +54,7 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
public FineFundamentalUniverse(Symbol symbol, UniverseSettings universeSettings, Func<IEnumerable<FineFundamental>, IEnumerable<Symbol>> selector)
|
||||
: base(CreateConfiguration(symbol))
|
||||
{
|
||||
_universeSettings = universeSettings;
|
||||
UniverseSettings = universeSettings;
|
||||
_selector = selector;
|
||||
}
|
||||
|
||||
|
||||
@@ -122,9 +122,10 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
/// </summary>
|
||||
/// <param name="utcTime">The current utc date time</param>
|
||||
/// <param name="security">The security to be added</param>
|
||||
/// <param name="isInternal">True if internal member</param>
|
||||
/// <returns>True if the security was successfully added,
|
||||
/// false if the security was already in the universe</returns>
|
||||
internal override bool AddMember(DateTime utcTime, Security security)
|
||||
internal override bool AddMember(DateTime utcTime, Security security, bool isInternal)
|
||||
{
|
||||
// never add members to disposed universes
|
||||
if (DisposeRequested)
|
||||
@@ -145,7 +146,7 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
Securities.TryRemove(security.Symbol, out member);
|
||||
}
|
||||
|
||||
var added = Securities.TryAdd(security.Symbol, new Member(utcTime, security));
|
||||
var added = Securities.TryAdd(security.Symbol, new Member(utcTime, security, isInternal));
|
||||
|
||||
if (added && _liveMode)
|
||||
{
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Util;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Data.UniverseSelection
|
||||
{
|
||||
@@ -28,15 +28,19 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
/// <summary>
|
||||
/// Gets an instance that represents no changes have been made
|
||||
/// </summary>
|
||||
public static readonly SecurityChanges None = new SecurityChanges(new List<Security>(), new List<Security>());
|
||||
public static readonly SecurityChanges None = new (Enumerable.Empty<Security>(), Enumerable.Empty<Security>(),
|
||||
Enumerable.Empty<Security>(), Enumerable.Empty<Security>());
|
||||
|
||||
private readonly HashSet<Security> _addedSecurities;
|
||||
private readonly HashSet<Security> _removedSecurities;
|
||||
private readonly IReadOnlySet<Security> _addedSecurities;
|
||||
private readonly IReadOnlySet<Security> _removedSecurities;
|
||||
private readonly IReadOnlySet<Security> _internalAddedSecurities;
|
||||
private readonly IReadOnlySet<Security> _internalRemovedSecurities;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total count of added and removed securities
|
||||
/// </summary>
|
||||
public int Count => _addedSecurities.Count + _removedSecurities.Count;
|
||||
public int Count => _addedSecurities.Count + _removedSecurities.Count
|
||||
+ _internalAddedSecurities.Count + _internalRemovedSecurities.Count;
|
||||
|
||||
/// <summary>
|
||||
/// True will filter out custom securities from the
|
||||
@@ -46,20 +50,23 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
/// the filtering if desired</remarks>
|
||||
public bool FilterCustomSecurities { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True will filter out internal securities from the
|
||||
/// <see cref="AddedSecurities"/> and <see cref="RemovedSecurities"/> properties
|
||||
/// </summary>
|
||||
/// <remarks>This allows us to filter but also to disable
|
||||
/// the filtering if desired</remarks>
|
||||
public bool FilterInternalSecurities { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the symbols that were added by universe selection
|
||||
/// </summary>
|
||||
/// <remarks>Will use <see cref="FilterCustomSecurities"/> value
|
||||
/// to determine if custom securities should be filtered</remarks>
|
||||
public IReadOnlyList<Security> AddedSecurities
|
||||
{
|
||||
get
|
||||
{
|
||||
return _addedSecurities.OrderBy(x => x.Symbol.Value)
|
||||
.Where(security => !FilterCustomSecurities || security.Type != SecurityType.Base)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
/// <remarks>Will use <see cref="FilterInternalSecurities"/> value
|
||||
/// to determine if internal securities should be filtered</remarks>
|
||||
public IReadOnlyList<Security> AddedSecurities => GetFilteredList(_addedSecurities,
|
||||
!FilterInternalSecurities ? _internalAddedSecurities : null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the symbols that were removed by universe selection. This list may
|
||||
@@ -68,25 +75,25 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
/// </summary>
|
||||
/// <remarks>Will use <see cref="FilterCustomSecurities"/> value
|
||||
/// to determine if custom securities should be filtered</remarks>
|
||||
public IReadOnlyList<Security> RemovedSecurities
|
||||
{
|
||||
get
|
||||
{
|
||||
return _removedSecurities.OrderBy(x => x.Symbol.Value)
|
||||
.Where(security => !FilterCustomSecurities || security.Type != SecurityType.Base)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
/// <remarks>Will use <see cref="FilterInternalSecurities"/> value
|
||||
/// to determine if internal securities should be filtered</remarks>
|
||||
public IReadOnlyList<Security> RemovedSecurities => GetFilteredList(_removedSecurities,
|
||||
!FilterInternalSecurities ? _internalRemovedSecurities : null);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SecurityChanges"/> class
|
||||
/// </summary>
|
||||
/// <param name="addedSecurities">Added symbols list</param>
|
||||
/// <param name="removedSecurities">Removed symbols list</param>
|
||||
public SecurityChanges(IEnumerable<Security> addedSecurities, IEnumerable<Security> removedSecurities)
|
||||
/// <param name="additions">Added symbols list</param>
|
||||
/// <param name="removals">Removed symbols list</param>
|
||||
/// <param name="internalAdditions">Internal added symbols list</param>
|
||||
/// <param name="internalRemovals">Internal removed symbols list</param>
|
||||
private SecurityChanges(IEnumerable<Security> additions, IEnumerable<Security> removals,
|
||||
IEnumerable<Security> internalAdditions, IEnumerable<Security> internalRemovals)
|
||||
{
|
||||
_addedSecurities = addedSecurities.ToHashSet();
|
||||
_removedSecurities = removedSecurities.ToHashSet();
|
||||
_addedSecurities = additions.ToHashSet();
|
||||
_removedSecurities = removals.ToHashSet();
|
||||
_internalAddedSecurities = internalAdditions.ToHashSet();
|
||||
_internalRemovedSecurities = internalRemovals.ToHashSet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -98,28 +105,8 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
{
|
||||
_addedSecurities = changes._addedSecurities;
|
||||
_removedSecurities = changes._removedSecurities;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new instance of <see cref="SecurityChanges"/> with the specified securities marked as added
|
||||
/// </summary>
|
||||
/// <param name="securities">The added securities</param>
|
||||
/// <returns>A new security changes instance with the specified securities marked as added</returns>
|
||||
public static SecurityChanges Added(params Security[] securities)
|
||||
{
|
||||
if (securities == null || securities.Length == 0) return None;
|
||||
return new SecurityChanges(securities.ToList(), new List<Security>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new instance of <see cref="SecurityChanges"/> with the specified securities marked as removed
|
||||
/// </summary>
|
||||
/// <param name="securities">The removed securities</param>
|
||||
/// <returns>A new security changes instance with the specified securities marked as removed</returns>
|
||||
public static SecurityChanges Removed(params Security[] securities)
|
||||
{
|
||||
if (securities == null || securities.Length == 0) return None;
|
||||
return new SecurityChanges(new List<Security>(), securities.ToList());
|
||||
_internalAddedSecurities = changes._internalAddedSecurities;
|
||||
_internalRemovedSecurities = changes._internalRemovedSecurities;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -127,17 +114,39 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
/// </summary>
|
||||
/// <param name="left">The left side of the operand</param>
|
||||
/// <param name="right">The right side of the operand</param>
|
||||
/// <returns>Adds the additions together and removes any removals found in the additions, that is, additions take precendence</returns>
|
||||
/// <returns>Adds the additions together and removes any removals found in the additions, that is, additions take precedence</returns>
|
||||
public static SecurityChanges operator +(SecurityChanges left, SecurityChanges right)
|
||||
{
|
||||
// common case is adding something to nothing, shortcut these to prevent linqness
|
||||
if (left == None) return right;
|
||||
if (right == None) return left;
|
||||
if (left == None || left.Count == 0) return right;
|
||||
if (right == None || right.Count == 0) return left;
|
||||
|
||||
// perf: no need to use Union here, SecurityChanges.Constructor will use hashset
|
||||
var additions = left.AddedSecurities.Concat(right.AddedSecurities).ToHashSet();
|
||||
var removals = left.RemovedSecurities.Concat(right.RemovedSecurities).Where(x => !additions.Contains(x));
|
||||
return new SecurityChanges(additions, removals);
|
||||
var additions = Merge(left._addedSecurities, right._addedSecurities);
|
||||
var internalAdditions = Merge(left._internalAddedSecurities, right._internalAddedSecurities);
|
||||
|
||||
var removals = Merge(left._removedSecurities, right._removedSecurities,
|
||||
security => !additions.Contains(security) && !internalAdditions.Contains(security));
|
||||
var internalRemovals = Merge(left._internalRemovedSecurities, right._internalRemovedSecurities,
|
||||
security => !additions.Contains(security) && !internalAdditions.Contains(security));
|
||||
|
||||
return new SecurityChanges(additions, removals, internalAdditions, internalRemovals);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SecurityChanges"/> class all none internal
|
||||
/// </summary>
|
||||
/// <param name="additions">Added symbols list</param>
|
||||
/// <param name="removals">Removed symbols list</param>
|
||||
/// <param name="internalAdditions">Internal added symbols list</param>
|
||||
/// <param name="internalRemovals">Internal removed symbols list</param>
|
||||
/// <remarks>Useful for testing</remarks>
|
||||
public static SecurityChanges Create(IReadOnlyCollection<Security> additions, IReadOnlyCollection<Security> removals,
|
||||
IReadOnlyCollection<Security> internalAdditions, IReadOnlyCollection<Security> internalRemovals)
|
||||
{
|
||||
// return None if there's no changes, otherwise return what we've modified
|
||||
return additions?.Count + removals?.Count + internalAdditions?.Count + internalRemovals?.Count > 0
|
||||
? new SecurityChanges(additions, removals, internalAdditions, internalRemovals)
|
||||
: None;
|
||||
}
|
||||
|
||||
#region Overrides of Object
|
||||
@@ -171,5 +180,106 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to filter added and removed securities based on current settings
|
||||
/// </summary>
|
||||
private IReadOnlyList<Security> GetFilteredList(IEnumerable<Security> source, IEnumerable<Security> secondSource = null)
|
||||
{
|
||||
if (secondSource != null)
|
||||
{
|
||||
source = source.Union(secondSource);
|
||||
}
|
||||
return source.Where(kvp => !FilterCustomSecurities || kvp.Type != SecurityType.Base)
|
||||
.Select(kvp => kvp)
|
||||
.OrderBy(security => security.Symbol.Value)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method that will merge two security sets, taken into account an optional filter
|
||||
/// </summary>
|
||||
/// <returns>Will return merged set</returns>
|
||||
private static HashSet<Security> Merge(IReadOnlyCollection<Security> left, IReadOnlyCollection<Security> right, Func<Security, bool> filter = null)
|
||||
{
|
||||
// if right is emtpy we just use left
|
||||
IEnumerable<Security> result = left;
|
||||
if (right.Count != 0)
|
||||
{
|
||||
if (left.Count == 0)
|
||||
{
|
||||
// left is emtpy so let's just use right
|
||||
result = right;
|
||||
}
|
||||
else
|
||||
{
|
||||
// merge, both are not empty
|
||||
result = result.Concat(right);
|
||||
}
|
||||
}
|
||||
|
||||
if (filter != null)
|
||||
{
|
||||
result = result.Where(filter.Invoke);
|
||||
}
|
||||
|
||||
return new HashSet<Security>(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create security changes
|
||||
/// </summary>
|
||||
public class SecurityChangesConstructor
|
||||
{
|
||||
private readonly List<Security> _internalAdditions = new();
|
||||
private readonly List<Security> _internalRemovals = new();
|
||||
private readonly List<Security> _additions = new();
|
||||
private readonly List<Security> _removals = new();
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a security addition change
|
||||
/// </summary>
|
||||
public void Add(Security security, bool isInternal)
|
||||
{
|
||||
if (isInternal)
|
||||
{
|
||||
_internalAdditions.Add(security);
|
||||
}
|
||||
else
|
||||
{
|
||||
_additions.Add(security);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a security removal change
|
||||
/// </summary>
|
||||
public void Remove(Security security, bool isInternal)
|
||||
{
|
||||
if (isInternal)
|
||||
{
|
||||
_internalRemovals.Add(security);
|
||||
}
|
||||
else
|
||||
{
|
||||
_removals.Add(security);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current security changes clearing state
|
||||
/// </summary>
|
||||
public SecurityChanges Flush()
|
||||
{
|
||||
var result = SecurityChanges.Create(_additions, _removals, _internalAdditions, _internalRemovals);
|
||||
|
||||
_internalAdditions.Clear();
|
||||
_removals.Clear();
|
||||
_internalRemovals.Clear();
|
||||
_additions.Clear();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,9 +277,10 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
/// </summary>
|
||||
/// <param name="utcTime">The current utc date time</param>
|
||||
/// <param name="security">The security to be added</param>
|
||||
/// <param name="isInternal">True if internal member</param>
|
||||
/// <returns>True if the security was successfully added,
|
||||
/// false if the security was already in the universe</returns>
|
||||
internal virtual bool AddMember(DateTime utcTime, Security security)
|
||||
internal virtual bool AddMember(DateTime utcTime, Security security, bool isInternal)
|
||||
{
|
||||
// never add members to disposed universes
|
||||
if (DisposeRequested)
|
||||
@@ -292,7 +293,7 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
return false;
|
||||
}
|
||||
|
||||
return Securities.TryAdd(security.Symbol, new Member(utcTime, security));
|
||||
return Securities.TryAdd(security.Symbol, new Member(utcTime, security, isInternal));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -386,15 +387,22 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
/// </summary>
|
||||
public readonly Security Security;
|
||||
|
||||
/// <summary>
|
||||
/// True if the security was added as internal by this universe
|
||||
/// </summary>
|
||||
public readonly bool IsInternal;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize a new member for the universe
|
||||
/// </summary>
|
||||
/// <param name="added">DateTime added</param>
|
||||
/// <param name="security">Security to add</param>
|
||||
public Member(DateTime added, Security security)
|
||||
/// <param name="isInternal">True if internal member</param>
|
||||
public Member(DateTime added, Security security, bool isInternal)
|
||||
{
|
||||
Added = added;
|
||||
Security = security;
|
||||
IsInternal = isInternal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Data.UniverseSelection
|
||||
@@ -72,5 +73,68 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
return second.SelectSymbols(utcTime, clone);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe symbol
|
||||
/// </summary>
|
||||
/// <param name="securityType">The security</param>
|
||||
/// <param name="market">The market</param>
|
||||
/// <param name="ticker">The Universe ticker</param>
|
||||
/// <returns>A symbol for user defined universe of the specified security type and market</returns>
|
||||
public static Symbol CreateSymbol(SecurityType securityType, string market, string ticker)
|
||||
{
|
||||
SecurityIdentifier sid;
|
||||
switch (securityType)
|
||||
{
|
||||
case SecurityType.Base:
|
||||
sid = SecurityIdentifier.GenerateBase(null, ticker, market);
|
||||
break;
|
||||
|
||||
case SecurityType.Equity:
|
||||
sid = SecurityIdentifier.GenerateEquity(SecurityIdentifier.DefaultDate, ticker, market);
|
||||
break;
|
||||
|
||||
case SecurityType.Option:
|
||||
var underlying = SecurityIdentifier.GenerateEquity(SecurityIdentifier.DefaultDate, ticker, market);
|
||||
sid = SecurityIdentifier.GenerateOption(SecurityIdentifier.DefaultDate, underlying, market, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case SecurityType.FutureOption:
|
||||
var underlyingFuture = SecurityIdentifier.GenerateFuture(SecurityIdentifier.DefaultDate, ticker, market);
|
||||
sid = SecurityIdentifier.GenerateOption(SecurityIdentifier.DefaultDate, underlyingFuture, market, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case SecurityType.IndexOption:
|
||||
var underlyingIndex = SecurityIdentifier.GenerateIndex(ticker, market);
|
||||
sid = SecurityIdentifier.GenerateOption(SecurityIdentifier.DefaultDate, underlyingIndex, market, 0, 0, OptionStyle.European);
|
||||
break;
|
||||
|
||||
case SecurityType.Forex:
|
||||
sid = SecurityIdentifier.GenerateForex(ticker, market);
|
||||
break;
|
||||
|
||||
case SecurityType.Cfd:
|
||||
sid = SecurityIdentifier.GenerateCfd(ticker, market);
|
||||
break;
|
||||
|
||||
case SecurityType.Index:
|
||||
sid = SecurityIdentifier.GenerateIndex(ticker, market);
|
||||
break;
|
||||
|
||||
case SecurityType.Future:
|
||||
sid = SecurityIdentifier.GenerateFuture(SecurityIdentifier.DefaultDate, ticker, market);
|
||||
break;
|
||||
|
||||
case SecurityType.Crypto:
|
||||
sid = SecurityIdentifier.GenerateCrypto(ticker, market);
|
||||
break;
|
||||
|
||||
case SecurityType.Commodity:
|
||||
default:
|
||||
throw new NotImplementedException($"The specified security type is not implemented yet: {securityType}");
|
||||
}
|
||||
|
||||
return new Symbol(sid, ticker);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,58 +110,7 @@ namespace QuantConnect.Data.UniverseSelection
|
||||
public static Symbol CreateSymbol(SecurityType securityType, string market)
|
||||
{
|
||||
var ticker = $"qc-universe-userdefined-{market.ToLowerInvariant()}-{securityType}";
|
||||
SecurityIdentifier sid;
|
||||
switch (securityType)
|
||||
{
|
||||
case SecurityType.Base:
|
||||
sid = SecurityIdentifier.GenerateBase(null, ticker, market);
|
||||
break;
|
||||
|
||||
case SecurityType.Equity:
|
||||
sid = SecurityIdentifier.GenerateEquity(SecurityIdentifier.DefaultDate, ticker, market);
|
||||
break;
|
||||
|
||||
case SecurityType.Option:
|
||||
var underlying = SecurityIdentifier.GenerateEquity(SecurityIdentifier.DefaultDate, ticker, market);
|
||||
sid = SecurityIdentifier.GenerateOption(SecurityIdentifier.DefaultDate, underlying, market, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case SecurityType.FutureOption:
|
||||
var underlyingFuture = SecurityIdentifier.GenerateFuture(SecurityIdentifier.DefaultDate, ticker, market);
|
||||
sid = SecurityIdentifier.GenerateOption(SecurityIdentifier.DefaultDate, underlyingFuture, market, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case SecurityType.IndexOption:
|
||||
var underlyingIndex = SecurityIdentifier.GenerateIndex(ticker, market);
|
||||
sid = SecurityIdentifier.GenerateOption(SecurityIdentifier.DefaultDate, underlyingIndex, market, 0, 0, OptionStyle.European);
|
||||
break;
|
||||
|
||||
case SecurityType.Forex:
|
||||
sid = SecurityIdentifier.GenerateForex(ticker, market);
|
||||
break;
|
||||
|
||||
case SecurityType.Cfd:
|
||||
sid = SecurityIdentifier.GenerateCfd(ticker, market);
|
||||
break;
|
||||
|
||||
case SecurityType.Index:
|
||||
sid = SecurityIdentifier.GenerateIndex(ticker, market);
|
||||
break;
|
||||
|
||||
case SecurityType.Future:
|
||||
sid = SecurityIdentifier.GenerateFuture(SecurityIdentifier.DefaultDate, ticker, market);
|
||||
break;
|
||||
|
||||
case SecurityType.Crypto:
|
||||
sid = SecurityIdentifier.GenerateCrypto(ticker, market);
|
||||
break;
|
||||
|
||||
case SecurityType.Commodity:
|
||||
default:
|
||||
throw new NotImplementedException($"The specified security type is not implemented yet: {securityType}");
|
||||
}
|
||||
|
||||
return new Symbol(sid, ticker);
|
||||
return UniverseExtensions.CreateSymbol(securityType, market, ticker);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
86
Common/DocumentationAttribute.cs
Normal file
86
Common/DocumentationAttribute.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using System.Reflection;
|
||||
|
||||
namespace QuantConnect
|
||||
{
|
||||
/// <summary>
|
||||
/// Custom attribute used for documentation
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
|
||||
[DocumentationAttribute("Reference")]
|
||||
public sealed class DocumentationAttribute : Attribute
|
||||
{
|
||||
private static readonly DocumentationAttribute Attribute =
|
||||
typeof(DocumentationAttribute).GetCustomAttributes<DocumentationAttribute>().Single();
|
||||
private static readonly string BasePath =
|
||||
Attribute.FileName.Substring(0, Attribute.FileName.LastIndexOf("Common", StringComparison.Ordinal));
|
||||
|
||||
/// <summary>
|
||||
/// The documentation tag
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "tag")]
|
||||
public string Tag { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The associated weight of this attribute and tag
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "weight")]
|
||||
public int Weight { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The associated line of this attribute
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "line")]
|
||||
public int Line { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The associated file name of this attribute
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "fileName")]
|
||||
public string FileName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The attributes type id, we override it to ignore it when serializing
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public override object TypeId => base.TypeId;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance
|
||||
/// </summary>
|
||||
public DocumentationAttribute(string tag, int weight = 0,
|
||||
[System.Runtime.CompilerServices.CallerLineNumber] int line = 0,
|
||||
[System.Runtime.CompilerServices.CallerFilePath] string fileName = "")
|
||||
{
|
||||
Tag = tag;
|
||||
Line = line;
|
||||
Weight = weight;
|
||||
// will be null for the attribute of DocumentationAttribute itself
|
||||
if (BasePath != null)
|
||||
{
|
||||
FileName = fileName.Replace(BasePath, string.Empty, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileName = fileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,6 +151,25 @@ namespace QuantConnect
|
||||
return marketHoursDatabase.GetEntry(symbol.ID.Market, symbol, symbol.ID.SecurityType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to deserialize a json array into a list also handling single json values
|
||||
/// </summary>
|
||||
/// <param name="jsonArray">The value to deserialize</param>
|
||||
public static List<string> DeserializeList(this string jsonArray)
|
||||
{
|
||||
List<string> result = new();
|
||||
try
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<string>>(jsonArray);
|
||||
}
|
||||
catch(JsonReaderException)
|
||||
{
|
||||
result.Add(jsonArray);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to download a provided url as a string
|
||||
/// </summary>
|
||||
@@ -1335,6 +1354,26 @@ namespace QuantConnect
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to determine if a data type implements the Stream reader method
|
||||
/// </summary>
|
||||
public static bool ImplementsStreamReader(this Type baseDataType)
|
||||
{
|
||||
// we know these type implement the streamReader interface lets avoid dynamic reflection call to figure it out
|
||||
if (baseDataType == typeof(TradeBar) || baseDataType == typeof(QuoteBar) || baseDataType == typeof(Tick))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var method = baseDataType.GetMethod("Reader",
|
||||
new[] { typeof(SubscriptionDataConfig), typeof(StreamReader), typeof(DateTime), typeof(bool) });
|
||||
if (method != null && method.DeclaringType == baseDataType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Breaks the specified string into csv components, all commas are considered separators
|
||||
/// </summary>
|
||||
@@ -2921,6 +2960,21 @@ namespace QuantConnect
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to determine symbol for a live subscription
|
||||
/// </summary>
|
||||
/// <remarks>Useful for continuous futures where we subscribe to the underlying</remarks>
|
||||
public static bool TryGetLiveSubscriptionSymbol(this Symbol symbol, out Symbol mapped)
|
||||
{
|
||||
mapped = null;
|
||||
if (symbol.SecurityType == SecurityType.Future && symbol.IsCanonical() && symbol.HasUnderlying)
|
||||
{
|
||||
mapped = symbol.Underlying;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the delisting date for the provided Symbol
|
||||
/// </summary>
|
||||
@@ -2987,6 +3041,35 @@ namespace QuantConnect
|
||||
return symbol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to unsubscribe a given configuration, handling any required mapping
|
||||
/// </summary>
|
||||
public static void UnsubscribeWithMapping(this IDataQueueHandler dataQueueHandler, SubscriptionDataConfig dataConfig)
|
||||
{
|
||||
if (dataConfig.Symbol.TryGetLiveSubscriptionSymbol(out var mappedSymbol))
|
||||
{
|
||||
dataConfig = new SubscriptionDataConfig(dataConfig, symbol: mappedSymbol, mappedConfig: true);
|
||||
}
|
||||
dataQueueHandler.Unsubscribe(dataConfig);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to subscribe a given configuration, handling any required mapping
|
||||
/// </summary>
|
||||
public static IEnumerator<BaseData> SubscribeWithMapping(this IDataQueueHandler dataQueueHandler,
|
||||
SubscriptionDataConfig dataConfig,
|
||||
EventHandler newDataAvailableHandler,
|
||||
out SubscriptionDataConfig subscribedConfig)
|
||||
{
|
||||
subscribedConfig = dataConfig;
|
||||
if (dataConfig.Symbol.TryGetLiveSubscriptionSymbol(out var mappedSymbol))
|
||||
{
|
||||
subscribedConfig = new SubscriptionDataConfig(dataConfig, symbol: mappedSymbol, mappedConfig: true);
|
||||
}
|
||||
var enumerator = dataQueueHandler.Subscribe(subscribedConfig, newDataAvailableHandler);
|
||||
return enumerator ?? Enumerable.Empty<BaseData>().GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to stream read lines from a file
|
||||
/// </summary>
|
||||
@@ -3003,10 +3086,16 @@ namespace QuantConnect
|
||||
|
||||
using (var streamReader = new StreamReader(stream))
|
||||
{
|
||||
while (!streamReader.EndOfStream)
|
||||
string line;
|
||||
do
|
||||
{
|
||||
yield return streamReader.ReadLine();
|
||||
line = streamReader.ReadLine();
|
||||
if (line != null)
|
||||
{
|
||||
yield return line;
|
||||
}
|
||||
}
|
||||
while (line != null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3138,6 +3227,41 @@ namespace QuantConnect
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Thread safe concurrent dictionary order by implementation by using <see cref="SafeEnumeration{TSource,TKey}"/>
|
||||
/// </summary>
|
||||
/// <remarks>See https://stackoverflow.com/questions/47630824/is-c-sharp-linq-orderby-threadsafe-when-used-with-concurrentdictionarytkey-tva</remarks>
|
||||
public static IOrderedEnumerable<KeyValuePair<TSource, TKey>> OrderBySafe<TSource, TKey>(
|
||||
this ConcurrentDictionary<TSource, TKey> source, Func<KeyValuePair<TSource, TKey>, TSource> keySelector
|
||||
)
|
||||
{
|
||||
return source.SafeEnumeration().OrderBy(keySelector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Thread safe concurrent dictionary order by implementation by using <see cref="SafeEnumeration{TSource,TKey}"/>
|
||||
/// </summary>
|
||||
/// <remarks>See https://stackoverflow.com/questions/47630824/is-c-sharp-linq-orderby-threadsafe-when-used-with-concurrentdictionarytkey-tva</remarks>
|
||||
public static IOrderedEnumerable<KeyValuePair<TSource, TKey>> OrderBySafe<TSource, TKey>(
|
||||
this ConcurrentDictionary<TSource, TKey> source, Func<KeyValuePair<TSource, TKey>, TKey> keySelector
|
||||
)
|
||||
{
|
||||
return source.SafeEnumeration().OrderBy(keySelector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Force concurrent dictionary enumeration using a thread safe implementation
|
||||
/// </summary>
|
||||
/// <remarks>See https://stackoverflow.com/questions/47630824/is-c-sharp-linq-orderby-threadsafe-when-used-with-concurrentdictionarytkey-tva</remarks>
|
||||
public static IEnumerable<KeyValuePair<TSource, TKey>> SafeEnumeration<TSource, TKey>(
|
||||
this ConcurrentDictionary<TSource, TKey> source)
|
||||
{
|
||||
foreach (var kvp in source)
|
||||
{
|
||||
yield return kvp;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to determine the right data normalization mode to use by default
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
@@ -725,29 +725,6 @@ namespace QuantConnect
|
||||
return exchange.GetPrimaryExchange(securityType, market).Code;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the exchange as single character representation.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[Obsolete("This overload has not enough information to determine the exchange. " +
|
||||
"Please use overload expecting a SecurityType and Market")]
|
||||
public static string GetPrimaryExchangeAsSingleCharacter(this string exchange)
|
||||
{
|
||||
return exchange.GetPrimaryExchange().Code;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the main Exchange from the single character encoding.
|
||||
/// </summary>
|
||||
/// <param name="exchange"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("This overload has not enough information to determine the exchange. " +
|
||||
"Please use overload expecting a string, SecurityType and Market")]
|
||||
public static Exchange GetPrimaryExchange(char exchange)
|
||||
{
|
||||
return exchange.ToString().GetPrimaryExchange();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the exchange as PrimaryExchange object.
|
||||
/// </summary>
|
||||
|
||||
@@ -18,6 +18,9 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using QuantConnect.Api;
|
||||
using QuantConnect.Optimizer.Objectives;
|
||||
using QuantConnect.Optimizer.Parameters;
|
||||
using QuantConnect.Statistics;
|
||||
|
||||
namespace QuantConnect.Interfaces
|
||||
{
|
||||
@@ -169,6 +172,96 @@ namespace QuantConnect.Interfaces
|
||||
/// <returns>BacktestList container for list of backtests</returns>
|
||||
BacktestList ListBacktests(int projectId);
|
||||
|
||||
/// <summary>
|
||||
/// Estimate optimization with the specified parameters via QuantConnect.com API
|
||||
/// </summary>
|
||||
/// <param name="projectId">Project ID of the project the optimization belongs to</param>
|
||||
/// <param name="name">Name of the optimization</param>
|
||||
/// <param name="target">Target of the optimization, see examples in <see cref="PortfolioStatistics"/></param>
|
||||
/// <param name="targetTo">Target extremum of the optimization, for example "max" or "min"</param>
|
||||
/// <param name="targetValue">Optimization target value</param>
|
||||
/// <param name="strategy">Optimization strategy, <see cref="GridSearchOptimizationStrategy"/></param>
|
||||
/// <param name="compileId">Optimization compile ID</param>
|
||||
/// <param name="parameters">Optimization parameters</param>
|
||||
/// <param name="constraints">Optimization constraints</param>
|
||||
/// <returns>Estimate object from the API.</returns>
|
||||
public Estimate EstimateOptimization(
|
||||
int projectId,
|
||||
string name,
|
||||
string target,
|
||||
string targetTo,
|
||||
decimal? targetValue,
|
||||
string strategy,
|
||||
string compileId,
|
||||
HashSet<OptimizationParameter> parameters,
|
||||
IReadOnlyList<Constraint> constraints);
|
||||
|
||||
/// <summary>
|
||||
/// Create an optimization with the specified parameters via QuantConnect.com API
|
||||
/// </summary>
|
||||
/// <param name="projectId">Project ID of the project the optimization belongs to</param>
|
||||
/// <param name="name">Name of the optimization</param>
|
||||
/// <param name="target">Target of the optimization, see examples in <see cref="PortfolioStatistics"/></param>
|
||||
/// <param name="targetTo">Target extremum of the optimization, for example "max" or "min"</param>
|
||||
/// <param name="targetValue">Optimization target value</param>
|
||||
/// <param name="strategy">Optimization strategy, <see cref="GridSearchOptimizationStrategy"/></param>
|
||||
/// <param name="compileId">Optimization compile ID</param>
|
||||
/// <param name="parameters">Optimization parameters</param>
|
||||
/// <param name="constraints">Optimization constraints</param>
|
||||
/// <param name="estimatedCost">Estimated cost for optimization</param>
|
||||
/// <param name="nodeType">Optimization node type</param>
|
||||
/// <param name="parallelNodes">Number of parallel nodes for optimization</param>
|
||||
/// <returns>BaseOptimization object from the API.</returns>
|
||||
public BaseOptimization CreateOptimization(
|
||||
int projectId,
|
||||
string name,
|
||||
string target,
|
||||
string targetTo,
|
||||
decimal? targetValue,
|
||||
string strategy,
|
||||
string compileId,
|
||||
HashSet<OptimizationParameter> parameters,
|
||||
IReadOnlyList<Constraint> constraints,
|
||||
decimal estimatedCost,
|
||||
string nodeType,
|
||||
int parallelNodes);
|
||||
|
||||
/// <summary>
|
||||
/// List all the optimizations for a project
|
||||
/// </summary>
|
||||
/// <param name="projectId">Project id we'd like to get a list of optimizations for</param>
|
||||
/// <returns>A list of BaseOptimization objects, <see cref="BaseOptimization"/></returns>
|
||||
public List<BaseOptimization> ListOptimizations(int projectId);
|
||||
|
||||
/// <summary>
|
||||
/// Read an optimization
|
||||
/// </summary>
|
||||
/// <param name="optimizationId">Optimization id for the optimization we want to read</param>
|
||||
/// <returns><see cref="Optimization"/></returns>
|
||||
public Optimization ReadOptimization(string optimizationId);
|
||||
|
||||
/// <summary>
|
||||
/// Abort an optimization
|
||||
/// </summary>
|
||||
/// <param name="optimizationId">Optimization id for the optimization we want to abort</param>
|
||||
/// <returns><see cref="RestResponse"/></returns>
|
||||
public RestResponse AbortOptimization(string optimizationId);
|
||||
|
||||
/// <summary>
|
||||
/// Update an optimization
|
||||
/// </summary>
|
||||
/// <param name="optimizationId">Optimization id we want to update</param>
|
||||
/// <param name="name">Name we'd like to assign to the optimization</param>
|
||||
/// <returns><see cref="RestResponse"/></returns>
|
||||
public RestResponse UpdateOptimization(string optimizationId, string name = null);
|
||||
|
||||
/// <summary>
|
||||
/// Delete an optimization
|
||||
/// </summary>
|
||||
/// <param name="optimizationId">Optimization id for the optimization we want to delete</param>
|
||||
/// <returns><see cref="RestResponse"/></returns>
|
||||
public RestResponse DeleteOptimization(string optimizationId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the logs of a specific live algorithm
|
||||
/// </summary>
|
||||
@@ -187,6 +280,25 @@ namespace QuantConnect.Interfaces
|
||||
/// <returns>Link to the downloadable data.</returns>
|
||||
DataLink ReadDataLink(string filePath, string organizationId);
|
||||
|
||||
/// <summary>
|
||||
/// Get valid data entries for a given filepath from data/list
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
DataList ReadDataDirectory(string filePath);
|
||||
|
||||
/// <summary>
|
||||
/// Gets data prices from data/prices
|
||||
/// </summary>
|
||||
public DataPricesList ReadDataPrices(string organizationId);
|
||||
|
||||
/// <summary>
|
||||
/// Read out the report of a backtest in the project id specified.
|
||||
/// </summary>
|
||||
/// <param name="projectId">Project id to read</param>
|
||||
/// <param name="backtestId">Specific backtest id to read</param>
|
||||
/// <returns><see cref="BacktestReport"/></returns>
|
||||
public BacktestReport ReadBacktestReport(int projectId, string backtestId);
|
||||
|
||||
/// <summary>
|
||||
/// Method to download and save the data purchased through QuantConnect
|
||||
/// </summary>
|
||||
@@ -194,6 +306,69 @@ namespace QuantConnect.Interfaces
|
||||
/// <returns>A bool indicating whether the data was successfully downloaded or not.</returns>
|
||||
bool DownloadData(string filePath, string organizationId);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new node in the organization, node configuration is defined by the
|
||||
/// <see cref="SKU"/>
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the new node</param>
|
||||
/// <param name="organizationId">ID of the organization</param>
|
||||
/// <param name="sku"><see cref="SKU"/> Object representing configuration</param>
|
||||
/// <returns>Returns <see cref="CreatedNode"/> which contains API response and
|
||||
/// <see cref="Node"/></returns>
|
||||
public CreatedNode CreateNode(string name, string organizationId, SKU sku);
|
||||
|
||||
/// <summary>
|
||||
/// Reads the nodes associated with the organization, creating a
|
||||
/// <see cref="NodeList"/> for the response
|
||||
/// </summary>
|
||||
/// <param name="organizationId">ID of the organization</param>
|
||||
/// <returns><see cref="NodeList"/> containing Backtest, Research, and Live Nodes</returns>
|
||||
public NodeList ReadNodes(string organizationId);
|
||||
|
||||
/// <summary>
|
||||
/// Update an organizations node with a new name
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node ID of the node you want to update</param>
|
||||
/// <param name="newName">The new name for that node</param>
|
||||
/// <param name="organizationId">ID of the organization</param>
|
||||
/// <returns><see cref="RestResponse"/> containing success response and errors</returns>
|
||||
public RestResponse UpdateNode(string nodeId, string newName, string organizationId);
|
||||
|
||||
/// <summary>
|
||||
/// Delete a node from an organization, requires node ID.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node ID of the node you want to delete</param>
|
||||
/// <param name="organizationId">ID of the organization</param>
|
||||
/// <returns><see cref="RestResponse"/> containing success response and errors</returns>
|
||||
public RestResponse DeleteNode(string nodeId, string organizationId);
|
||||
|
||||
/// <summary>
|
||||
/// Stop a running node in a organization
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node ID of the node you want to stop</param>
|
||||
/// <param name="organizationId">ID of the organization</param>
|
||||
/// <returns><see cref="RestResponse"/> containing success response and errors</returns>
|
||||
public RestResponse StopNode(string nodeId, string organizationId);
|
||||
|
||||
/// <summary>
|
||||
/// Will read the organization account status
|
||||
/// </summary>
|
||||
/// <param name="organizationId">The target organization id, if null will return default organization</param>
|
||||
public Account ReadAccount(string organizationId = null);
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of organizations tied to this account
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<Organization> ListOrganizations();
|
||||
|
||||
/// <summary>
|
||||
/// Fetch organization data from web API
|
||||
/// </summary>
|
||||
/// <param name="organizationId"></param>
|
||||
/// <returns></returns>
|
||||
public Organization ReadOrganization(string organizationId = null);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new live algorithm for a logged in user.
|
||||
/// </summary>
|
||||
|
||||
@@ -17,6 +17,8 @@ using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using QuantConnect.Util;
|
||||
using System;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace QuantConnect.Optimizer.Objectives
|
||||
{
|
||||
@@ -29,7 +31,7 @@ namespace QuantConnect.Optimizer.Objectives
|
||||
/// <summary>
|
||||
/// The target comparison operation, eg. 'Greater'
|
||||
/// </summary>
|
||||
[JsonProperty("operator")]
|
||||
[JsonProperty("operator"), JsonConverter(typeof(StringEnumConverter), typeof(DefaultNamingStrategy))]
|
||||
public ComparisonOperatorTypes Operator { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -16,7 +16,7 @@
|
||||
namespace QuantConnect.Optimizer.Objectives
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines standard maximization strategy, i.e. right operand is great than left
|
||||
/// Defines standard maximization strategy, i.e. right operand is greater than left
|
||||
/// </summary>
|
||||
public class Maximization : Extremum
|
||||
{
|
||||
43
Common/Optimizer/OptimizationStatus.cs
Normal file
43
Common/Optimizer/OptimizationStatus.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Optimizer
|
||||
{
|
||||
/// <summary>
|
||||
/// The different optimization status
|
||||
/// </summary>
|
||||
public enum OptimizationStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Just created and not running optimization
|
||||
/// </summary>
|
||||
New,
|
||||
|
||||
/// <summary>
|
||||
/// We failed or we were aborted
|
||||
/// </summary>
|
||||
Aborted,
|
||||
|
||||
/// <summary>
|
||||
/// We are running
|
||||
/// </summary>
|
||||
Running,
|
||||
|
||||
/// <summary>
|
||||
/// Optimization job has completed
|
||||
/// </summary>
|
||||
Completed
|
||||
}
|
||||
}
|
||||
@@ -16,12 +16,15 @@
|
||||
using System.Linq;
|
||||
using QuantConnect.Util;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using QuantConnect.Api;
|
||||
|
||||
namespace QuantConnect.Optimizer.Parameters
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single combination of optimization parameters
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(ParameterSetJsonConverter))]
|
||||
public class ParameterSet
|
||||
{
|
||||
/// <summary>
|
||||
@@ -29,22 +32,24 @@ namespace QuantConnect.Optimizer.Parameters
|
||||
/// </summary>
|
||||
/// <remarks>Internal id, useful for the optimization strategy to id each generated parameter sets,
|
||||
/// even before there is any backtest id</remarks>
|
||||
[JsonProperty(PropertyName = "id")]
|
||||
public int Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Represent a combination as key value of parameters, i.e. order doesn't matter
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, string> Value;
|
||||
[JsonProperty(PropertyName = "value", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public IReadOnlyDictionary<string, string> Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of <see cref="ParameterSet"/> based on new combination of optimization parameters
|
||||
/// </summary>
|
||||
/// <param name="id">Unique identifier</param>
|
||||
/// <param name="arguments">Combination of optimization parameters</param>
|
||||
public ParameterSet(int id, Dictionary<string, string> arguments)
|
||||
/// <param name="value">Combination of optimization parameters</param>
|
||||
public ParameterSet(int id, Dictionary<string, string> value)
|
||||
{
|
||||
Id = id;
|
||||
Value = arguments.ToReadOnlyDictionary();
|
||||
Value = value?.ToReadOnlyDictionary();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -31,7 +31,7 @@ namespace QuantConnect.Orders.Fees
|
||||
/// <remarks>Default value is $0.0015 per share</remarks>
|
||||
public AtreyuFeeModel(decimal? feesPerShare = null)
|
||||
{
|
||||
_feesPerShare = feesPerShare ?? 0.0015m;
|
||||
_feesPerShare = feesPerShare ?? 0.0035m;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace QuantConnect.Orders.Fees
|
||||
if (market == Market.Globex || market == Market.NYMEX
|
||||
|| market == Market.CBOT || market == Market.ICE
|
||||
|| market == Market.CFE || market == Market.COMEX
|
||||
|| market == Market.CME)
|
||||
|| market == Market.CME || market == Market.HKFE)
|
||||
{
|
||||
// just in case...
|
||||
market = Market.USA;
|
||||
|
||||
@@ -72,6 +72,8 @@ namespace QuantConnect.Orders.Fees
|
||||
// limit order posted to the order book
|
||||
unitPrice = ((LimitOrder)order).LimitPrice;
|
||||
}
|
||||
|
||||
unitPrice *= security.SymbolProperties.ContractMultiplier;
|
||||
|
||||
var fee = TakerTier1CryptoFee;
|
||||
|
||||
@@ -104,7 +106,7 @@ namespace QuantConnect.Orders.Fees
|
||||
CurrencyPairUtil.DecomposeCurrencyPair(security.Symbol, out actualBaseCurrency, out actualQuoteCurrency);
|
||||
|
||||
return new OrderFee(new CashAmount(
|
||||
unitPrice * order.AbsoluteQuantity * fee,
|
||||
isBuy ? unitPrice * order.AbsoluteQuantity * fee : 1 * order.AbsoluteQuantity * fee,
|
||||
isBuy ? actualQuoteCurrency : actualBaseCurrency));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.10" />
|
||||
<PackageReference Include="CloneExtensions" Version="1.3.0" />
|
||||
<PackageReference Include="DotNetZip" Version="1.13.3" />
|
||||
<PackageReference Include="fasterflect" Version="3.0.0" />
|
||||
<PackageReference Include="MathNet.Numerics" Version="4.15.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.3">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
@@ -26,8 +26,13 @@ namespace QuantConnect.Scheduling
|
||||
/// </summary>
|
||||
public class TimeMonitor : IDisposable
|
||||
{
|
||||
private readonly List<TimeConsumer> _timeConsumers;
|
||||
private readonly Timer _timer;
|
||||
/// <summary>
|
||||
/// List to store the coming TimeConsumer objects
|
||||
/// </summary>
|
||||
/// <remarks>This field is protected because it's used in a test class
|
||||
/// in `IsolatorLimitResultProviderTests.cs</remarks>
|
||||
protected readonly List<TimeConsumer> TimeConsumers;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of time consumers currently being monitored
|
||||
@@ -36,9 +41,9 @@ namespace QuantConnect.Scheduling
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_timeConsumers)
|
||||
lock (TimeConsumers)
|
||||
{
|
||||
return _timeConsumers.Count;
|
||||
return TimeConsumers.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,48 +53,69 @@ namespace QuantConnect.Scheduling
|
||||
/// </summary>
|
||||
public TimeMonitor(int monitorIntervalMs = 100)
|
||||
{
|
||||
_timeConsumers = new List<TimeConsumer>();
|
||||
TimeConsumers = new List<TimeConsumer>();
|
||||
_timer = new Timer(state =>
|
||||
{
|
||||
lock (_timeConsumers)
|
||||
lock (TimeConsumers)
|
||||
{
|
||||
_timeConsumers.RemoveAll(time => time.Finished);
|
||||
RemoveAll();
|
||||
|
||||
foreach (var consumer in _timeConsumers)
|
||||
foreach (var consumer in TimeConsumers)
|
||||
{
|
||||
if (consumer.NextTimeRequest == null)
|
||||
{
|
||||
// first time, for performance we register this here and not the time consumer
|
||||
consumer.NextTimeRequest = consumer.TimeProvider.GetUtcNow().AddMinutes(1);
|
||||
}
|
||||
else if (consumer.TimeProvider.GetUtcNow() >= consumer.NextTimeRequest)
|
||||
{
|
||||
// each minute request additional time from the isolator
|
||||
consumer.NextTimeRequest = consumer.NextTimeRequest.Value.AddMinutes(1);
|
||||
try
|
||||
{
|
||||
// this will notify the isolator that we've exceed the limits
|
||||
consumer.IsolatorLimitProvider.RequestAdditionalTime(minutes: 1);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// pass
|
||||
}
|
||||
}
|
||||
ProcessConsumer(consumer);
|
||||
}
|
||||
}
|
||||
}, null, monitorIntervalMs, monitorIntervalMs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the TimeConsumer object in TimeConsumers list
|
||||
/// </summary>
|
||||
/// <param name="consumer">The TimeConsumer object to be processed</param>
|
||||
/// <remarks>This method is protected because it's overrode by a test class
|
||||
/// in `IsolatorLimitResultProviderTests.cs`</remarks>
|
||||
protected virtual void ProcessConsumer(TimeConsumer consumer)
|
||||
{
|
||||
if (consumer.NextTimeRequest == null)
|
||||
{
|
||||
// first time, for performance we register this here and not the time consumer
|
||||
consumer.NextTimeRequest = consumer.TimeProvider.GetUtcNow().AddMinutes(1);
|
||||
}
|
||||
else if (consumer.TimeProvider.GetUtcNow() >= consumer.NextTimeRequest)
|
||||
{
|
||||
// each minute request additional time from the isolator
|
||||
consumer.NextTimeRequest = consumer.NextTimeRequest.Value.AddMinutes(1);
|
||||
try
|
||||
{
|
||||
// this will notify the isolator that we've exceed the limits
|
||||
consumer.IsolatorLimitProvider.RequestAdditionalTime(minutes: 1);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove all TimeConsumer objects where the `Finished` field is marked as true
|
||||
/// </summary>
|
||||
/// <remarks>This method is protected because it's overrode by a test class in
|
||||
/// `IsolatorLimitResultProviderTests.cs`</remarks>
|
||||
protected virtual void RemoveAll()
|
||||
{
|
||||
TimeConsumers.RemoveAll(time => time.Finished);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new time consumer element to be monitored
|
||||
/// </summary>
|
||||
/// <param name="consumer">Time consumer instance</param>
|
||||
public void Add(TimeConsumer consumer)
|
||||
{
|
||||
lock (_timeConsumers)
|
||||
lock (TimeConsumers)
|
||||
{
|
||||
_timeConsumers.Add(consumer);
|
||||
TimeConsumers.Add(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ using QuantConnect.Orders.Fees;
|
||||
using QuantConnect.Orders.Fills;
|
||||
using QuantConnect.Orders.Slippage;
|
||||
using Python.Runtime;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Securities.Future
|
||||
@@ -27,7 +28,7 @@ namespace QuantConnect.Securities.Future
|
||||
/// Futures Security Object Implementation for Futures Assets
|
||||
/// </summary>
|
||||
/// <seealso cref="Security"/>
|
||||
public class Future : Security, IDerivativeSecurity
|
||||
public class Future : Security, IDerivativeSecurity, IContinuousSecurity
|
||||
{
|
||||
/// <summary>
|
||||
/// The default number of days required to settle a futures sale
|
||||
@@ -167,6 +168,14 @@ namespace QuantConnect.Securities.Future
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the currently mapped symbol for the security
|
||||
/// </summary>
|
||||
public Symbol Mapped
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the contract filter
|
||||
/// </summary>
|
||||
|
||||
28
Common/Securities/IContinuousSecurity.cs
Normal file
28
Common/Securities/IContinuousSecurity.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Securities
|
||||
{
|
||||
/// <summary>
|
||||
/// A continuous security that get's mapped during his life
|
||||
/// </summary>
|
||||
public interface IContinuousSecurity
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the currently mapped symbol for the security
|
||||
/// </summary>
|
||||
Symbol Mapped { get; set; }
|
||||
}
|
||||
}
|
||||
46
Common/Statistics/PerformanceMetrics.cs
Normal file
46
Common/Statistics/PerformanceMetrics.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Statistics
|
||||
{
|
||||
/// <summary>
|
||||
/// PerformanceMetrics contains the names of the various performance metrics used for evaluation purposes.
|
||||
/// </summary>
|
||||
public static class PerformanceMetrics
|
||||
{
|
||||
public const string Alpha = "Alpha";
|
||||
public const string AnnualStandardDeviation = "Annual Standard Deviation";
|
||||
public const string AnnualVariance = "Annual Variance";
|
||||
public const string AverageLoss = "Average Loss";
|
||||
public const string AverageWin = "Average Win";
|
||||
public const string Beta = "Beta";
|
||||
public const string CompoundingAnnualReturn = "Compounding Annual Return";
|
||||
public const string Drawdown = "Drawdown";
|
||||
public const string EstimatedStrategyCapacity = "Estimated Strategy Capacity";
|
||||
public const string Expectancy = "Expectancy";
|
||||
public const string InformationRatio = "Information Ratio";
|
||||
public const string LossRate = "Loss Rate";
|
||||
public const string NetProfit = "Net Profit";
|
||||
public const string ProbabilisticSharpeRatio = "Probabilistic Sharpe Ratio";
|
||||
public const string ProfitLossRatio = "Profit-Loss Ratio";
|
||||
public const string SharpeRatio = "Sharpe Ratio";
|
||||
public const string TotalFees = "Total Fees";
|
||||
public const string TotalTrades = "Total Trades";
|
||||
public const string TrackingError = "Tracking Error";
|
||||
public const string TreynorRatio = "Treynor Ratio";
|
||||
public const string WinRate = "Win Rate";
|
||||
public const string LowestCapacityAsset = "Lowest Capacity Asset";
|
||||
}
|
||||
}
|
||||
@@ -174,28 +174,28 @@ namespace QuantConnect.Statistics
|
||||
|
||||
return new Dictionary<string, string>
|
||||
{
|
||||
{ "Total Trades", totalTransactions.ToStringInvariant() },
|
||||
{ "Average Win", Math.Round(totalPerformance.PortfolioStatistics.AverageWinRate.SafeMultiply100(), 2).ToStringInvariant() + "%" },
|
||||
{ "Average Loss", Math.Round(totalPerformance.PortfolioStatistics.AverageLossRate.SafeMultiply100(), 2).ToStringInvariant() + "%" },
|
||||
{ "Compounding Annual Return", Math.Round(totalPerformance.PortfolioStatistics.CompoundingAnnualReturn.SafeMultiply100(), 3).ToStringInvariant() + "%" },
|
||||
{ "Drawdown", Math.Round(totalPerformance.PortfolioStatistics.Drawdown.SafeMultiply100(), 3).ToStringInvariant() + "%" },
|
||||
{ "Expectancy", Math.Round(totalPerformance.PortfolioStatistics.Expectancy, 3).ToStringInvariant() },
|
||||
{ "Net Profit", Math.Round(totalPerformance.PortfolioStatistics.TotalNetProfit.SafeMultiply100(), 3).ToStringInvariant() + "%"},
|
||||
{ "Sharpe Ratio", Math.Round((double)totalPerformance.PortfolioStatistics.SharpeRatio, 3).ToStringInvariant() },
|
||||
{ "Probabilistic Sharpe Ratio", Math.Round(totalPerformance.PortfolioStatistics.ProbabilisticSharpeRatio.SafeMultiply100(), 3).ToStringInvariant() + "%"},
|
||||
{ "Loss Rate", Math.Round(totalPerformance.PortfolioStatistics.LossRate.SafeMultiply100()).ToStringInvariant() + "%" },
|
||||
{ "Win Rate", Math.Round(totalPerformance.PortfolioStatistics.WinRate.SafeMultiply100()).ToStringInvariant() + "%" },
|
||||
{ "Profit-Loss Ratio", Math.Round(totalPerformance.PortfolioStatistics.ProfitLossRatio, 2).ToStringInvariant() },
|
||||
{ "Alpha", Math.Round((double)totalPerformance.PortfolioStatistics.Alpha, 3).ToStringInvariant() },
|
||||
{ "Beta", Math.Round((double)totalPerformance.PortfolioStatistics.Beta, 3).ToStringInvariant() },
|
||||
{ "Annual Standard Deviation", Math.Round((double)totalPerformance.PortfolioStatistics.AnnualStandardDeviation, 3).ToStringInvariant() },
|
||||
{ "Annual Variance", Math.Round((double)totalPerformance.PortfolioStatistics.AnnualVariance, 3).ToStringInvariant() },
|
||||
{ "Information Ratio", Math.Round((double)totalPerformance.PortfolioStatistics.InformationRatio, 3).ToStringInvariant() },
|
||||
{ "Tracking Error", Math.Round((double)totalPerformance.PortfolioStatistics.TrackingError, 3).ToStringInvariant() },
|
||||
{ "Treynor Ratio", Math.Round((double)totalPerformance.PortfolioStatistics.TreynorRatio, 3).ToStringInvariant() },
|
||||
{ "Total Fees", "$" + totalFees.ToStringInvariant("0.00") },
|
||||
{ "Estimated Strategy Capacity", "$" + capacity.RoundToSignificantDigits(2).ToStringInvariant() },
|
||||
{ "Lowest Capacity Asset", lowestCapacitySymbol != Symbol.Empty ? lowestCapacitySymbol.ID.ToString() : "" },
|
||||
{ PerformanceMetrics.TotalTrades, totalTransactions.ToStringInvariant() },
|
||||
{ PerformanceMetrics.AverageWin, Math.Round(totalPerformance.PortfolioStatistics.AverageWinRate.SafeMultiply100(), 2).ToStringInvariant() + "%" },
|
||||
{ PerformanceMetrics.AverageLoss, Math.Round(totalPerformance.PortfolioStatistics.AverageLossRate.SafeMultiply100(), 2).ToStringInvariant() + "%" },
|
||||
{ PerformanceMetrics.CompoundingAnnualReturn, Math.Round(totalPerformance.PortfolioStatistics.CompoundingAnnualReturn.SafeMultiply100(), 3).ToStringInvariant() + "%" },
|
||||
{ PerformanceMetrics.Drawdown, Math.Round(totalPerformance.PortfolioStatistics.Drawdown.SafeMultiply100(), 3).ToStringInvariant() + "%" },
|
||||
{ PerformanceMetrics.Expectancy, Math.Round(totalPerformance.PortfolioStatistics.Expectancy, 3).ToStringInvariant() },
|
||||
{ PerformanceMetrics.NetProfit, Math.Round(totalPerformance.PortfolioStatistics.TotalNetProfit.SafeMultiply100(), 3).ToStringInvariant() + "%"},
|
||||
{ PerformanceMetrics.SharpeRatio, Math.Round((double)totalPerformance.PortfolioStatistics.SharpeRatio, 3).ToStringInvariant() },
|
||||
{ PerformanceMetrics.ProbabilisticSharpeRatio, Math.Round(totalPerformance.PortfolioStatistics.ProbabilisticSharpeRatio.SafeMultiply100(), 3).ToStringInvariant() + "%"},
|
||||
{ PerformanceMetrics.LossRate, Math.Round(totalPerformance.PortfolioStatistics.LossRate.SafeMultiply100()).ToStringInvariant() + "%" },
|
||||
{ PerformanceMetrics.WinRate, Math.Round(totalPerformance.PortfolioStatistics.WinRate.SafeMultiply100()).ToStringInvariant() + "%" },
|
||||
{ PerformanceMetrics.ProfitLossRatio, Math.Round(totalPerformance.PortfolioStatistics.ProfitLossRatio, 2).ToStringInvariant() },
|
||||
{ PerformanceMetrics.Alpha, Math.Round((double)totalPerformance.PortfolioStatistics.Alpha, 3).ToStringInvariant() },
|
||||
{ PerformanceMetrics.Beta, Math.Round((double)totalPerformance.PortfolioStatistics.Beta, 3).ToStringInvariant() },
|
||||
{ PerformanceMetrics.AnnualStandardDeviation, Math.Round((double)totalPerformance.PortfolioStatistics.AnnualStandardDeviation, 3).ToStringInvariant() },
|
||||
{ PerformanceMetrics.AnnualVariance, Math.Round((double)totalPerformance.PortfolioStatistics.AnnualVariance, 3).ToStringInvariant() },
|
||||
{ PerformanceMetrics.InformationRatio, Math.Round((double)totalPerformance.PortfolioStatistics.InformationRatio, 3).ToStringInvariant() },
|
||||
{ PerformanceMetrics.TrackingError, Math.Round((double)totalPerformance.PortfolioStatistics.TrackingError, 3).ToStringInvariant() },
|
||||
{ PerformanceMetrics.TreynorRatio, Math.Round((double)totalPerformance.PortfolioStatistics.TreynorRatio, 3).ToStringInvariant() },
|
||||
{ PerformanceMetrics.TotalFees, "$" + totalFees.ToStringInvariant("0.00") },
|
||||
{ PerformanceMetrics.EstimatedStrategyCapacity, "$" + capacity.RoundToSignificantDigits(2).ToStringInvariant() },
|
||||
{ PerformanceMetrics.LowestCapacityAsset, lowestCapacitySymbol != Symbol.Empty ? lowestCapacitySymbol.ID.ToString() : "" },
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,12 @@ namespace QuantConnect
|
||||
/// </summary>
|
||||
public static class Time
|
||||
{
|
||||
/// <summary>
|
||||
/// Allows specifying an offset to trigger the tradable date event
|
||||
/// </summary>
|
||||
/// <remarks>Useful for delaying the tradable date event until new auxiliary data is available to refresh map and factor files</remarks>
|
||||
public static TimeSpan LiveAuxiliaryDataOffset { get; set; } = TimeSpan.FromHours(8);
|
||||
|
||||
/// <summary>
|
||||
/// Provides a value far enough in the future the current computer hardware will have decayed :)
|
||||
/// </summary>
|
||||
|
||||
@@ -214,6 +214,25 @@ namespace QuantConnect.Util
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will return all loaded types that are assignable to T type
|
||||
/// </summary>
|
||||
public IEnumerable<Type> GetExportedTypes<T>() where T : class
|
||||
{
|
||||
var type = typeof(T);
|
||||
return _exportedTypes.Where(type1 =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return type.IsAssignableFrom(type1);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension method to searches the composition container for an export that has a matching type name. This function
|
||||
/// will first try to match on Type.AssemblyQualifiedName, then Type.FullName, and finally on Type.Name
|
||||
|
||||
@@ -726,6 +726,7 @@ namespace QuantConnect.Util
|
||||
case SecurityType.IndexOption:
|
||||
if (isHourOrDaily)
|
||||
{
|
||||
// see TryParsePath: he knows tick type position is 3
|
||||
var optionPath = symbol.Underlying.Value.ToLowerInvariant();
|
||||
return $"{optionPath}_{date.Year}_{tickTypeString}_{symbol.ID.OptionStyle.OptionStyleToLower()}.zip";
|
||||
}
|
||||
@@ -735,6 +736,7 @@ namespace QuantConnect.Util
|
||||
case SecurityType.FutureOption:
|
||||
if (isHourOrDaily)
|
||||
{
|
||||
// see TryParsePath: he knows tick type position is 3
|
||||
var futureOptionPath = symbol.ID.Symbol.ToLowerInvariant();
|
||||
return $"{futureOptionPath}_{date.Year}_{tickTypeString}_{symbol.ID.OptionStyle.OptionStyleToLower()}.zip";
|
||||
}
|
||||
@@ -1013,7 +1015,15 @@ namespace QuantConnect.Util
|
||||
var fileName = Path.GetFileNameWithoutExtension(filePath);
|
||||
if (fileName.Contains("_"))
|
||||
{
|
||||
tickType = (TickType)Enum.Parse(typeof(TickType), fileName.Split('_')[1], true);
|
||||
// example: 20140606_openinterest_american.zip
|
||||
var tickTypePosition = 1;
|
||||
if (resolution >= Resolution.Hour && symbol.SecurityType.IsOption())
|
||||
{
|
||||
// daily and hourly have the year too, example: aapl_2014_openinterest_american.zip
|
||||
// see GenerateZipFileName he's creating these paths
|
||||
tickTypePosition = 2;
|
||||
}
|
||||
tickType = (TickType)Enum.Parse(typeof(TickType), fileName.Split('_')[tickTypePosition], true);
|
||||
}
|
||||
|
||||
dataType = GetDataType(resolution, tickType);
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace QuantConnect.Util
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the input value to a value to be serialzied
|
||||
/// Convert the input value to a value to be serialized
|
||||
/// </summary>
|
||||
/// <param name="value">The input value to be converted before serialziation</param>
|
||||
/// <returns>A new instance of TResult that is to be serialzied</returns>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user