Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ab1f90e27 | ||
|
|
bf2ef35ada | ||
|
|
2001f9a181 | ||
|
|
8026785116 | ||
|
|
5083433f68 | ||
|
|
5d4f428906 | ||
|
|
da60daa60d | ||
|
|
7d88b5040b | ||
|
|
d76106b444 | ||
|
|
de09ec0933 | ||
|
|
c3874bc618 | ||
|
|
0e1e497fbf | ||
|
|
8eb023e854 | ||
|
|
b251cffc2f | ||
|
|
1d904e716c | ||
|
|
df57428bd7 | ||
|
|
9d734c4d8f | ||
|
|
765ce87df1 | ||
|
|
8a5766fa39 | ||
|
|
933e5ce6ca | ||
|
|
dc433493b7 | ||
|
|
9acf68ad19 | ||
|
|
5ebf451fb3 | ||
|
|
a4d49c05ca | ||
|
|
aaba566954 | ||
|
|
bf28a1d313 | ||
|
|
85a4d3364b | ||
|
|
eccca2c029 |
@@ -17,6 +17,8 @@ using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Brokerages;
|
||||
using QuantConnect.Securities;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Data.Custom.AlphaStreams;
|
||||
@@ -44,6 +46,9 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
Settings.MinimumOrderMarginPortfolioPercentage = 0.01m;
|
||||
SetPortfolioConstruction(new EqualWeightingAlphaStreamsPortfolioConstructionModel());
|
||||
|
||||
SetSecurityInitializer(new BrokerageModelSecurityInitializer(new DefaultBrokerageModel(),
|
||||
new FuncSecuritySeeder(GetLastKnownPrices)));
|
||||
|
||||
foreach (var alphaId in new [] { "623b06b231eb1cc1aa3643a46", "9fc8ef73792331b11dbd5429a" })
|
||||
{
|
||||
AddData<AlphaStreamsPortfolioState>(alphaId);
|
||||
@@ -58,24 +63,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
foreach (var portfolioState in data.Get<AlphaStreamsPortfolioState>().Values)
|
||||
{
|
||||
var alphaId = portfolioState.Symbol;
|
||||
var currentSymbols = _symbolsPerAlpha[alphaId];
|
||||
|
||||
var newSymbols = new HashSet<Symbol>(currentSymbols.Count);
|
||||
foreach (var symbol in portfolioState.PositionGroups?.SelectMany(positionGroup => positionGroup.Positions).Select(state => state.Symbol) ?? Enumerable.Empty<Symbol>())
|
||||
{
|
||||
// only add it if it's not used by any alpha (already added check)
|
||||
if (newSymbols.Add(symbol) && !UsedBySomeAlpha(symbol))
|
||||
{
|
||||
AddSecurity(symbol, resolution: UniverseSettings.Resolution);
|
||||
}
|
||||
}
|
||||
_symbolsPerAlpha[alphaId] = newSymbols;
|
||||
|
||||
foreach (var symbol in currentSymbols.Where(symbol => !UsedBySomeAlpha(symbol)))
|
||||
{
|
||||
RemoveSecurity(symbol);
|
||||
}
|
||||
ProcessPortfolioState(portfolioState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +79,12 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
if (addedSecurity.Symbol.IsCustomDataType<AlphaStreamsPortfolioState>())
|
||||
{
|
||||
_symbolsPerAlpha[addedSecurity.Symbol] = new HashSet<Symbol>();
|
||||
if (!_symbolsPerAlpha.ContainsKey(addedSecurity.Symbol))
|
||||
{
|
||||
_symbolsPerAlpha[addedSecurity.Symbol] = new HashSet<Symbol>();
|
||||
}
|
||||
// warmup alpha state, adding target securities
|
||||
ProcessPortfolioState(addedSecurity.Cache.GetData<AlphaStreamsPortfolioState>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +96,36 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
return _symbolsPerAlpha.Any(pair => pair.Value.Contains(asset));
|
||||
}
|
||||
|
||||
private void ProcessPortfolioState(AlphaStreamsPortfolioState portfolioState)
|
||||
{
|
||||
if (portfolioState == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var alphaId = portfolioState.Symbol;
|
||||
if (!_symbolsPerAlpha.TryGetValue(alphaId, out var currentSymbols))
|
||||
{
|
||||
_symbolsPerAlpha[alphaId] = currentSymbols = new HashSet<Symbol>();
|
||||
}
|
||||
|
||||
var newSymbols = new HashSet<Symbol>(currentSymbols.Count);
|
||||
foreach (var symbol in portfolioState.PositionGroups?.SelectMany(positionGroup => positionGroup.Positions).Select(state => state.Symbol) ?? Enumerable.Empty<Symbol>())
|
||||
{
|
||||
// only add it if it's not used by any alpha (already added check)
|
||||
if (newSymbols.Add(symbol) && !UsedBySomeAlpha(symbol))
|
||||
{
|
||||
AddSecurity(symbol, resolution: UniverseSettings.Resolution, extendedMarketHours: UniverseSettings.ExtendedMarketHours);
|
||||
}
|
||||
}
|
||||
_symbolsPerAlpha[alphaId] = newSymbols;
|
||||
|
||||
foreach (var symbol in currentSymbols.Where(symbol => !UsedBySomeAlpha(symbol)))
|
||||
{
|
||||
RemoveSecurity(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
|
||||
@@ -47,17 +47,17 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.84%"},
|
||||
{"Average Win", "0.01%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "-78.502%"},
|
||||
{"Drawdown", "3.100%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Expectancy", "7.797"},
|
||||
{"Net Profit", "-1.134%"},
|
||||
{"Sharpe Ratio", "-2.456"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Loss Rate", "50%"},
|
||||
{"Win Rate", "50%"},
|
||||
{"Profit-Loss Ratio", "16.59"},
|
||||
{"Alpha", "0.008"},
|
||||
{"Beta", "1.012"},
|
||||
{"Annual Standard Deviation", "0.343"},
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// </summary>
|
||||
public class AlphaStreamsWithHoldingsBasicTemplateAlgorithm : AlphaStreamsBasicTemplateAlgorithm
|
||||
{
|
||||
private decimal _initialCash = 100000;
|
||||
private decimal _expectedSpyQuantity;
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
@@ -36,33 +35,33 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
SetStartDate(2018, 04, 04);
|
||||
SetEndDate(2018, 04, 06);
|
||||
SetCash(_initialCash);
|
||||
SetCash(100000);
|
||||
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
UniverseSettings.Resolution = Resolution.Hour;
|
||||
Settings.MinimumOrderMarginPortfolioPercentage = 0.01m;
|
||||
Settings.MinimumOrderMarginPortfolioPercentage = 0.001m;
|
||||
SetPortfolioConstruction(new EqualWeightingAlphaStreamsPortfolioConstructionModel());
|
||||
|
||||
// AAPL should be liquidated since it's not hold by the alpha
|
||||
// This is handled by the PCM
|
||||
var aapl = AddEquity("AAPL", Resolution.Hour);
|
||||
aapl.Holdings.SetHoldings(100, 10);
|
||||
aapl.Holdings.SetHoldings(40, 10);
|
||||
|
||||
// SPY will be bought following the alpha streams portfolio
|
||||
// This is handled by the PCM + Execution Model
|
||||
var spy = AddEquity("SPY", Resolution.Hour);
|
||||
spy.Holdings.SetHoldings(100, -10);
|
||||
spy.Holdings.SetHoldings(246, -10);
|
||||
|
||||
AddData<AlphaStreamsPortfolioState>("94d820a93fff127fa46c15231d");
|
||||
}
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
if (_expectedSpyQuantity == 0 && orderEvent.Symbol == "SPY")
|
||||
if (_expectedSpyQuantity == 0 && orderEvent.Symbol == "SPY" && orderEvent.Status == OrderStatus.Filled)
|
||||
{
|
||||
var security = Securities["SPY"];
|
||||
var priceInAccountCurrency = security.AskPrice * security.QuoteCurrency.ConversionRate;
|
||||
_expectedSpyQuantity = (_initialCash * (1 - Settings.FreePortfolioValuePercentage) - priceInAccountCurrency) / priceInAccountCurrency;
|
||||
var priceInAccountCurrency = Portfolio.CashBook.ConvertToAccountCurrency(security.AskPrice, security.QuoteCurrency.Symbol);
|
||||
_expectedSpyQuantity = (Portfolio.TotalPortfolioValue - Settings.FreePortfolioValue) / priceInAccountCurrency;
|
||||
_expectedSpyQuantity = _expectedSpyQuantity.DiscretelyRoundBy(1, MidpointRounding.ToZero);
|
||||
}
|
||||
|
||||
@@ -76,7 +75,8 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
throw new Exception("We should no longer hold AAPL since the alpha does not");
|
||||
}
|
||||
|
||||
if (Securities["SPY"].Holdings.Quantity != _expectedSpyQuantity)
|
||||
// we allow some padding for small price differences
|
||||
if (Math.Abs(Securities["SPY"].Holdings.Quantity - _expectedSpyQuantity) > _expectedSpyQuantity * 0.03m)
|
||||
{
|
||||
throw new Exception($"Unexpected SPY holdings. Expected {_expectedSpyQuantity} was {Securities["SPY"].Holdings.Quantity}");
|
||||
}
|
||||
@@ -98,17 +98,17 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "2"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-1.03%"},
|
||||
{"Average Win", "0.01%"},
|
||||
{"Average Loss", "0.00%"},
|
||||
{"Compounding Annual Return", "-87.617%"},
|
||||
{"Drawdown", "3.100%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Expectancy", "8.518"},
|
||||
{"Net Profit", "-1.515%"},
|
||||
{"Sharpe Ratio", "-2.45"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Loss Rate", "50%"},
|
||||
{"Win Rate", "50%"},
|
||||
{"Profit-Loss Ratio", "18.04"},
|
||||
{"Alpha", "0.008"},
|
||||
{"Beta", "1.015"},
|
||||
{"Annual Standard Deviation", "0.344"},
|
||||
|
||||
130
Algorithm.CSharp/BasicTemplateAtreyuAlgorithm.cs
Normal file
130
Algorithm.CSharp/BasicTemplateAtreyuAlgorithm.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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 QuantConnect.Brokerages;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic template algorithm for the Atreyu brokerage
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data" />
|
||||
/// <meta name="tag" content="using quantconnect" />
|
||||
/// <meta name="tag" content="trading and orders" />
|
||||
public class BasicTemplateAtreyuAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07);
|
||||
SetEndDate(2013, 10, 11);
|
||||
SetCash(100000);
|
||||
|
||||
SetBrokerageModel(BrokerageName.Atreyu);
|
||||
AddEquity("SPY", Resolution.Minute);
|
||||
|
||||
DefaultOrderProperties = new AtreyuOrderProperties
|
||||
{
|
||||
// Can specify the default exchange to execute an order on.
|
||||
// If not specified will default to the primary exchange
|
||||
Exchange = Exchange.NASDAQ,
|
||||
// Currently only support order for the day
|
||||
TimeInForce = TimeInForce.Day
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice data)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
// will set 25% of our buying power with a market order that will be routed to exchange set in the default order properties (NASDAQ)
|
||||
SetHoldings("SPY", 0.25m);
|
||||
// will increase our SPY holdings to 50% of our buying power with a market order that will be routed to ARCA
|
||||
SetHoldings("SPY", 0.50m, orderProperties: new AtreyuOrderProperties { Exchange = Exchange.ARCA });
|
||||
|
||||
Debug("Purchased SPY!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public 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%"},
|
||||
{"Compounding Annual Return", "93.443%"},
|
||||
{"Drawdown", "1.100%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0.847%"},
|
||||
{"Sharpe Ratio", "6.515"},
|
||||
{"Probabilistic Sharpe Ratio", "67.535%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0.11"},
|
||||
{"Annual Variance", "0.012"},
|
||||
{"Information Ratio", "6.515"},
|
||||
{"Tracking Error", "0.11"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$0.52"},
|
||||
{"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"},
|
||||
{"Portfolio Turnover", "0.124"},
|
||||
{"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", "cb542eaaeab5eac3bcae5d915ded30da"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic template algorithm which showcases <see cref="ConstituentsUniverse"/> simple use case
|
||||
/// </summary>
|
||||
public class BasicTemplateConstituentUniverseAlgorithm : QCAlgorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07);
|
||||
SetEndDate(2013, 10, 11);
|
||||
|
||||
// by default will use algorithms UniverseSettings
|
||||
AddUniverse(Universe.Constituent.Steel());
|
||||
|
||||
// we specify the UniverseSettings it should use
|
||||
AddUniverse(Universe.Constituent.AggressiveGrowth(
|
||||
new UniverseSettings(Resolution.Hour,
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
UniverseSettings.MinimumTimeInUniverse)));
|
||||
|
||||
SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromDays(1)));
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// <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 };
|
||||
public virtual 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
|
||||
|
||||
@@ -13,16 +13,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Orders;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
@@ -47,15 +40,14 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
// Find more symbols here: http://quantconnect.com/data
|
||||
// Equities Resolutions: Tick, Second, Minute, Hour, Daily.
|
||||
AddEquity("UNIONBANK", Resolution.Second, Market.India);
|
||||
|
||||
|
||||
//Set Order Prperties as per the requirements for order placement
|
||||
DefaultOrderProperties = new ZerodhaOrderProperties(exchange: "nse");
|
||||
DefaultOrderProperties = new IndiaOrderProperties(exchange: Exchange.NSE);
|
||||
//override default productType value set in config.json if needed - order specific productType value
|
||||
//DefaultOrderProperties = new ZerodhaOrderProperties(exchange: "nse",ZerodhaOrderProperties.KiteProductType.CNC);
|
||||
//DefaultOrderProperties = new IndiaOrderProperties(exchange: Exchange.NSE, IndiaOrderProperties.IndiaProductType.CNC);
|
||||
|
||||
// General Debug statement for acknowledgement
|
||||
Debug("Intialization Done");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -70,7 +62,6 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
if (orderEvent.Status.IsFill())
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
SetCash(100000); // Set Strategy Cash
|
||||
|
||||
// Add QC500 Universe
|
||||
AddUniverse(Universe.Index.QC500);
|
||||
AddUniverse(Universe.QC500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Linq;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm that will test that <see cref="IAlgorithmSettings.MinimumOrderMarginPortfolioPercentage"/>
|
||||
/// is respected by the <see cref="ImmediateExecutionModel"/>
|
||||
/// </summary>
|
||||
public class ImmediateExecutionModelMinimumOrderMarginRegressionAlgorithm : BasicTemplateFrameworkAlgorithm
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
// this setting is the difference between doing 3 trades and > 60
|
||||
Settings.MinimumOrderMarginPortfolioPercentage = 0.001m;
|
||||
SetPortfolioConstruction(new CustomPortfolioConstructionModel(TimeKeeper));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public override Language[] Languages { get; } = { Language.CSharp };
|
||||
|
||||
private class CustomPortfolioConstructionModel : EqualWeightingPortfolioConstructionModel
|
||||
{
|
||||
private ITimeKeeper _timeKeeper;
|
||||
public CustomPortfolioConstructionModel(ITimeKeeper timeKeeper)
|
||||
{
|
||||
_timeKeeper = timeKeeper;
|
||||
}
|
||||
protected override Dictionary<Insight, double> DetermineTargetPercent(List<Insight> activeInsights)
|
||||
{
|
||||
var baseResult = base.DetermineTargetPercent(activeInsights);
|
||||
|
||||
// we generate some fake noise in the percentage allocation
|
||||
var adjustPercentage = _timeKeeper.UtcTime.Minute % 2 == 0;
|
||||
return baseResult.ToDictionary(pair => pair.Key, pair => adjustPercentage ? pair.Value - 0.001 : pair.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@
|
||||
<DebugType>portable</DebugType>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.5" />
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.6" />
|
||||
<PackageReference Include="Accord" Version="3.6.0" />
|
||||
<PackageReference Include="Accord.Fuzzy" Version="3.6.0" />
|
||||
<PackageReference Include="Accord.MachineLearning" Version="3.6.0" />
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
_gdvd = QuantConnect.Symbol.Create("GDVD", SecurityType.Equity, Market.USA);
|
||||
}
|
||||
|
||||
AddUniverse(new ETFConstituentsUniverse(_gdvd, UniverseSettings, FilterETFs));
|
||||
AddUniverse(Universe.ETF(_gdvd, universeFilterFunc: FilterETFs));
|
||||
}
|
||||
|
||||
private IEnumerable<Symbol> FilterETFs(IEnumerable<ETFConstituentData> constituents)
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
_spy = AddEquity("SPY", Resolution.Hour).Symbol;
|
||||
_aapl = QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA);
|
||||
|
||||
AddUniverse(new ETFConstituentsUniverse(_spy, UniverseSettings, FilterETFs));
|
||||
AddUniverse(Universe.ETF(_spy, universeFilterFunc: FilterETFs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests ETF constituents universe selection with the algorithm framework models (Alpha, PortfolioConstruction, Execution)
|
||||
/// </summary>
|
||||
public class ETFConstituentUniverseFrameworkRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
private List<ETFConstituentData> ConstituentData = new List<ETFConstituentData>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the algorithm, setting up the framework classes and ETF constituent universe settings
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2020, 12, 1);
|
||||
SetEndDate(2021, 1, 31);
|
||||
SetCash(100000);
|
||||
|
||||
SetAlpha(new ETFConstituentAlphaModel());
|
||||
SetPortfolioConstruction(new ETFConstituentPortfolioModel());
|
||||
SetExecution(new ETFConstituentExecutionModel());
|
||||
|
||||
var spy = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
|
||||
|
||||
UniverseSettings.Resolution = Resolution.Hour;
|
||||
AddUniverse(Universe.ETF(spy, UniverseSettings, FilterETFConstituents));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filters ETF constituents
|
||||
/// </summary>
|
||||
/// <param name="constituents">ETF constituents</param>
|
||||
/// <returns>ETF constituent Symbols that we want to include in the algorithm</returns>
|
||||
public IEnumerable<Symbol> FilterETFConstituents(IEnumerable<ETFConstituentData> constituents)
|
||||
{
|
||||
var constituentData = constituents
|
||||
.Where(x => (x.Weight ?? 0m) >= 0.001m)
|
||||
.ToList();
|
||||
|
||||
ConstituentData = constituentData;
|
||||
|
||||
return constituentData
|
||||
.Select(x => x.Symbol)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// no-op for performance
|
||||
/// </summary>
|
||||
public override void OnData(Slice data)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alpha model for ETF constituents, where we generate insights based on the weighting
|
||||
/// of the ETF constituent
|
||||
/// </summary>
|
||||
private class ETFConstituentAlphaModel : IAlphaModel
|
||||
{
|
||||
public void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates new insights based on constituent data and their weighting
|
||||
/// in their respective ETF
|
||||
/// </summary>
|
||||
public IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
var algo = (ETFConstituentUniverseFrameworkRegressionAlgorithm) algorithm;
|
||||
|
||||
foreach (var constituent in algo.ConstituentData)
|
||||
{
|
||||
if (!data.Bars.ContainsKey(constituent.Symbol) &&
|
||||
!data.QuoteBars.ContainsKey(constituent.Symbol))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var insightDirection = constituent.Weight != null && constituent.Weight >= 0.01m
|
||||
? InsightDirection.Up
|
||||
: InsightDirection.Down;
|
||||
|
||||
yield return new Insight(
|
||||
algorithm.UtcTime,
|
||||
constituent.Symbol,
|
||||
TimeSpan.FromDays(1),
|
||||
InsightType.Price,
|
||||
insightDirection,
|
||||
1 * (double)insightDirection,
|
||||
1.0,
|
||||
weight: (double)(constituent.Weight ?? 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates targets for ETF constituents, which will be set to the weighting
|
||||
/// of the constituent in their respective ETF
|
||||
/// </summary>
|
||||
private class ETFConstituentPortfolioModel : IPortfolioConstructionModel
|
||||
{
|
||||
private bool _hasAdded;
|
||||
|
||||
/// <summary>
|
||||
/// Securities changed, detects if we've got new additions to the universe
|
||||
/// so that we don't try to trade every loop
|
||||
/// </summary>
|
||||
public void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
_hasAdded = changes.AddedSecurities.Count != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates portfolio targets based on the insights provided to us by the alpha model.
|
||||
/// Emits portfolio targets setting the quantity to the weight of the constituent
|
||||
/// in its respective ETF.
|
||||
/// </summary>
|
||||
public IEnumerable<IPortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
|
||||
{
|
||||
if (!_hasAdded)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var insight in insights)
|
||||
{
|
||||
yield return new PortfolioTarget(insight.Symbol, (decimal) (insight.Weight ?? 0));
|
||||
_hasAdded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes based on ETF constituent weighting
|
||||
/// </summary>
|
||||
private class ETFConstituentExecutionModel : IExecutionModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Liquidates if constituents have been removed from the universe
|
||||
/// </summary>
|
||||
public void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
foreach (var change in changes.RemovedSecurities)
|
||||
{
|
||||
algorithm.Liquidate(change.Symbol);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates orders for constituents that attempts to add
|
||||
/// the weighting of the constituent in our portfolio. The
|
||||
/// resulting algorithm portfolio weight might not be equal
|
||||
/// to the leverage of the ETF (1x, 2x, 3x, etc.)
|
||||
/// </summary>
|
||||
public void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
|
||||
{
|
||||
foreach (var target in targets)
|
||||
{
|
||||
algorithm.SetHoldings(target.Symbol, target.Quantity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public 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", "4"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "3.225%"},
|
||||
{"Drawdown", "0.800%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0.520%"},
|
||||
{"Sharpe Ratio", "1.518"},
|
||||
{"Probabilistic Sharpe Ratio", "57.759%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0.022"},
|
||||
{"Beta", "0.101"},
|
||||
{"Annual Standard Deviation", "0.022"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.653"},
|
||||
{"Tracking Error", "0.117"},
|
||||
{"Treynor Ratio", "0.333"},
|
||||
{"Total Fees", "$4.00"},
|
||||
{"Estimated Strategy Capacity", "$1300000000.00"},
|
||||
{"Lowest Capacity Asset", "AIG R735QTJ8XC9X"},
|
||||
{"Fitness Score", "0.001"},
|
||||
{"Kelly Criterion Estimate", "1.528"},
|
||||
{"Kelly Criterion Probability Value", "0.091"},
|
||||
{"Sortino Ratio", "4.929"},
|
||||
{"Return Over Maximum Drawdown", "8.624"},
|
||||
{"Portfolio Turnover", "0.001"},
|
||||
{"Total Insights Generated", "1108"},
|
||||
{"Total Insights Closed", "1080"},
|
||||
{"Total Insights Analysis Completed", "1080"},
|
||||
{"Long Insight Count", "277"},
|
||||
{"Short Insight Count", "831"},
|
||||
{"Long/Short Ratio", "33.33%"},
|
||||
{"Estimated Monthly Alpha Value", "$4169774.3402"},
|
||||
{"Total Accumulated Estimated Alpha Value", "$8322174.6207"},
|
||||
{"Mean Population Estimated Insight Value", "$7705.7172"},
|
||||
{"Mean Population Direction", "49.7222%"},
|
||||
{"Mean Population Magnitude", "49.7222%"},
|
||||
{"Rolling Averaged Population Direction", "56.0724%"},
|
||||
{"Rolling Averaged Population Magnitude", "56.0724%"},
|
||||
{"OrderListHash", "eb27e818f4a6609329a52feeb74bd554"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
|
||||
_aapl = QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA);
|
||||
_qqq = AddEquity("QQQ", Resolution.Daily).Symbol;
|
||||
AddUniverse(new ETFConstituentsUniverse(_qqq, UniverseSettings, FilterETFs));
|
||||
AddUniverse(Universe.ETF(_qqq, universeFilterFunc: FilterETFs));
|
||||
}
|
||||
|
||||
private IEnumerable<Symbol> FilterETFs(IEnumerable<ETFConstituentData> constituents)
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Indicators;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Example algorithm demonstrating the usage of the RSI indicator
|
||||
/// in combination with ETF constituents data to replicate the weighting
|
||||
/// of the ETF's assets in our own account.
|
||||
/// </summary>
|
||||
public class ETFConstituentUniverseRSIAlphaModelAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize 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(2020, 12, 1);
|
||||
SetEndDate(2021, 1, 31);
|
||||
SetCash(100000);
|
||||
|
||||
SetAlpha(new ConstituentWeightedRsiAlphaModel());
|
||||
SetPortfolioConstruction(new InsightWeightingPortfolioConstructionModel());
|
||||
SetExecution(new ImmediateExecutionModel());
|
||||
|
||||
var spy = AddEquity("SPY", Resolution.Hour).Symbol;
|
||||
|
||||
// We load hourly data for ETF constituents in this algorithm
|
||||
UniverseSettings.Resolution = Resolution.Hour;
|
||||
Settings.MinimumOrderMarginPortfolioPercentage = 0.01m;
|
||||
|
||||
AddUniverse(Universe.ETF(spy, UniverseSettings, FilterETFConstituents));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filters ETF constituents and adds the resulting Symbols to the ETF constituent universe
|
||||
/// </summary>
|
||||
/// <param name="constituents">ETF constituents, i.e. the components of the ETF and their weighting</param>
|
||||
/// <returns>Symbols to add to universe</returns>
|
||||
public IEnumerable<Symbol> FilterETFConstituents(IEnumerable<ETFConstituentData> constituents)
|
||||
{
|
||||
return constituents
|
||||
.Where(x => x.Weight != null && x.Weight >= 0.001m)
|
||||
.Select(x => x.Symbol);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alpha model making use of the RSI indicator and ETF constituent weighting to determine
|
||||
/// which assets we should invest in and the direction of investment
|
||||
/// </summary>
|
||||
private class ConstituentWeightedRsiAlphaModel : AlphaModel
|
||||
{
|
||||
private Dictionary<Symbol, SymbolData> _rsiSymbolData = new Dictionary<Symbol, SymbolData>();
|
||||
|
||||
/// <summary>
|
||||
/// Receives new data and emits new <see cref="Insight"/> instances
|
||||
/// </summary>
|
||||
/// <param name="algorithm">Algorithm</param>
|
||||
/// <param name="data">Current data</param>
|
||||
/// <returns>Enumerable of insights for assets to invest with a specific weight</returns>
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
// Cast first, and then access the constituents collection defined in our algorithm.
|
||||
var algoConstituents = data.Bars.Keys
|
||||
.Where(x => algorithm.Securities[x].Cache.HasData(typeof(ETFConstituentData)))
|
||||
.Select(x => algorithm.Securities[x].Cache.GetData<ETFConstituentData>())
|
||||
.ToList();
|
||||
|
||||
if (algoConstituents.Count == 0 || data.Bars.Count == 0)
|
||||
{
|
||||
// Don't do anything if we have no data we can work with
|
||||
yield break;
|
||||
}
|
||||
|
||||
var constituents = algoConstituents
|
||||
.ToDictionary(x => x.Symbol, x => x);
|
||||
|
||||
foreach (var bar in data.Bars.Values)
|
||||
{
|
||||
if (!constituents.ContainsKey(bar.Symbol))
|
||||
{
|
||||
// Dealing with a manually added equity, which in this case is SPY
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_rsiSymbolData.ContainsKey(bar.Symbol))
|
||||
{
|
||||
// First time we're initializing the RSI.
|
||||
// It won't be ready now, but it will be
|
||||
// after 7 data points.
|
||||
var constituent = constituents[bar.Symbol];
|
||||
_rsiSymbolData[bar.Symbol] = new SymbolData(bar.Symbol, algorithm, constituent, 7);
|
||||
}
|
||||
}
|
||||
|
||||
// Let's make sure all RSI indicators are ready before we emit any insights.
|
||||
var allReady = _rsiSymbolData.All(kvp => kvp.Value.Rsi.IsReady);
|
||||
if (!allReady)
|
||||
{
|
||||
// We're still warming up the RSI indicators.
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var kvp in _rsiSymbolData)
|
||||
{
|
||||
var symbol = kvp.Key;
|
||||
var symbolData = kvp.Value;
|
||||
|
||||
var averageLoss = symbolData.Rsi.AverageLoss.Current.Value;
|
||||
var averageGain = symbolData.Rsi.AverageGain.Current.Value;
|
||||
|
||||
// If we've lost more than gained, then we think it's going to go down more
|
||||
var direction = averageLoss > averageGain
|
||||
? InsightDirection.Down
|
||||
: InsightDirection.Up;
|
||||
|
||||
// Set the weight of the insight as the weight of the ETF's
|
||||
// holding. The InsightWeightingPortfolioConstructionModel
|
||||
// will rebalance our portfolio to have the same percentage
|
||||
// of holdings in our algorithm that the ETF has.
|
||||
yield return Insight.Price(
|
||||
symbol,
|
||||
TimeSpan.FromDays(1),
|
||||
direction,
|
||||
(double)(direction == InsightDirection.Down
|
||||
? averageLoss
|
||||
: averageGain),
|
||||
weight: (double?) symbolData.Constituent.Weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper class to access ETF constituent data and RSI indicators
|
||||
/// for a single Symbol
|
||||
/// </summary>
|
||||
private class SymbolData
|
||||
{
|
||||
/// <summary>
|
||||
/// Symbol this data belongs to
|
||||
/// </summary>
|
||||
public Symbol Symbol { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Symbol's constituent data for the ETF it belongs to
|
||||
/// </summary>
|
||||
public ETFConstituentData Constituent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// RSI indicator for the Symbol's price data
|
||||
/// </summary>
|
||||
public RelativeStrengthIndex Rsi { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of SymbolData
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol to add data for</param>
|
||||
/// <param name="constituent">ETF constituent data</param>
|
||||
/// <param name="period">RSI period</param>
|
||||
public SymbolData(Symbol symbol, QCAlgorithm algorithm, ETFConstituentData constituent, int period)
|
||||
{
|
||||
Symbol = symbol;
|
||||
Constituent = constituent;
|
||||
Rsi = algorithm.RSI(symbol, period, MovingAverageType.Exponential, Resolution.Hour);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public 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", "52"},
|
||||
{"Average Win", "0.09%"},
|
||||
{"Average Loss", "-0.05%"},
|
||||
{"Compounding Annual Return", "3.919%"},
|
||||
{"Drawdown", "0.500%"},
|
||||
{"Expectancy", "0.080"},
|
||||
{"Net Profit", "0.630%"},
|
||||
{"Sharpe Ratio", "2.197"},
|
||||
{"Probabilistic Sharpe Ratio", "67.639%"},
|
||||
{"Loss Rate", "61%"},
|
||||
{"Win Rate", "39%"},
|
||||
{"Profit-Loss Ratio", "1.75"},
|
||||
{"Alpha", "0.043"},
|
||||
{"Beta", "-0.024"},
|
||||
{"Annual Standard Deviation", "0.018"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "-0.522"},
|
||||
{"Tracking Error", "0.133"},
|
||||
{"Treynor Ratio", "-1.678"},
|
||||
{"Total Fees", "$52.00"},
|
||||
{"Estimated Strategy Capacity", "$430000000.00"},
|
||||
{"Lowest Capacity Asset", "AAPL R735QTJ8XC9X"},
|
||||
{"Fitness Score", "0.144"},
|
||||
{"Kelly Criterion Estimate", "-2.61"},
|
||||
{"Kelly Criterion Probability Value", "0.987"},
|
||||
{"Sortino Ratio", "2.877"},
|
||||
{"Return Over Maximum Drawdown", "6.437"},
|
||||
{"Portfolio Turnover", "0.162"},
|
||||
{"Total Insights Generated", "1076"},
|
||||
{"Total Insights Closed", "1048"},
|
||||
{"Total Insights Analysis Completed", "1048"},
|
||||
{"Long Insight Count", "530"},
|
||||
{"Short Insight Count", "546"},
|
||||
{"Long/Short Ratio", "97.07%"},
|
||||
{"Estimated Monthly Alpha Value", "$-378965.1"},
|
||||
{"Total Accumulated Estimated Alpha Value", "$-756351.1"},
|
||||
{"Mean Population Estimated Insight Value", "$-721.7091"},
|
||||
{"Mean Population Direction", "45.8015%"},
|
||||
{"Mean Population Magnitude", "45.8015%"},
|
||||
{"Rolling Averaged Population Direction", "45.6662%"},
|
||||
{"Rolling Averaged Population Magnitude", "45.6662%"},
|
||||
{"OrderListHash", "f320b74a7bb7207f3f88f7fce9d0f286"}
|
||||
};
|
||||
}
|
||||
}
|
||||
161
Algorithm.CSharp/SamcoBasicTemplateOptionsAlgorithm.cs
Normal file
161
Algorithm.CSharp/SamcoBasicTemplateOptionsAlgorithm.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.Brokerages;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Orders;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// This example demonstrates how to add options for a given underlying equity security. It also
|
||||
/// shows how you can prefilter contracts easily based on strikes and expirations, and how you
|
||||
/// can inspect the option chain to pick a specific option contract to trade.
|
||||
/// </summary>
|
||||
/// <meta name="tag" content="using data"/>
|
||||
/// <meta name="tag" content="options"/>
|
||||
/// <meta name="tag" content="filter selection"/>
|
||||
public class SamcoBasicTemplateOptionsAlgorithm : QCAlgorithm
|
||||
{
|
||||
private const string UnderlyingTicker = "NIFTY";
|
||||
public Symbol OptionSymbol;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SetTimeZone(TimeZones.Kolkata);
|
||||
SetBrokerageModel(BrokerageName.Samco, AccountType.Margin);
|
||||
SetAccountCurrency(Currencies.INR);
|
||||
|
||||
var equity = AddEquity(UnderlyingTicker, market: Market.India);
|
||||
var option = AddOption(equity.Symbol, market: Market.India);
|
||||
OptionSymbol = option.Symbol;
|
||||
|
||||
// set our strike/expiry filter for this option chain
|
||||
option.SetFilter(u => u.Strikes(-2, +2)
|
||||
// Expiration method accepts TimeSpan objects or integer for
|
||||
// days. The following statements yield the same filtering criteria
|
||||
.Expiration(0, 180));
|
||||
// .Expiration(TimeSpan.Zero, TimeSpan.FromDays(180)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for
|
||||
/// receiving all subscription data in a single event
|
||||
/// </summary>
|
||||
/// <param name="slice">The current slice of data keyed by symbol string</param>
|
||||
public override void OnData(Slice slice)
|
||||
{
|
||||
if (!Portfolio.Invested && IsMarketOpen(OptionSymbol))
|
||||
{
|
||||
OptionChain chain;
|
||||
if (slice.OptionChains.TryGetValue(OptionSymbol, out chain))
|
||||
{
|
||||
// we find at the money (ATM) put contract with farthest expiration
|
||||
var atmContract = chain
|
||||
.OrderByDescending(x => x.Expiry)
|
||||
.ThenBy(x => Math.Abs(chain.Underlying.Price - x.Strike))
|
||||
.ThenByDescending(x => x.Right)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (atmContract != null)
|
||||
{
|
||||
// if found, trade it
|
||||
MarketOrder(atmContract.Symbol, 1);
|
||||
MarketOnCloseOrder(atmContract.Symbol, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Order fill event handler. On an order fill update the resulting information is passed to
|
||||
/// this method.
|
||||
/// </summary>
|
||||
/// <param name="orderEvent">Order event details containing details of the evemts</param>
|
||||
/// <remarks>
|
||||
/// This method can be called asynchronously and so should only be used by seasoned C#
|
||||
/// experts. Ensure you use proper locks on thread-unsafe objects
|
||||
/// </remarks>
|
||||
public override void OnOrderEvent(OrderEvent orderEvent)
|
||||
{
|
||||
Log(orderEvent.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean
|
||||
/// repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = false;
|
||||
|
||||
/// <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%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "0"},
|
||||
{"Tracking Error", "0"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$2.00"},
|
||||
{"Fitness Score", "0"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "0"},
|
||||
{"Return Over Maximum Drawdown", "0"},
|
||||
{"Portfolio Turnover", "0"},
|
||||
{"Total Insights Generated", "0"},
|
||||
{"Total Insights Closed", "0"},
|
||||
{"Total Insights Analysis Completed", "0"},
|
||||
{"Long Insight Count", "0"},
|
||||
{"Short Insight Count", "0"},
|
||||
{"Long/Short Ratio", "100%"},
|
||||
{"Estimated Monthly Alpha Value", "$0"},
|
||||
{"Total Accumulated Estimated Alpha Value", "$0"},
|
||||
{"Mean Population Estimated Insight Value", "$0"},
|
||||
{"Mean Population Direction", "0%"},
|
||||
{"Mean Population Magnitude", "0%"},
|
||||
{"Rolling Averaged Population Direction", "0%"},
|
||||
{"Rolling Averaged Population Magnitude", "0%"},
|
||||
{"OrderListHash", "1130102123"}
|
||||
};
|
||||
}
|
||||
}
|
||||
111
Algorithm.CSharp/SetHoldingsRegressionAlgorithm.cs
Normal file
111
Algorithm.CSharp/SetHoldingsRegressionAlgorithm.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.CSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Regression algorithm testing the SetHolding trading API precision
|
||||
/// </summary>
|
||||
public class SetHoldingsRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
SetStartDate(2013, 10, 07);
|
||||
SetEndDate(2013, 10, 08);
|
||||
AddEquity("SPY", Resolution.Minute);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
/// </summary>
|
||||
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
|
||||
public override void OnData(Slice data)
|
||||
{
|
||||
if (!Portfolio.Invested)
|
||||
{
|
||||
SetHoldings("SPY", 0.1m);
|
||||
SetHoldings("SPY", 0.2d);
|
||||
SetHoldings("SPY", 0.3f);
|
||||
SetHoldings("SPY", 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
|
||||
/// </summary>
|
||||
public bool CanRunLocally { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the regression test system to indicate which languages this algorithm is written in.
|
||||
/// </summary>
|
||||
public 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", "4"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "0%"},
|
||||
{"Compounding Annual Return", "0%"},
|
||||
{"Drawdown", "0%"},
|
||||
{"Expectancy", "0"},
|
||||
{"Net Profit", "0%"},
|
||||
{"Sharpe Ratio", "0"},
|
||||
{"Probabilistic Sharpe Ratio", "0%"},
|
||||
{"Loss Rate", "0%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "0"},
|
||||
{"Beta", "0"},
|
||||
{"Annual Standard Deviation", "0"},
|
||||
{"Annual Variance", "0"},
|
||||
{"Information Ratio", "0"},
|
||||
{"Tracking Error", "0"},
|
||||
{"Treynor Ratio", "0"},
|
||||
{"Total Fees", "$5.41"},
|
||||
{"Estimated Strategy Capacity", "$2800000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Fitness Score", "0.995"},
|
||||
{"Kelly Criterion Estimate", "0"},
|
||||
{"Kelly Criterion Probability Value", "0"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
|
||||
{"Portfolio Turnover", "0.995"},
|
||||
{"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", "211aa90fef127ec5652eff1b3d2b8ca8"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -73,34 +73,34 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
|
||||
{
|
||||
{"Total Trades", "7"},
|
||||
{"Total Trades", "5"},
|
||||
{"Average Win", "0%"},
|
||||
{"Average Loss", "-0.35%"},
|
||||
{"Compounding Annual Return", "239.778%"},
|
||||
{"Drawdown", "2.300%"},
|
||||
{"Average Loss", "-0.76%"},
|
||||
{"Compounding Annual Return", "280.877%"},
|
||||
{"Drawdown", "2.200%"},
|
||||
{"Expectancy", "-1"},
|
||||
{"Net Profit", "1.576%"},
|
||||
{"Sharpe Ratio", "7.724"},
|
||||
{"Probabilistic Sharpe Ratio", "65.265%"},
|
||||
{"Net Profit", "1.724%"},
|
||||
{"Sharpe Ratio", "9.01"},
|
||||
{"Probabilistic Sharpe Ratio", "67.047%"},
|
||||
{"Loss Rate", "100%"},
|
||||
{"Win Rate", "0%"},
|
||||
{"Profit-Loss Ratio", "0"},
|
||||
{"Alpha", "-0.271"},
|
||||
{"Beta", "1.028"},
|
||||
{"Annual Standard Deviation", "0.229"},
|
||||
{"Annual Variance", "0.052"},
|
||||
{"Information Ratio", "-24.894"},
|
||||
{"Tracking Error", "0.009"},
|
||||
{"Treynor Ratio", "1.719"},
|
||||
{"Total Fees", "$24.08"},
|
||||
{"Estimated Strategy Capacity", "$18000000.00"},
|
||||
{"Alpha", "0.026"},
|
||||
{"Beta", "1.012"},
|
||||
{"Annual Standard Deviation", "0.226"},
|
||||
{"Annual Variance", "0.051"},
|
||||
{"Information Ratio", "3.929"},
|
||||
{"Tracking Error", "0.013"},
|
||||
{"Treynor Ratio", "2.008"},
|
||||
{"Total Fees", "$17.21"},
|
||||
{"Estimated Strategy Capacity", "$29000000.00"},
|
||||
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
|
||||
{"Fitness Score", "0.999"},
|
||||
{"Kelly Criterion Estimate", "38.796"},
|
||||
{"Kelly Criterion Probability Value", "0.228"},
|
||||
{"Sortino Ratio", "79228162514264337593543950335"},
|
||||
{"Return Over Maximum Drawdown", "68.799"},
|
||||
{"Portfolio Turnover", "1.748"},
|
||||
{"Return Over Maximum Drawdown", "91.3"},
|
||||
{"Portfolio Turnover", "1.241"},
|
||||
{"Total Insights Generated", "100"},
|
||||
{"Total Insights Closed", "99"},
|
||||
{"Total Insights Analysis Completed", "99"},
|
||||
@@ -114,7 +114,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
{"Mean Population Magnitude", "53.5354%"},
|
||||
{"Rolling Averaged Population Direction", "58.2788%"},
|
||||
{"Rolling Averaged Population Magnitude", "58.2788%"},
|
||||
{"OrderListHash", "4e7e8421606feccde05e3fcd3aa6b459"}
|
||||
{"OrderListHash", "1d1c126b61eb07c291b0e451864a7481"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,16 +42,7 @@ namespace QuantConnect.Algorithm.CSharp
|
||||
SetCash(100*1000);
|
||||
|
||||
// add universe for the top 50 stocks by dollar volume
|
||||
AddUniverse(Universe.DollarVolume.Top(50));
|
||||
|
||||
// add universe for the bottom 50 stocks by dollar volume
|
||||
AddUniverse(Universe.DollarVolume.Bottom(50));
|
||||
|
||||
// add universe for the 90th dollar volume percentile
|
||||
AddUniverse(Universe.DollarVolume.Percentile(90));
|
||||
|
||||
// add universe for stocks between the 70th and 80th dollar volume percentile
|
||||
AddUniverse(Universe.DollarVolume.Percentile(70, 80));
|
||||
AddUniverse(Universe.Top(50));
|
||||
}
|
||||
|
||||
public void OnData(TradeBars data)
|
||||
|
||||
@@ -11,18 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
AddReference("QuantConnect.Indicators")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Indicators import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Alphas import *
|
||||
from datetime import timedelta
|
||||
from AlgorithmImports import *
|
||||
from enum import Enum
|
||||
|
||||
class BasePairsTradingAlphaModel(AlphaModel):
|
||||
@@ -182,4 +171,4 @@ class BasePairsTradingAlphaModel(AlphaModel):
|
||||
# creates a group id and set the GroupId property on each insight object
|
||||
return Insight.Group(longAsset1, shortAsset2)
|
||||
|
||||
return []
|
||||
return []
|
||||
|
||||
@@ -11,16 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Alphas import AlphaModel, Insight, InsightType, InsightDirection
|
||||
|
||||
from AlgorithmImports import *
|
||||
|
||||
class ConstantAlphaModel(AlphaModel):
|
||||
''' Provides an implementation of IAlphaModel that always returns the same insight for each security'''
|
||||
@@ -106,4 +97,4 @@ def strfdelta(tdelta):
|
||||
d = tdelta.days
|
||||
h, rem = divmod(tdelta.seconds, 3600)
|
||||
m, s = divmod(rem, 60)
|
||||
return "{}.{:02d}:{:02d}:{:02d}".format(d,h,m,s)
|
||||
return "{}.{:02d}:{:02d}:{:02d}".format(d,h,m,s)
|
||||
|
||||
@@ -11,18 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
AddReference("QuantConnect.Indicators")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Indicators import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Alphas import *
|
||||
|
||||
from AlgorithmImports import *
|
||||
|
||||
class EmaCrossAlphaModel(AlphaModel):
|
||||
'''Alpha model that uses an EMA cross to create insights'''
|
||||
@@ -102,4 +91,4 @@ class SymbolData:
|
||||
|
||||
@property
|
||||
def SlowIsOverFast(self):
|
||||
return not self.FastIsOverSlow
|
||||
return not self.FastIsOverSlow
|
||||
|
||||
@@ -11,15 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
AddReference("QuantConnect.Indicators")
|
||||
AddReference("QuantConnect.Common")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Indicators import *
|
||||
from QuantConnect.Algorithm.Framework.Alphas import *
|
||||
from datetime import timedelta
|
||||
from AlgorithmImports import *
|
||||
|
||||
class HistoricalReturnsAlphaModel(AlphaModel):
|
||||
'''Uses Historical returns to create insights.'''
|
||||
|
||||
@@ -11,18 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
AddReference("QuantConnect.Indicators")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Indicators import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Alphas import *
|
||||
|
||||
from AlgorithmImports import *
|
||||
|
||||
class MacdAlphaModel(AlphaModel):
|
||||
'''Defines a custom alpha model that uses MACD crossovers. The MACD signal line
|
||||
|
||||
@@ -11,19 +11,9 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
AddReference("QuantConnect.Indicators")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Indicators import *
|
||||
from QuantConnect.Algorithm.Framework.Alphas import *
|
||||
from AlgorithmImports import *
|
||||
from Alphas.BasePairsTradingAlphaModel import BasePairsTradingAlphaModel
|
||||
from datetime import timedelta
|
||||
from scipy.stats import pearsonr
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
class PearsonCorrelationPairsTradingAlphaModel(BasePairsTradingAlphaModel):
|
||||
''' This alpha model is designed to rank every pair combination by its pearson correlation
|
||||
@@ -114,4 +104,4 @@ class PearsonCorrelationPairsTradingAlphaModel(BasePairsTradingAlphaModel):
|
||||
|
||||
df = pd.DataFrame(series_dict).dropna()
|
||||
|
||||
return (df - df.shift(1)).dropna()
|
||||
return (df - df.shift(1)).dropna()
|
||||
|
||||
@@ -11,20 +11,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
AddReference("QuantConnect.Indicators")
|
||||
AddReference("QuantConnect.Logging")
|
||||
AddReference("QuantConnect.Common")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Indicators import *
|
||||
from QuantConnect.Logging import Log
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Alphas import *
|
||||
from datetime import timedelta
|
||||
from AlgorithmImports import *
|
||||
from QuantConnect.Logging import *
|
||||
from enum import Enum
|
||||
|
||||
class RsiAlphaModel(AlphaModel):
|
||||
@@ -137,4 +125,4 @@ class State(Enum):
|
||||
'''Defines the state. This is used to prevent signal spamming and aid in bounce detection.'''
|
||||
TrippedLow = 0
|
||||
Middle = 1
|
||||
TrippedHigh = 2
|
||||
TrippedHigh = 2
|
||||
|
||||
@@ -11,19 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from System import *
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Orders import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Execution import *
|
||||
from QuantConnect.Algorithm.Framework.Portfolio import *
|
||||
from AlgorithmImports import *
|
||||
|
||||
class SpreadExecutionModel(ExecutionModel):
|
||||
'''Execution model that submits orders while the current spread is tight.
|
||||
|
||||
@@ -11,25 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Indicators")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from System import *
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Indicators import *
|
||||
from QuantConnect.Data import *
|
||||
from QuantConnect.Data.Market import *
|
||||
from QuantConnect.Orders import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Execution import *
|
||||
from QuantConnect.Algorithm.Framework.Portfolio import *
|
||||
import numpy as np
|
||||
|
||||
from AlgorithmImports import *
|
||||
|
||||
class StandardDeviationExecutionModel(ExecutionModel):
|
||||
'''Execution model that submits orders while the current market prices is at least the configured number of standard
|
||||
|
||||
@@ -11,26 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Indicators")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from System import *
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Indicators import *
|
||||
from QuantConnect.Data import *
|
||||
from QuantConnect.Data.Market import *
|
||||
from QuantConnect.Orders import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Execution import *
|
||||
from QuantConnect.Algorithm.Framework.Portfolio import *
|
||||
import numpy as np
|
||||
from datetime import datetime
|
||||
|
||||
from AlgorithmImports import *
|
||||
|
||||
class VolumeWeightedAveragePriceExecutionModel(ExecutionModel):
|
||||
'''Execution model that submits orders while the current market price is more favorable that the current volume weighted average price.'''
|
||||
@@ -174,4 +155,4 @@ class IntradayVwap:
|
||||
averagePrice = float(input.High + input.Low + input.Close) / 3
|
||||
return True, float(input.Volume), averagePrice
|
||||
|
||||
return False, 0.0, 0.0
|
||||
return False, 0.0, 0.0
|
||||
|
||||
@@ -11,11 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect.Algorithm.Framework.Alphas import *
|
||||
from AlgorithmImports import *
|
||||
from Portfolio.EqualWeightingPortfolioConstructionModel import *
|
||||
|
||||
class AccumulativeInsightPortfolioConstructionModel(EqualWeightingPortfolioConstructionModel):
|
||||
|
||||
@@ -11,26 +11,9 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Logging")
|
||||
AddReference("QuantConnect.Indicators")
|
||||
|
||||
from System import *
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Indicators import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Logging import Log
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Alphas import *
|
||||
from QuantConnect.Algorithm.Framework.Portfolio import *
|
||||
from AlgorithmImports import *
|
||||
from Portfolio.MaximumSharpeRatioPortfolioOptimizer import MaximumSharpeRatioPortfolioOptimizer
|
||||
from datetime import datetime, timedelta
|
||||
from itertools import groupby
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from numpy import dot, transpose
|
||||
from numpy.linalg import inv
|
||||
|
||||
|
||||
@@ -11,12 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Algorithm.Framework.Portfolio import *
|
||||
from AlgorithmImports import *
|
||||
from InsightWeightingPortfolioConstructionModel import InsightWeightingPortfolioConstructionModel
|
||||
|
||||
class ConfidenceWeightedPortfolioConstructionModel(InsightWeightingPortfolioConstructionModel):
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Logging;
|
||||
using QuantConnect.Securities;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
@@ -89,7 +90,16 @@ namespace QuantConnect.Algorithm.Framework.Portfolio
|
||||
{
|
||||
foreach (var portfolioTarget in _targetsPerSymbol.Values)
|
||||
{
|
||||
yield return portfolioTarget;
|
||||
if (algorithm.Securities.ContainsKey(portfolioTarget.Symbol))
|
||||
{
|
||||
yield return portfolioTarget;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this could happen if the algorithm has not yet added a security used by an alpha
|
||||
Log.Error("EqualWeightingAlphaStreamsPortfolioConstructionModel.CreateTargets(): " +
|
||||
$"Skip emitting portfolio target, security not found in algorithm {portfolioTarget.Symbol}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -123,7 +133,8 @@ namespace QuantConnect.Algorithm.Framework.Portfolio
|
||||
_rebalance = true;
|
||||
_targetsPerSymbolPerAlpha[security.Symbol] = new Dictionary<Symbol, PortfolioTarget>();
|
||||
|
||||
var lastState = algorithm.History<AlphaStreamsPortfolioState>(security.Symbol, TimeSpan.FromDays(1)).LastOrDefault();
|
||||
var lastState = security.Cache.GetData<AlphaStreamsPortfolioState>();
|
||||
lastState ??= algorithm.GetLastKnownPrices(security).OfType<AlphaStreamsPortfolioState>().LastOrDefault();
|
||||
if (lastState != null)
|
||||
{
|
||||
// keep the last state per alpha
|
||||
@@ -213,6 +224,7 @@ namespace QuantConnect.Algorithm.Framework.Portfolio
|
||||
}
|
||||
}
|
||||
|
||||
List<Symbol> symbolsToRemove = null;
|
||||
// We adjust existing targets for symbols that got removed from this alpha
|
||||
foreach (var removedTarget in ourExistingTargets.Values.Where(target => !newTargets.ContainsKey(target.Symbol)))
|
||||
{
|
||||
@@ -224,7 +236,8 @@ namespace QuantConnect.Algorithm.Framework.Portfolio
|
||||
newAggregatedTarget = new PortfolioTarget(symbol, quantity.DiscretelyRoundBy(_unitQuantity[symbol], MidpointRounding.ToZero));
|
||||
}
|
||||
|
||||
ourExistingTargets.Remove(symbol);
|
||||
symbolsToRemove ??= new List<Symbol>();
|
||||
symbolsToRemove.Add(symbol);
|
||||
if (existingAggregatedTarget == null || existingAggregatedTarget.Quantity != newAggregatedTarget.Quantity)
|
||||
{
|
||||
updatedTargets = true;
|
||||
@@ -232,6 +245,15 @@ namespace QuantConnect.Algorithm.Framework.Portfolio
|
||||
}
|
||||
}
|
||||
|
||||
if (symbolsToRemove != null)
|
||||
{
|
||||
for (var i = 0; i < symbolsToRemove.Count; i++)
|
||||
{
|
||||
// we can't remove from dictionary while iterating through it
|
||||
ourExistingTargets.Remove(symbolsToRemove[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return updatedTargets;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,15 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Algorithm.Framework.Alphas import *
|
||||
from QuantConnect.Algorithm.Framework.Portfolio import *
|
||||
from itertools import groupby
|
||||
from datetime import datetime, timedelta
|
||||
from AlgorithmImports import *
|
||||
|
||||
class EqualWeightingPortfolioConstructionModel(PortfolioConstructionModel):
|
||||
'''Provides an implementation of IPortfolioConstructionModel that gives equal weighting to all securities.
|
||||
|
||||
@@ -11,12 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Algorithm.Framework.Alphas import *
|
||||
from AlgorithmImports import *
|
||||
from EqualWeightingPortfolioConstructionModel import EqualWeightingPortfolioConstructionModel, PortfolioBias
|
||||
|
||||
class InsightWeightingPortfolioConstructionModel(EqualWeightingPortfolioConstructionModel):
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from AlgorithmImports import *
|
||||
from scipy.optimize import minimize
|
||||
|
||||
### <summary>
|
||||
@@ -94,4 +93,4 @@ class MaximumSharpeRatioPortfolioOptimizer:
|
||||
|
||||
def get_budget_constraint(self, weights):
|
||||
'''Defines a budget constraint: the sum of the weights equals unity'''
|
||||
return np.sum(weights) - 1
|
||||
return np.sum(weights) - 1
|
||||
|
||||
@@ -11,23 +11,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Indicators")
|
||||
|
||||
from System import *
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Indicators import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Portfolio import *
|
||||
from AlgorithmImports import *
|
||||
from Portfolio.MinimumVariancePortfolioOptimizer import MinimumVariancePortfolioOptimizer
|
||||
from datetime import timedelta
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
### <summary>
|
||||
### Provides an implementation of Mean-Variance portfolio optimization based on modern portfolio theory.
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from AlgorithmImports import *
|
||||
from scipy.optimize import minimize
|
||||
|
||||
### <summary>
|
||||
|
||||
@@ -11,14 +11,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect import Resolution
|
||||
from QuantConnect.Algorithm.Framework.Alphas import *
|
||||
from AlgorithmImports import *
|
||||
from EqualWeightingPortfolioConstructionModel import EqualWeightingPortfolioConstructionModel
|
||||
from itertools import groupby
|
||||
|
||||
class SectorWeightingPortfolioConstructionModel(EqualWeightingPortfolioConstructionModel):
|
||||
'''Provides an implementation of IPortfolioConstructionModel that
|
||||
@@ -105,4 +99,4 @@ class SectorWeightingPortfolioConstructionModel(EqualWeightingPortfolioConstruct
|
||||
Other sectors can be defined using AssetClassification'''
|
||||
fundamentals = security.Fundamentals
|
||||
companyReference = security.Fundamentals.CompanyReference if fundamentals else None
|
||||
return companyReference.IndustryTemplateCode if companyReference else None
|
||||
return companyReference.IndustryTemplateCode if companyReference else None
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.5" />
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.6" />
|
||||
<PackageReference Include="Accord" Version="3.6.0" />
|
||||
<PackageReference Include="Accord.Math" Version="3.6.0" />
|
||||
<PackageReference Include="Accord.Statistics" Version="3.6.0" />
|
||||
|
||||
@@ -11,17 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Portfolio import *
|
||||
from QuantConnect.Algorithm.Framework.Risk import *
|
||||
from AlgorithmImports import *
|
||||
|
||||
class MaximumDrawdownPercentPerSecurity(RiskManagementModel):
|
||||
'''Provides an implementation of IRiskManagementModel that limits the drawdown per holding to the specified percentage'''
|
||||
|
||||
@@ -11,17 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Portfolio import *
|
||||
from QuantConnect.Algorithm.Framework.Risk import *
|
||||
from AlgorithmImports import *
|
||||
|
||||
class MaximumDrawdownPercentPortfolio(RiskManagementModel):
|
||||
'''Provides an implementation of IRiskManagementModel that limits the drawdown of the portfolio to the specified percentage.'''
|
||||
|
||||
@@ -11,16 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Portfolio import *
|
||||
from QuantConnect.Algorithm.Framework.Risk import *
|
||||
from AlgorithmImports import *
|
||||
from itertools import groupby
|
||||
|
||||
class MaximumSectorExposureRiskManagementModel(RiskManagementModel):
|
||||
|
||||
@@ -11,17 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Portfolio import *
|
||||
from QuantConnect.Algorithm.Framework.Risk import *
|
||||
from AlgorithmImports import *
|
||||
|
||||
class MaximumUnrealizedProfitPercentPerSecurity(RiskManagementModel):
|
||||
'''Provides an implementation of IRiskManagementModel that limits the unrealized profit per holding to the specified percentage'''
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace QuantConnect.Algorithm.Framework.Risk
|
||||
public class TrailingStopRiskManagementModel : RiskManagementModel
|
||||
{
|
||||
private readonly decimal _maximumDrawdownPercent;
|
||||
private Dictionary<Symbol, decimal> _trailingHighs = new Dictionary<Symbol, decimal>();
|
||||
private readonly Dictionary<Symbol, decimal> _trailing = new Dictionary<Symbol, decimal>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TrailingStopRiskManagementModel"/> class
|
||||
@@ -35,7 +35,7 @@ namespace QuantConnect.Algorithm.Framework.Risk
|
||||
/// <param name="maximumDrawdownPercent">The maximum percentage relative drawdown allowed for algorithm portfolio compared with the highest unrealized profit, defaults to 5% drawdown per security</param>
|
||||
public TrailingStopRiskManagementModel(decimal maximumDrawdownPercent = 0.05m)
|
||||
{
|
||||
_maximumDrawdownPercent = -Math.Abs(maximumDrawdownPercent);
|
||||
_maximumDrawdownPercent = Math.Abs(maximumDrawdownPercent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -53,32 +53,32 @@ namespace QuantConnect.Algorithm.Framework.Risk
|
||||
// Remove if not invested
|
||||
if (!security.Invested)
|
||||
{
|
||||
if (_trailingHighs.ContainsKey(symbol))
|
||||
if (_trailing.ContainsKey(symbol))
|
||||
{
|
||||
_trailingHighs.Remove(symbol);
|
||||
_trailing.Remove(symbol);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add newly invested securities
|
||||
if (!_trailingHighs.ContainsKey(symbol))
|
||||
var profitPercent = security.Holdings.UnrealizedProfitPercent;
|
||||
|
||||
decimal value;
|
||||
if (!_trailing.TryGetValue(symbol, out value))
|
||||
{
|
||||
_trailingHighs.Add(symbol, security.Holdings.AveragePrice); // Set to average holding cost
|
||||
var newValue = profitPercent > 0 ? profitPercent : 0;
|
||||
_trailing.Add(symbol, newValue);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for new highs and update - set to tradebar high
|
||||
if (_trailingHighs[symbol] < security.High)
|
||||
// Check for new high and update
|
||||
if (value < profitPercent)
|
||||
{
|
||||
_trailingHighs[symbol] = security.High;
|
||||
_trailing[symbol] = profitPercent;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for securities past the drawdown limit
|
||||
var securityHigh = _trailingHighs[symbol];
|
||||
var drawdown = (security.Low / securityHigh) - 1m;
|
||||
|
||||
if (drawdown < _maximumDrawdownPercent)
|
||||
// If unrealized profit percent deviates from local max for more than affordable percentage
|
||||
if (profitPercent < value - _maximumDrawdownPercent)
|
||||
{
|
||||
// liquidate
|
||||
yield return new PortfolioTarget(security.Symbol, 0);
|
||||
@@ -86,4 +86,4 @@ namespace QuantConnect.Algorithm.Framework.Risk
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,17 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Portfolio import *
|
||||
from QuantConnect.Algorithm.Framework.Risk import *
|
||||
from AlgorithmImports import *
|
||||
|
||||
class TrailingStopRiskManagementModel(RiskManagementModel):
|
||||
'''Provides an implementation of IRiskManagementModel that limits the maximum possible loss
|
||||
@@ -30,8 +20,8 @@ class TrailingStopRiskManagementModel(RiskManagementModel):
|
||||
'''Initializes a new instance of the TrailingStopRiskManagementModel class
|
||||
Args:
|
||||
maximumDrawdownPercent: The maximum percentage drawdown allowed for algorithm portfolio compared with the highest unrealized profit, defaults to 5% drawdown'''
|
||||
self.maximumDrawdownPercent = -abs(maximumDrawdownPercent)
|
||||
self.trailingHighs = dict()
|
||||
self.maximumDrawdownPercent = abs(maximumDrawdownPercent)
|
||||
self.trailing = dict()
|
||||
|
||||
def ManageRisk(self, algorithm, targets):
|
||||
'''Manages the algorithm's risk at each time step
|
||||
@@ -46,24 +36,25 @@ class TrailingStopRiskManagementModel(RiskManagementModel):
|
||||
|
||||
# Remove if not invested
|
||||
if not security.Invested:
|
||||
self.trailingHighs.pop(symbol, None)
|
||||
self.trailing.pop(symbol, None)
|
||||
continue
|
||||
|
||||
profitPercent = security.Holdings.UnrealizedProfitPercent
|
||||
|
||||
# Add newly invested securities
|
||||
if symbol not in self.trailingHighs:
|
||||
self.trailingHighs[symbol] = security.Holdings.AveragePrice # Set to average holding cost
|
||||
value = self.trailing.get(symbol)
|
||||
if value == None:
|
||||
newValue = profitPercent if profitPercent > 0 else 0
|
||||
self.trailing[symbol] = newValue
|
||||
continue
|
||||
|
||||
# Check for new highs and update - set to tradebar high
|
||||
if self.trailingHighs[symbol] < security.High:
|
||||
self.trailingHighs[symbol] = security.High
|
||||
# Check for new high and update
|
||||
if value < profitPercent:
|
||||
self.trailing[symbol] = profitPercent
|
||||
continue
|
||||
|
||||
# Check for securities past the drawdown limit
|
||||
securityHigh = self.trailingHighs[symbol]
|
||||
drawdown = (security.Low / securityHigh) - 1
|
||||
|
||||
if drawdown < self.maximumDrawdownPercent:
|
||||
# If unrealized profit percent deviates from local max for more than affordable percentage
|
||||
if profitPercent < value - self.maximumDrawdownPercent:
|
||||
# liquidate
|
||||
riskAdjustedTargets.append(PortfolioTarget(symbol, 0))
|
||||
|
||||
|
||||
@@ -11,14 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Indicators")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect.Data.UniverseSelection import *
|
||||
from QuantConnect.Indicators import *
|
||||
from AlgorithmImports import *
|
||||
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel
|
||||
|
||||
class EmaCrossUniverseSelectionModel(FundamentalUniverseSelectionModel):
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace QuantConnect.Algorithm.Framework.Selection
|
||||
|
||||
/// <summary>
|
||||
/// Creates the coarse fundamental universe object.
|
||||
/// This is provided to allow more flexibility when creating coarse universe, such as using algorithm.Universe.DollarVolume.Top(5)
|
||||
/// This is provided to allow more flexibility when creating coarse universe.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <returns>The coarse fundamental universe</returns>
|
||||
|
||||
@@ -11,12 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect.Data.UniverseSelection import *
|
||||
from AlgorithmImports import *
|
||||
|
||||
class FundamentalUniverseSelectionModel:
|
||||
'''Provides a base class for defining equity coarse/fine fundamental selection models'''
|
||||
@@ -46,7 +41,7 @@ class FundamentalUniverseSelectionModel:
|
||||
|
||||
def CreateCoarseFundamentalUniverse(self, algorithm):
|
||||
'''Creates the coarse fundamental universe object.
|
||||
This is provided to allow more flexibility when creating coarse universe, such as using algorithm.Universe.DollarVolume.Top(5)
|
||||
This is provided to allow more flexibility when creating coarse universe.
|
||||
Args:
|
||||
algorithm: The algorithm instance
|
||||
Returns:
|
||||
@@ -85,4 +80,4 @@ class FundamentalUniverseSelectionModel:
|
||||
fine: The fine fundamental data used to perform filtering
|
||||
Returns:
|
||||
An enumerable of symbols passing the filter'''
|
||||
return [f.Symbol for f in fine]
|
||||
return [f.Symbol for f in fine]
|
||||
|
||||
@@ -11,18 +11,10 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
from AlgorithmImports import *
|
||||
from clr import GetClrType as typeof
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Securities import *
|
||||
from QuantConnect.Data.Auxiliary import *
|
||||
from QuantConnect.Data.UniverseSelection import *
|
||||
from Selection.UniverseSelectionModel import UniverseSelectionModel
|
||||
from datetime import datetime
|
||||
|
||||
class FutureUniverseSelectionModel(UniverseSelectionModel):
|
||||
'''Provides an implementation of IUniverseSelectionMode that subscribes to future chains'''
|
||||
|
||||
@@ -11,18 +11,9 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
from AlgorithmImports import *
|
||||
from clr import GetClrType as typeof
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Securities import *
|
||||
from QuantConnect.Data.Auxiliary import *
|
||||
from QuantConnect.Data.UniverseSelection import *
|
||||
from Selection.UniverseSelectionModel import UniverseSelectionModel
|
||||
from datetime import datetime
|
||||
|
||||
class OptionUniverseSelectionModel(UniverseSelectionModel):
|
||||
'''Provides an implementation of IUniverseSelectionMode that subscribes to option chains'''
|
||||
|
||||
@@ -11,12 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect.Data.UniverseSelection import *
|
||||
from AlgorithmImports import *
|
||||
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel
|
||||
from itertools import groupby
|
||||
from math import ceil
|
||||
@@ -87,4 +82,4 @@ class QC500UniverseSelectionModel(FundamentalUniverseSelectionModel):
|
||||
sortedByDollarVolume.extend(y[:c])
|
||||
|
||||
sortedByDollarVolume = sorted(sortedByDollarVolume, key = lambda x: self.dollarVolumeBySymbol[x.Symbol], reverse=True)
|
||||
return [x.Symbol for x in sortedByDollarVolume[:self.numberOfSymbolsFine]]
|
||||
return [x.Symbol for x in sortedByDollarVolume[:self.numberOfSymbolsFine]]
|
||||
|
||||
@@ -11,17 +11,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
AddReference("QuantConnect.Common")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Indicators import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from AlgorithmImports import *
|
||||
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel
|
||||
import pandas as pd
|
||||
|
||||
class UncorrelatedUniverseSelectionModel(FundamentalUniverseSelectionModel):
|
||||
'''This universe selection model picks stocks that currently have their correlation to a benchmark deviated from the mean.'''
|
||||
|
||||
57
Algorithm.Python/BasicTemplateAtreyuAlgorithm.py
Normal file
57
Algorithm.Python/BasicTemplateAtreyuAlgorithm.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# 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 template algorithm for the Atreyu brokerage
|
||||
### </summary>
|
||||
### <meta name="tag" content="using data" />
|
||||
### <meta name="tag" content="using quantconnect" />
|
||||
### <meta name="tag" content="trading and orders" />
|
||||
class BasicTemplateAtreyuAlgorithm(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,10, 7) #Set Start Date
|
||||
self.SetEndDate(2013,10,11) #Set End Date
|
||||
self.SetCash(100000) #Set Strategy Cash
|
||||
|
||||
self.SetBrokerageModel(BrokerageName.Atreyu)
|
||||
self.AddEquity("SPY", Resolution.Minute)
|
||||
|
||||
self.DefaultOrderProperties = AtreyuOrderProperties()
|
||||
# Can specify the default exchange to execute an order on.
|
||||
# If not specified will default to the primary exchange
|
||||
self.DefaultOrderProperties.Exchange = Exchange.NASDAQ
|
||||
# Currently only support order for the day
|
||||
self.DefaultOrderProperties.TimeInForce = TimeInForce.Day
|
||||
|
||||
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
|
||||
'''
|
||||
if not self.Portfolio.Invested:
|
||||
# will set 25% of our buying power with a market order that will be routed to exchange set in the default order properties (NASDAQ)
|
||||
self.SetHoldings("SPY", 0.25)
|
||||
# will increase our SPY holdings to 50% of our buying power with a market order that will be routed to ARCA
|
||||
|
||||
orderProperties = AtreyuOrderProperties()
|
||||
orderProperties.Exchange = Exchange.ARCA
|
||||
self.SetHoldings("SPY", 0.50, orderProperties = orderProperties)
|
||||
|
||||
self.Debug("Purchased SPY!")
|
||||
@@ -33,4 +33,4 @@ class ConstituentsQC500GeneratorAlgorithm(QCAlgorithm):
|
||||
self.SetCash(100000) # Set Strategy Cash
|
||||
|
||||
# Add QC500 Universe
|
||||
self.AddUniverse(self.Universe.Index.QC500)
|
||||
self.AddUniverse(self.Universe.QC500)
|
||||
|
||||
@@ -33,7 +33,7 @@ class ETFConstituentUniverseCompositeDelistingRegressionAlgorithm(QCAlgorithm):
|
||||
self.aapl = self.AddEquity("AAPL", Resolution.Hour).Symbol
|
||||
self.gdvd = self.AddEquity("GDVD", Resolution.Hour).Symbol
|
||||
|
||||
self.AddUniverse(ETFConstituentsUniverse(self.gdvd, self.UniverseSettings, self.FilterETFs))
|
||||
self.AddUniverse(self.Universe.ETF(self.gdvd, self.UniverseSettings, self.FilterETFs))
|
||||
|
||||
def FilterETFs(self, constituents):
|
||||
if self.UtcTime.date() > self.delistingDate:
|
||||
|
||||
@@ -33,7 +33,7 @@ class ETFConstituentUniverseCompositeDelistingRegressionAlgorithmNoAddEquityETF(
|
||||
self.aapl = self.AddEquity("AAPL", Resolution.Hour).Symbol
|
||||
self.gdvd = Symbol.Create("GDVD", SecurityType.Equity, Market.USA)
|
||||
|
||||
self.AddUniverse(ETFConstituentsUniverse(self.gdvd, self.UniverseSettings, self.FilterETFs))
|
||||
self.AddUniverse(self.Universe.ETF(self.gdvd, self.UniverseSettings, self.FilterETFs))
|
||||
|
||||
def FilterETFs(self, constituents):
|
||||
if self.UtcTime.date() > self.delistingDate:
|
||||
|
||||
@@ -35,7 +35,7 @@ class ETFConstituentUniverseFilterFunctionRegressionAlgorithm(QCAlgorithm):
|
||||
self.spy = self.AddEquity("SPY", Resolution.Hour).Symbol
|
||||
self.aapl = Symbol.Create("AAPL", SecurityType.Equity, Market.USA)
|
||||
|
||||
self.AddUniverse(ETFConstituentsUniverse(self.spy, self.UniverseSettings, self.FilterETFs))
|
||||
self.AddUniverse(self.Universe.ETF(self.spy, self.UniverseSettings, self.FilterETFs))
|
||||
|
||||
def FilterETFs(self, constituents):
|
||||
constituentsData = list(constituents)
|
||||
@@ -108,4 +108,4 @@ class ETFConstituentUniverseFilterFunctionRegressionAlgorithm(QCAlgorithm):
|
||||
raise Exception("Security changes never propagated to the algorithm")
|
||||
|
||||
if not self.receivedData:
|
||||
raise Exception("Data was never loaded for the S&P 500 constituent AAPL")
|
||||
raise Exception("Data was never loaded for the S&P 500 constituent AAPL")
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import typing
|
||||
from AlgorithmImports import *
|
||||
|
||||
constituentData = []
|
||||
|
||||
### <summary>
|
||||
### Alpha model for ETF constituents, where we generate insights based on the weighting
|
||||
### of the ETF constituent
|
||||
### </summary>
|
||||
class ETFConstituentAlphaModel(AlphaModel):
|
||||
def OnSecuritiesChanged(self, algorithm, changes):
|
||||
pass
|
||||
|
||||
### <summary>
|
||||
### Creates new insights based on constituent data and their weighting
|
||||
### in their respective ETF
|
||||
### </summary>
|
||||
def Update(self, algorithm: QCAlgorithm, data: Slice):
|
||||
insights = []
|
||||
|
||||
for constituent in constituentData:
|
||||
if constituent.Symbol not in data.Bars and \
|
||||
constituent.Symbol not in data.QuoteBars:
|
||||
|
||||
continue
|
||||
|
||||
insightDirection = InsightDirection.Up if constituent.Weight is not None and constituent.Weight >= 0.01 else InsightDirection.Down
|
||||
|
||||
insights.append(Insight(
|
||||
algorithm.UtcTime,
|
||||
constituent.Symbol,
|
||||
timedelta(days=1),
|
||||
InsightType.Price,
|
||||
insightDirection,
|
||||
float(1 * int(insightDirection)),
|
||||
1.0,
|
||||
weight=float(0 if constituent.Weight is None else constituent.Weight)
|
||||
))
|
||||
|
||||
return insights
|
||||
|
||||
### <summary>
|
||||
### Generates targets for ETF constituents, which will be set to the weighting
|
||||
### of the constituent in their respective ETF
|
||||
### </summary>
|
||||
class ETFConstituentPortfolioModel(PortfolioConstructionModel):
|
||||
def __init__(self):
|
||||
self.hasAdded = False
|
||||
|
||||
### <summary>
|
||||
### Securities changed, detects if we've got new additions to the universe
|
||||
### so that we don't try to trade every loop
|
||||
### </summary>
|
||||
def OnSecuritiesChanged(self, algorithm: QCAlgorithm, changes: SecurityChanges):
|
||||
self.hasAdded = len(changes.AddedSecurities) != 0
|
||||
|
||||
### <summary>
|
||||
### Creates portfolio targets based on the insights provided to us by the alpha model.
|
||||
### Emits portfolio targets setting the quantity to the weight of the constituent
|
||||
### in its respective ETF.
|
||||
### </summary>
|
||||
def CreateTargets(self, algorithm: QCAlgorithm, insights: typing.List[Insight]):
|
||||
if not self.hasAdded:
|
||||
return []
|
||||
|
||||
finalInsights = []
|
||||
for insight in insights:
|
||||
finalInsights.append(PortfolioTarget(insight.Symbol, float(0 if insight.Weight is None else insight.Weight)))
|
||||
self.hasAdded = False
|
||||
|
||||
return finalInsights
|
||||
|
||||
### <summary>
|
||||
### Executes based on ETF constituent weighting
|
||||
### </summary>
|
||||
class ETFConstituentExecutionModel(ExecutionModel):
|
||||
### <summary>
|
||||
### Liquidates if constituents have been removed from the universe
|
||||
### </summary>
|
||||
def OnSecuritiesChanged(self, algorithm: QCAlgorithm, changes: SecurityChanges):
|
||||
for change in changes.RemovedSecurities:
|
||||
algorithm.Liquidate(change.Symbol)
|
||||
|
||||
### <summary>
|
||||
### Creates orders for constituents that attempts to add
|
||||
### the weighting of the constituent in our portfolio. The
|
||||
### resulting algorithm portfolio weight might not be equal
|
||||
### to the leverage of the ETF (1x, 2x, 3x, etc.)
|
||||
### </summary>
|
||||
def Execute(self, algorithm: QCAlgorithm, targets: typing.List[IPortfolioTarget]):
|
||||
for target in targets:
|
||||
algorithm.SetHoldings(target.Symbol, target.Quantity)
|
||||
|
||||
### <summary>
|
||||
### Tests ETF constituents universe selection with the algorithm framework models (Alpha, PortfolioConstruction, Execution)
|
||||
### </summary>
|
||||
class ETFConstituentUniverseFrameworkRegressionAlgorithm(QCAlgorithm):
|
||||
### <summary>
|
||||
### Initializes the algorithm, setting up the framework classes and ETF constituent universe settings
|
||||
### </summary>
|
||||
def Initialize(self):
|
||||
self.SetStartDate(2020, 12, 1)
|
||||
self.SetEndDate(2021, 1, 31)
|
||||
self.SetCash(100000)
|
||||
|
||||
self.SetAlpha(ETFConstituentAlphaModel())
|
||||
self.SetPortfolioConstruction(ETFConstituentPortfolioModel())
|
||||
self.SetExecution(ETFConstituentExecutionModel())
|
||||
|
||||
spy = Symbol.Create("SPY", SecurityType.Equity, Market.USA)
|
||||
|
||||
self.UniverseSettings.Resolution = Resolution.Hour
|
||||
self.AddUniverse(self.Universe.ETF(spy, self.UniverseSettings, self.FilterETFConstituents))
|
||||
|
||||
### <summary>
|
||||
### Filters ETF constituents
|
||||
### </summary>
|
||||
### <param name="constituents">ETF constituents</param>
|
||||
### <returns>ETF constituent Symbols that we want to include in the algorithm</returns>
|
||||
def FilterETFConstituents(self, constituents):
|
||||
global constituentData
|
||||
|
||||
constituentDataLocal = [i for i in constituents if i is not None and i.Weight >= 0.001]
|
||||
constituentData = list(constituentDataLocal)
|
||||
|
||||
return [i.Symbol for i in constituentDataLocal]
|
||||
|
||||
### <summary>
|
||||
### no-op for performance
|
||||
### </summary>
|
||||
def OnData(self, data):
|
||||
pass
|
||||
@@ -33,7 +33,7 @@ class ETFConstituentUniverseFilterFunctionRegressionAlgorithm(QCAlgorithm):
|
||||
self.aapl = Symbol.Create("AAPL", SecurityType.Equity, Market.USA)
|
||||
self.qqq = self.AddEquity("QQQ", Resolution.Daily).Symbol
|
||||
|
||||
self.AddUniverse(ETFConstituentsUniverse(self.qqq, self.UniverseSettings, self.FilterETFs))
|
||||
self.AddUniverse(self.Universe.ETF(self.qqq, self.UniverseSettings, self.FilterETFs))
|
||||
|
||||
def FilterETFs(self, constituents):
|
||||
constituentSymbols = [i.Symbol for i in constituents]
|
||||
@@ -85,4 +85,4 @@ class ETFConstituentUniverseFilterFunctionRegressionAlgorithm(QCAlgorithm):
|
||||
|
||||
for constituentDate, constituentEncountered in self.constituentDataEncountered.items():
|
||||
if not constituentEncountered:
|
||||
raise Exception(f"Received data in OnData(...) but it did not contain any constituent data on {constituentDate.strftime('%Y-%m-%d %H:%M:%S.%f')}")
|
||||
raise Exception(f"Received data in OnData(...) but it did not contain any constituent data on {constituentDate.strftime('%Y-%m-%d %H:%M:%S.%f')}")
|
||||
|
||||
123
Algorithm.Python/ETFConstituentUniverseRSIAlphaModelAlgorithm.py
Normal file
123
Algorithm.Python/ETFConstituentUniverseRSIAlphaModelAlgorithm.py
Normal file
@@ -0,0 +1,123 @@
|
||||
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import typing
|
||||
|
||||
from AlgorithmImports import *
|
||||
from datetime import timedelta
|
||||
|
||||
|
||||
### <summary>
|
||||
### Example algorithm demonstrating the usage of the RSI indicator
|
||||
### in combination with ETF constituents data to replicate the weighting
|
||||
### of the ETF's assets in our own account.
|
||||
### </summary>
|
||||
class ETFConstituentUniverseRSIAlphaModelAlgorithm(QCAlgorithm):
|
||||
### <summary>
|
||||
### Initialize the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
### </summary>
|
||||
def Initialize(self):
|
||||
self.SetStartDate(2020, 12, 1)
|
||||
self.SetEndDate(2021, 1, 31)
|
||||
self.SetCash(100000)
|
||||
|
||||
self.SetAlpha(ConstituentWeightedRsiAlphaModel())
|
||||
self.SetPortfolioConstruction(InsightWeightingPortfolioConstructionModel())
|
||||
self.SetExecution(ImmediateExecutionModel())
|
||||
|
||||
spy = self.AddEquity("SPY", Resolution.Hour).Symbol
|
||||
|
||||
# We load hourly data for ETF constituents in this algorithm
|
||||
self.UniverseSettings.Resolution = Resolution.Hour
|
||||
self.Settings.MinimumOrderMarginPortfolioPercentage = 0.01
|
||||
|
||||
self.AddUniverse(self.Universe.ETF(spy, self.UniverseSettings, self.FilterETFConstituents))
|
||||
|
||||
### <summary>
|
||||
### Filters ETF constituents
|
||||
### </summary>
|
||||
### <param name="constituents">ETF constituents</param>
|
||||
### <returns>ETF constituent Symbols that we want to include in the algorithm</returns>
|
||||
def FilterETFConstituents(self, constituents):
|
||||
return [i.Symbol for i in constituents if i.Weight is not None and i.Weight >= 0.001]
|
||||
|
||||
|
||||
### <summary>
|
||||
### Alpha model making use of the RSI indicator and ETF constituent weighting to determine
|
||||
### which assets we should invest in and the direction of investment
|
||||
### </summary>
|
||||
class ConstituentWeightedRsiAlphaModel(AlphaModel):
|
||||
def __init__(self, maxTrades=None):
|
||||
self.rsiSymbolData = {}
|
||||
|
||||
def Update(self, algorithm: QCAlgorithm, data: Slice):
|
||||
algoConstituents = []
|
||||
for barSymbol in data.Bars.Keys:
|
||||
if not algorithm.Securities[barSymbol].Cache.HasData(ETFConstituentData):
|
||||
continue
|
||||
|
||||
constituentData = algorithm.Securities[barSymbol].Cache.GetData[ETFConstituentData]()
|
||||
algoConstituents.append(constituentData)
|
||||
|
||||
if len(algoConstituents) == 0 or len(data.Bars) == 0:
|
||||
# Don't do anything if we have no data we can work with
|
||||
return []
|
||||
|
||||
constituents = {i.Symbol:i for i in algoConstituents}
|
||||
|
||||
for bar in data.Bars.Values:
|
||||
if bar.Symbol not in constituents:
|
||||
# Dealing with a manually added equity, which in this case is SPY
|
||||
continue
|
||||
|
||||
if bar.Symbol not in self.rsiSymbolData:
|
||||
# First time we're initializing the RSI.
|
||||
# It won't be ready now, but it will be
|
||||
# after 7 data points
|
||||
constituent = constituents[bar.Symbol]
|
||||
self.rsiSymbolData[bar.Symbol] = SymbolData(bar.Symbol, algorithm, constituent, 7)
|
||||
|
||||
allReady = all([sd.rsi.IsReady for sd in self.rsiSymbolData.values()])
|
||||
if not allReady:
|
||||
# We're still warming up the RSI indicators.
|
||||
return []
|
||||
|
||||
insights = []
|
||||
|
||||
for symbol, symbolData in self.rsiSymbolData.items():
|
||||
averageLoss = symbolData.rsi.AverageLoss.Current.Value
|
||||
averageGain = symbolData.rsi.AverageGain.Current.Value
|
||||
|
||||
# If we've lost more than gained, then we think it's going to go down more
|
||||
direction = InsightDirection.Down if averageLoss > averageGain else InsightDirection.Up
|
||||
|
||||
# Set the weight of the insight as the weight of the ETF's
|
||||
# holding. The InsightWeightingPortfolioConstructionModel
|
||||
# will rebalance our portfolio to have the same percentage
|
||||
# of holdings in our algorithm that the ETF has.
|
||||
insights.append(Insight.Price(
|
||||
symbol,
|
||||
timedelta(days=1),
|
||||
direction,
|
||||
float(averageLoss if direction == InsightDirection.Down else averageGain),
|
||||
weight=float(symbolData.constituent.Weight)
|
||||
))
|
||||
|
||||
return insights
|
||||
|
||||
|
||||
class SymbolData:
|
||||
def __init__(self, symbol, algorithm, constituent, period):
|
||||
self.Symbol = symbol
|
||||
self.constituent = constituent
|
||||
self.rsi = algorithm.RSI(symbol, period, MovingAverageType.Exponential, Resolution.Hour)
|
||||
@@ -37,7 +37,7 @@
|
||||
<Compile Include="..\Common\Properties\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.5" />
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.6" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
@@ -77,7 +77,6 @@
|
||||
<None Include="TrainingExampleAlgorithm.py" />
|
||||
<None Include="LongOnlyAlphaStreamAlgorithm.py" />
|
||||
<None Include="CustomPartialFillModelAlgorithm.py" />
|
||||
<Content Include="BasicTemplateConstituentUniverseAlgorithm.py" />
|
||||
<Content Include="BasicTemplateOptionsConsolidationAlgorithm.py" />
|
||||
<None Include="BasicTemplateOptionsPriceModel.py" />
|
||||
<Content Include="CoarseFineOptionUniverseChainRegressionAlgorithm.py" />
|
||||
@@ -140,6 +139,8 @@
|
||||
<None Include="TensorFlowNeuralNetworkAlgorithm.py" />
|
||||
<None Include="TiingoPriceAlgorithm.py" />
|
||||
<None Include="PearsonCorrelationPairsTradingAlphaModelFrameworkAlgorithm.py" />
|
||||
<None Include="UniverseSelectionDefinitionsAlgorithm.py" />
|
||||
<None Include="ConstituentsQC500GeneratorAlgorithm.py" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="AddRemoveSecurityRegressionAlgorithm.py" />
|
||||
@@ -171,7 +172,6 @@
|
||||
<None Include="CoarseFineFundamentalRegressionAlgorithm.py" />
|
||||
<None Include="CoarseFundamentalTop3Algorithm.py" />
|
||||
<None Include="CompositeAlphaModelFrameworkAlgorithm.py" />
|
||||
<None Include="ConstituentsQC500GeneratorAlgorithm.py" />
|
||||
<None Include="CustomBenchmarkAlgorithm.py" />
|
||||
<None Include="CustomChartingAlgorithm.py" />
|
||||
<None Include="CustomDataBitcoinAlgorithm.py" />
|
||||
@@ -238,7 +238,6 @@
|
||||
<None Include="TimeInForceAlgorithm.py" />
|
||||
<None Include="TrailingStopRiskFrameworkAlgorithm.py" />
|
||||
<None Include="UncorrelatedUniverseSelectionFrameworkAlgorithm.py" />
|
||||
<None Include="UniverseSelectionDefinitionsAlgorithm.py" />
|
||||
<None Include="UniverseSelectionRegressionAlgorithm.py" />
|
||||
<None Include="UpdateOrderRegressionAlgorithm.py" />
|
||||
<None Include="UserDefinedUniverseAlgorithm.py" />
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
<Compile Include="CompositeRiskManagementModelFrameworkAlgorithm.py" />
|
||||
<Compile Include="ConfidenceWeightedFrameworkAlgorithm.py" />
|
||||
<Compile Include="ConsolidateRegressionAlgorithm.py" />
|
||||
<Compile Include="ConstituentsQC500GeneratorAlgorithm.py" />
|
||||
<Compile Include="ConstituentsUniverseRegressionAlgorithm.py" />
|
||||
<Compile Include="ConvertToFrameworkAlgorithm.py" />
|
||||
<Compile Include="CustomBuyingPowerModelAlgorithm.py" />
|
||||
|
||||
@@ -14,27 +14,26 @@
|
||||
from AlgorithmImports import *
|
||||
|
||||
### <summary>
|
||||
### Basic template algorithm which showcases ConstituentsUniverse simple use case
|
||||
### Regression algorithm testing the SetHolding trading API precision
|
||||
### </summary>
|
||||
class BasicTemplateConstituentUniverseAlgorithm(QCAlgorithm):
|
||||
class SetHoldingsRegressionAlgorithm(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,10, 7)
|
||||
self.SetEndDate(2013,10,11)
|
||||
|
||||
# by default will use algorithms UniverseSettings
|
||||
self.AddUniverse(self.Universe.Constituent.Steel())
|
||||
self.SetStartDate(2013, 10, 7)
|
||||
self.SetEndDate(2013, 10, 8)
|
||||
self.AddEquity("SPY", Resolution.Minute)
|
||||
|
||||
# we specify the UniverseSettings it should use
|
||||
self.AddUniverse(self.Universe.Constituent.AggressiveGrowth(
|
||||
UniverseSettings(Resolution.Hour,
|
||||
2,
|
||||
False,
|
||||
False,
|
||||
self.UniverseSettings.MinimumTimeInUniverse)))
|
||||
def OnData(self, data):
|
||||
'''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
|
||||
self.SetAlpha(ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromDays(1)))
|
||||
self.SetExecution(ImmediateExecutionModel())
|
||||
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
|
||||
Arguments:
|
||||
data: Slice object keyed by symbol containing the stock data
|
||||
'''
|
||||
if not self.Portfolio.Invested:
|
||||
self.SetHoldings("SPY", 0.1)
|
||||
self.SetHoldings("SPY", np.float(0.20))
|
||||
self.SetHoldings("SPY", np.float64(0.30))
|
||||
self.SetHoldings("SPY", 1)
|
||||
@@ -32,16 +32,7 @@ class UniverseSelectionDefinitionsAlgorithm(QCAlgorithm):
|
||||
self.SetCash(100000) # Set Strategy Cash
|
||||
|
||||
# add universe for the top 50 stocks by dollar volume
|
||||
self.AddUniverse(self.Universe.DollarVolume.Top(50))
|
||||
|
||||
# add universe for the bottom 50 stocks by dollar volume
|
||||
self.AddUniverse(self.Universe.DollarVolume.Bottom(50))
|
||||
|
||||
# add universe for the 90th dollar volume percentile
|
||||
self.AddUniverse(self.Universe.DollarVolume.Percentile(90.0))
|
||||
|
||||
# add universe for stocks between the 70th and 80th dollar volume percentile
|
||||
self.AddUniverse(self.Universe.DollarVolume.Percentile(70.0, 80.0))
|
||||
self.AddUniverse(self.Universe.Top(50))
|
||||
|
||||
self.changes = None
|
||||
|
||||
|
||||
@@ -11,11 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
|
||||
from QuantConnect.Algorithm.Framework.Alphas import AlphaModel
|
||||
|
||||
from AlgorithmImports import *
|
||||
|
||||
class NullAlphaModel(AlphaModel):
|
||||
'''Provides a null implementation of an alpha model'''
|
||||
@@ -27,4 +23,4 @@ class NullAlphaModel(AlphaModel):
|
||||
data: The new data available
|
||||
Returns:
|
||||
The new insights generated'''
|
||||
return []
|
||||
return []
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MathNet.Numerics.Statistics;
|
||||
@@ -46,94 +47,10 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="universeSettings">The settings for stocks added by this universe.
|
||||
/// Defaults to <see cref="QCAlgorithm.UniverseSettings"/></param>
|
||||
/// <returns>A new coarse universe for the top count of stocks by dollar volume</returns>
|
||||
[Obsolete("This method is deprecated. Use method `Universe.DollarVolume.Top(...)` instead")]
|
||||
public Universe Top(int count, UniverseSettings universeSettings = null)
|
||||
{
|
||||
universeSettings = universeSettings ?? _algorithm.UniverseSettings;
|
||||
var symbol = Symbol.Create("us-equity-dollar-volume-top-" + count, SecurityType.Equity, Market.USA);
|
||||
var config = new SubscriptionDataConfig(typeof(CoarseFundamental), symbol, Resolution.Daily, TimeZones.NewYork, TimeZones.NewYork, false, false, true);
|
||||
return new FuncUniverse(config, universeSettings, selectionData => (
|
||||
from c in selectionData.OfType<CoarseFundamental>()
|
||||
orderby c.DollarVolume descending
|
||||
select c.Symbol).Take(count)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new coarse universe that contains the bottom count of stocks
|
||||
/// by daily dollar volume
|
||||
/// </summary>
|
||||
/// <param name="count">The number of stock to select</param>
|
||||
/// <param name="universeSettings">The settings for stocks added by this universe.
|
||||
/// Defaults to <see cref="QCAlgorithm.UniverseSettings"/></param>
|
||||
/// <returns>A new coarse universe for the bottom count of stocks by dollar volume</returns>
|
||||
public Universe Bottom(int count, UniverseSettings universeSettings = null)
|
||||
{
|
||||
universeSettings = universeSettings ?? _algorithm.UniverseSettings;
|
||||
var symbol = Symbol.Create("us-equity-dollar-volume-bottom-" + count, SecurityType.Equity, Market.USA);
|
||||
var config = new SubscriptionDataConfig(typeof(CoarseFundamental), symbol, Resolution.Daily, TimeZones.NewYork, TimeZones.NewYork, false, false, true);
|
||||
return new FuncUniverse(config, universeSettings, selectionData => (
|
||||
from c in selectionData.OfType<CoarseFundamental>()
|
||||
orderby c.DollarVolume descending
|
||||
select c.Symbol).Take(count)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new coarse universe that contains stocks in the specified
|
||||
/// dollar volume percentile
|
||||
/// </summary>
|
||||
/// <param name="percentile">The desired dollar volume percentile (0 to 100 inclusive)</param>
|
||||
/// <param name="universeSettings">The settings for stocks added by this universe.
|
||||
/// Defaults to <see cref="QCAlgorithm.UniverseSettings"/></param>
|
||||
/// <returns>A new coarse universe for the bottom count of stocks by dollar volume</returns>
|
||||
public Universe Percentile(double percentile, UniverseSettings universeSettings = null)
|
||||
{
|
||||
universeSettings = universeSettings ?? _algorithm.UniverseSettings;
|
||||
var symbol = Symbol.Create("us-equity-dollar-volume-percentile-" + percentile, SecurityType.Equity, Market.USA);
|
||||
var config = new SubscriptionDataConfig(typeof(CoarseFundamental), symbol, Resolution.Daily, TimeZones.NewYork, TimeZones.NewYork, false, false, true);
|
||||
return new FuncUniverse(config, universeSettings, selectionData =>
|
||||
{
|
||||
var list = selectionData as IReadOnlyList<CoarseFundamental> ?? selectionData.OfType<CoarseFundamental>().ToList();
|
||||
|
||||
// using quantiles since the Percentile implementation requires integers, so scale into quantile space
|
||||
var lowerBound = (decimal)list.Select(x => (double)x.DollarVolume).Quantile(percentile / 100d);
|
||||
|
||||
return from c in list
|
||||
where c.DollarVolume >= lowerBound
|
||||
orderby c.DollarVolume descending
|
||||
select c.Symbol;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new coarse universe that contains stocks in the specified dollar volume percentile range,
|
||||
/// that is, this universe will produce stocks with dollar volumes between the lower percentile bound
|
||||
/// and the upper percentile bound
|
||||
/// </summary>
|
||||
/// <param name="lowerPercentile">The desired lower dollar volume percentile bound (0 to 100 inclusive)</param>
|
||||
/// <param name="upperPercentile">The desired upper dollar volume percentile bound (0 to 100 inclusive)</param>
|
||||
/// <param name="universeSettings">The settings for stocks added by this universe.
|
||||
/// Defaults to <see cref="QCAlgorithm.UniverseSettings"/></param>
|
||||
/// <returns>A new coarse universe for the bottom count of stocks by dollar volume</returns>
|
||||
public Universe Percentile(double lowerPercentile, double upperPercentile, UniverseSettings universeSettings = null)
|
||||
{
|
||||
universeSettings = universeSettings ?? _algorithm.UniverseSettings;
|
||||
var symbol = Symbol.Create("us-equity-dollar-volume-percentile-" + lowerPercentile + "-" + upperPercentile, SecurityType.Equity, Market.USA);
|
||||
var config = new SubscriptionDataConfig(typeof(CoarseFundamental), symbol, Resolution.Daily, TimeZones.NewYork, TimeZones.NewYork, false, false, true);
|
||||
return new FuncUniverse(config, universeSettings, selectionData =>
|
||||
{
|
||||
var list = selectionData as IReadOnlyList<CoarseFundamental> ?? selectionData.OfType<CoarseFundamental>().ToList();
|
||||
|
||||
// using quantiles since the Percentile implementation requires integers, so scale into quantile space
|
||||
var lowerBound = (decimal) list.Select(x => (double) x.DollarVolume).Quantile(lowerPercentile/100d);
|
||||
var upperBound = (decimal) list.Select(x => (double) x.DollarVolume).Quantile(upperPercentile/100d);
|
||||
|
||||
return from c in list
|
||||
where c.DollarVolume >= lowerBound
|
||||
where c.DollarVolume <= upperBound
|
||||
orderby c.DollarVolume descending
|
||||
select c.Symbol;
|
||||
});
|
||||
return _algorithm.Universe.Top(count, universeSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Execution
|
||||
{
|
||||
@@ -40,11 +41,17 @@ namespace QuantConnect.Algorithm.Framework.Execution
|
||||
{
|
||||
foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm))
|
||||
{
|
||||
var security = algorithm.Securities[target.Symbol];
|
||||
|
||||
// calculate remaining quantity to be ordered
|
||||
var quantity = OrderSizing.GetUnorderedQuantity(algorithm, target);
|
||||
var quantity = OrderSizing.GetUnorderedQuantity(algorithm, target, security);
|
||||
if (quantity != 0)
|
||||
{
|
||||
algorithm.MarketOrder(target.Symbol, quantity);
|
||||
if (security.BuyingPowerModel.AboveMinimumOrderMarginPortfolioPercentage(security, quantity,
|
||||
algorithm.Portfolio, algorithm.Settings.MinimumOrderMarginPortfolioPercentage))
|
||||
{
|
||||
algorithm.MarketOrder(security, quantity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,4 +68,4 @@ namespace QuantConnect.Algorithm.Framework.Execution
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,19 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from System import *
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Orders import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Execution import *
|
||||
from QuantConnect.Algorithm.Framework.Portfolio import *
|
||||
from AlgorithmImports import *
|
||||
|
||||
class ImmediateExecutionModel(ExecutionModel):
|
||||
'''Provides an implementation of IExecutionModel that immediately submits market orders to achieve the desired portfolio targets'''
|
||||
@@ -42,9 +30,12 @@ class ImmediateExecutionModel(ExecutionModel):
|
||||
self.targetsCollection.AddRange(targets)
|
||||
if self.targetsCollection.Count > 0:
|
||||
for target in self.targetsCollection.OrderByMarginImpact(algorithm):
|
||||
security = algorithm.Securities[target.Symbol]
|
||||
# calculate remaining quantity to be ordered
|
||||
quantity = OrderSizing.GetUnorderedQuantity(algorithm, target)
|
||||
quantity = OrderSizing.GetUnorderedQuantity(algorithm, target, security)
|
||||
if quantity != 0:
|
||||
algorithm.MarketOrder(target.Symbol, quantity)
|
||||
aboveMinimumPortfolio = BuyingPowerModelExtensions.AboveMinimumOrderMarginPortfolioPercentage(security.BuyingPowerModel, security, quantity, algorithm.Portfolio, algorithm.Settings.MinimumOrderMarginPortfolioPercentage)
|
||||
if aboveMinimumPortfolio:
|
||||
algorithm.MarketOrder(security, quantity)
|
||||
|
||||
self.targetsCollection.ClearFulfilled(algorithm)
|
||||
|
||||
@@ -11,9 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
from QuantConnect.Algorithm.Framework.Execution import *
|
||||
from AlgorithmImports import *
|
||||
|
||||
class NullExecutionModel(ExecutionModel):
|
||||
'''Provides an implementation of IExecutionModel that does nothing'''
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Algorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides helpers for defining universes based on index definitions
|
||||
/// </summary>
|
||||
public class IndexUniverseDefinitions
|
||||
{
|
||||
private readonly QCAlgorithm _algorithm;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IndexUniverseDefinitions"/> class
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance, used for obtaining the default <see cref="UniverseSettings"/></param>
|
||||
public IndexUniverseDefinitions(QCAlgorithm algorithm)
|
||||
{
|
||||
_algorithm = algorithm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new fine universe that contains the constituents of QC500 index based onthe company fundamentals
|
||||
/// The algorithm creates a default tradable and liquid universe containing 500 US equities
|
||||
/// which are chosen at the first trading day of each month.
|
||||
/// </summary>
|
||||
/// <returns>A new coarse universe for the top count of stocks by dollar volume</returns>
|
||||
public Universe QC500
|
||||
{
|
||||
get
|
||||
{
|
||||
var lastMonth = -1;
|
||||
var numberOfSymbolsCoarse = 1000;
|
||||
var numberOfSymbolsFine = 500;
|
||||
var dollarVolumeBySymbol = new Dictionary<Symbol, decimal>();
|
||||
var symbol = Symbol.Create("qc-500", SecurityType.Equity, Market.USA);
|
||||
|
||||
var coarseUniverse = new CoarseFundamentalUniverse(
|
||||
symbol,
|
||||
_algorithm.UniverseSettings,
|
||||
coarse =>
|
||||
{
|
||||
if (_algorithm.Time.Month == lastMonth)
|
||||
{
|
||||
return Universe.Unchanged;
|
||||
}
|
||||
|
||||
// The stocks must have fundamental data
|
||||
// The stock must have positive previous-day close price
|
||||
// The stock must have positive volume on the previous trading day
|
||||
var sortedByDollarVolume =
|
||||
(from x in coarse
|
||||
where x.HasFundamentalData && x.Volume > 0 && x.Price > 0
|
||||
orderby x.DollarVolume descending
|
||||
select x).Take(numberOfSymbolsCoarse).ToList();
|
||||
|
||||
dollarVolumeBySymbol.Clear();
|
||||
foreach (var x in sortedByDollarVolume)
|
||||
{
|
||||
dollarVolumeBySymbol[x.Symbol] = x.DollarVolume;
|
||||
}
|
||||
|
||||
// If no security has met the QC500 criteria, the universe is unchanged.
|
||||
// A new selection will be attempted on the next trading day as lastMonth is not updated
|
||||
if (dollarVolumeBySymbol.Count == 0)
|
||||
{
|
||||
return Universe.Unchanged;
|
||||
}
|
||||
|
||||
return dollarVolumeBySymbol.Keys;
|
||||
});
|
||||
|
||||
return new FineFundamentalFilteredUniverse(
|
||||
coarseUniverse,
|
||||
fine =>
|
||||
{
|
||||
// The company's headquarter must in the U.S.
|
||||
// The stock must be traded on either the NYSE or NASDAQ
|
||||
// At least half a year since its initial public offering
|
||||
// The stock's market cap must be greater than 500 million
|
||||
var filteredFine =
|
||||
(from x in fine
|
||||
where x.CompanyReference.CountryId == "USA" &&
|
||||
(x.CompanyReference.PrimaryExchangeID == "NYS" || x.CompanyReference.PrimaryExchangeID == "NAS") &&
|
||||
(_algorithm.Time - x.SecurityReference.IPODate).Days > 180 &&
|
||||
x.MarketCap > 500000000m
|
||||
select x).ToList();
|
||||
|
||||
var count = filteredFine.Count;
|
||||
|
||||
// If no security has met the QC500 criteria, the universe is unchanged.
|
||||
// A new selection will be attempted on the next trading day as lastMonth is not updated
|
||||
if (count == 0)
|
||||
{
|
||||
return Universe.Unchanged;
|
||||
}
|
||||
|
||||
// Update _lastMonth after all QC500 criteria checks passed
|
||||
lastMonth = _algorithm.Time.Month;
|
||||
|
||||
var percent = numberOfSymbolsFine / (double)count;
|
||||
|
||||
// select stocks with top dollar volume in every single sector
|
||||
var topFineBySector =
|
||||
(from x in filteredFine
|
||||
// Group by sector
|
||||
group x by x.CompanyReference.IndustryTemplateCode into g
|
||||
let y = from item in g
|
||||
orderby dollarVolumeBySymbol[item.Symbol] descending
|
||||
select item
|
||||
let c = (int)Math.Ceiling(y.Count() * percent)
|
||||
select new { g.Key, Value = y.Take(c) }
|
||||
).ToDictionary(x => x.Key, x => x.Value);
|
||||
|
||||
return topFineBySector.SelectMany(x => x.Value)
|
||||
.OrderByDescending(x => dollarVolumeBySymbol[x.Symbol])
|
||||
.Take(numberOfSymbolsFine)
|
||||
.Select(x => x.Symbol);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,9 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
from QuantConnect.Algorithm.Framework.Portfolio import *
|
||||
from AlgorithmImports import *
|
||||
|
||||
class NullPortfolioConstructionModel(PortfolioConstructionModel):
|
||||
'''Provides an implementation of IPortfolioConstructionModel that does nothing'''
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NodaTime;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Util;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Util;
|
||||
using QuantConnect.Data.Market;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm
|
||||
{
|
||||
@@ -458,104 +458,88 @@ namespace QuantConnect.Algorithm
|
||||
return History(requests, TimeZone).Memoize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Yields data to warmup a security for all it's subscribed data types
|
||||
/// </summary>
|
||||
/// <param name="security"><see cref="Security"/> object for which to retrieve historical data</param>
|
||||
/// <returns>Securities historical data</returns>
|
||||
public IEnumerable<BaseData> GetLastKnownPrices(Security security)
|
||||
{
|
||||
return GetLastKnownPrices(security.Symbol);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Yields data to warmup a security for all it's subscribed data types
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol we want to get seed data for</param>
|
||||
/// <returns>Securities historical data</returns>
|
||||
public IEnumerable<BaseData> GetLastKnownPrices(Symbol symbol)
|
||||
{
|
||||
if (symbol.IsCanonical() || HistoryProvider == null)
|
||||
{
|
||||
return Enumerable.Empty<BaseData>();
|
||||
}
|
||||
|
||||
var result = new Dictionary<TickType, BaseData>();
|
||||
// For speed and memory usage, use Resolution.Minute as the minimum resolution
|
||||
var resolution = (Resolution)Math.Max((int)Resolution.Minute,
|
||||
(int)SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(symbol).GetHighestResolution());
|
||||
Func<int, bool> requestData = period =>
|
||||
{
|
||||
var historyRequests = CreateBarCountHistoryRequests(new[] { symbol }, period, resolution)
|
||||
.Select(request =>
|
||||
{
|
||||
// force no fill forward behavior
|
||||
request.FillForwardResolution = null;
|
||||
return request;
|
||||
})
|
||||
// request only those tick types we didn't get the data we wanted
|
||||
.Where(request => !result.ContainsKey(request.TickType))
|
||||
.ToList();
|
||||
foreach (var slice in History(historyRequests))
|
||||
{
|
||||
for (var i = 0; i < historyRequests.Count; i++)
|
||||
{
|
||||
var historyRequest = historyRequests[i];
|
||||
var data = slice.Get(historyRequest.DataType);
|
||||
if (data.ContainsKey(symbol))
|
||||
{
|
||||
// keep the last data point per tick type
|
||||
result[historyRequest.TickType] = (BaseData)data[symbol];
|
||||
}
|
||||
}
|
||||
}
|
||||
// true when all history requests tick types have a data point
|
||||
return historyRequests.All(request => result.ContainsKey(request.TickType));
|
||||
};
|
||||
|
||||
if (!requestData(5))
|
||||
{
|
||||
// If the first attempt to get the last know price returns null, it maybe the case of an illiquid security.
|
||||
// We increase the look-back period for this case accordingly to the resolution to cover 3 trading days
|
||||
var periods =
|
||||
resolution == Resolution.Daily ? 3 :
|
||||
resolution == Resolution.Hour ? 24 : 1440;
|
||||
requestData(periods);
|
||||
}
|
||||
// return the data ordered by time ascending
|
||||
return result.Values.OrderBy(data => data.Time);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the last known price using the history provider.
|
||||
/// Useful for seeding securities with the correct price
|
||||
/// </summary>
|
||||
/// <param name="security"><see cref="Security"/> object for which to retrieve historical data</param>
|
||||
/// <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")]
|
||||
public BaseData GetLastKnownPrice(Security security)
|
||||
{
|
||||
if (security.Symbol.IsCanonical() || HistoryProvider == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var configs = SubscriptionManager.SubscriptionDataConfigService
|
||||
.GetSubscriptionDataConfigs(security.Symbol);
|
||||
|
||||
var dataTimeZone = MarketHoursDatabase
|
||||
.GetDataTimeZone(security.Symbol.ID.Market, security.Symbol, security.Symbol.SecurityType);
|
||||
|
||||
// For speed and memory usage, use Resolution.Minute as the minimum resolution
|
||||
var resolution = (Resolution)Math.Max((int)Resolution.Minute, (int)configs.GetHighestResolution());
|
||||
var isExtendedMarketHours = configs.IsExtendedMarketHours();
|
||||
|
||||
// request QuoteBar for Futures and all option types
|
||||
var dataType = typeof(BaseData);
|
||||
if (security.Type.IsOption() || security.Type == SecurityType.Future)
|
||||
{
|
||||
dataType = LeanData.GetDataType(resolution, TickType.Quote);
|
||||
}
|
||||
|
||||
// Get the config with the largest resolution
|
||||
var subscriptionDataConfig = GetMatchingSubscription(security.Symbol, dataType);
|
||||
|
||||
TickType tickType;
|
||||
|
||||
if (subscriptionDataConfig == null)
|
||||
{
|
||||
dataType = typeof(TradeBar);
|
||||
tickType = LeanData.GetCommonTickTypeForCommonDataTypes(dataType, security.Type);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if subscription resolution is Tick, we also need to update the data type from Tick to TradeBar/QuoteBar
|
||||
if (subscriptionDataConfig.Resolution == Resolution.Tick)
|
||||
{
|
||||
dataType = LeanData.GetDataType(resolution, subscriptionDataConfig.TickType);
|
||||
subscriptionDataConfig = new SubscriptionDataConfig(subscriptionDataConfig, dataType, resolution: resolution);
|
||||
}
|
||||
|
||||
dataType = subscriptionDataConfig.Type;
|
||||
tickType = subscriptionDataConfig.TickType;
|
||||
}
|
||||
|
||||
Func<int, BaseData> getLastKnownPriceForPeriods = backwardsPeriods =>
|
||||
{
|
||||
var startTimeUtc = _historyRequestFactory
|
||||
.GetStartTimeAlgoTz(security.Symbol, backwardsPeriods, resolution, security.Exchange.Hours, dataTimeZone)
|
||||
.ConvertToUtc(_localTimeKeeper.TimeZone);
|
||||
|
||||
var request = new HistoryRequest(
|
||||
startTimeUtc,
|
||||
UtcTime,
|
||||
dataType,
|
||||
security.Symbol,
|
||||
resolution,
|
||||
security.Exchange.Hours,
|
||||
dataTimeZone,
|
||||
resolution,
|
||||
isExtendedMarketHours,
|
||||
configs.IsCustomData(),
|
||||
configs.DataNormalizationMode(),
|
||||
tickType
|
||||
);
|
||||
|
||||
BaseData result = null;
|
||||
History(new List<HistoryRequest> { request })
|
||||
.PushThrough(bar =>
|
||||
{
|
||||
if (!bar.IsFillForward)
|
||||
result = bar;
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
var lastKnownPrice = getLastKnownPriceForPeriods(1);
|
||||
if (lastKnownPrice != null)
|
||||
{
|
||||
return lastKnownPrice;
|
||||
}
|
||||
|
||||
// If the first attempt to get the last know price returns null, it maybe the case of an illiquid security.
|
||||
// We increase the look-back period for this case accordingly to the resolution to cover 3 trading days
|
||||
var periods =
|
||||
resolution == Resolution.Daily ? 3 :
|
||||
resolution == Resolution.Hour ? 24 : 1440;
|
||||
|
||||
return getLastKnownPriceForPeriods(periods);
|
||||
return GetLastKnownPrices(security.Symbol)
|
||||
// since we are returning a single data point let's respect order
|
||||
.OrderByDescending(data => GetTickTypeOrder(data.Symbol.SecurityType, LeanData.GetCommonTickTypeForCommonDataTypes(data.GetType(), data.Symbol.SecurityType)))
|
||||
.LastOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -668,16 +652,26 @@ namespace QuantConnect.Algorithm
|
||||
return GetMatchingSubscriptions(symbol, type, resolution).FirstOrDefault();
|
||||
}
|
||||
|
||||
private int GetTickTypeOrder(SecurityType securityType, TickType tickType)
|
||||
{
|
||||
return SubscriptionManager.AvailableDataTypes[securityType].IndexOf(tickType);
|
||||
}
|
||||
|
||||
private IEnumerable<SubscriptionDataConfig> GetMatchingSubscriptions(Symbol symbol, Type type, Resolution? resolution = null)
|
||||
{
|
||||
Security security;
|
||||
if (Securities.TryGetValue(symbol, out security))
|
||||
{
|
||||
var matchingSubscriptions = SubscriptionManager.SubscriptionDataConfigService
|
||||
.GetSubscriptionDataConfigs(symbol, includeInternalConfigs:true)
|
||||
// find all subscriptions matching the requested type with a higher resolution than requested
|
||||
var matchingSubscriptions = from sub in security.Subscriptions.OrderByDescending(s => s.Resolution)
|
||||
where SubscriptionDataConfigTypeFilter(type, sub.Type)
|
||||
select sub;
|
||||
|
||||
.OrderByDescending(s => s.Resolution)
|
||||
// lets make sure to respect the order of the data types
|
||||
.ThenByDescending(config => GetTickTypeOrder(config.SecurityType, config.TickType))
|
||||
.ThenBy(config => config.IsInternalFeed ? 1 : 0)
|
||||
.Where(s => SubscriptionDataConfigTypeFilter(type, s.Type))
|
||||
.ToList();
|
||||
// we use the subscription manager registered configurations here, we can not rely on the Securities collection
|
||||
// since this might be called when creating a security and warming it up
|
||||
if (matchingSubscriptions.Count != 0)
|
||||
{
|
||||
if (resolution.HasValue
|
||||
&& (resolution == Resolution.Daily || resolution == Resolution.Hour)
|
||||
&& symbol.SecurityType == SecurityType.Equity)
|
||||
@@ -685,7 +679,7 @@ namespace QuantConnect.Algorithm
|
||||
// for Daily and Hour resolution, for equities, we have to
|
||||
// filter out any existing subscriptions that could be of Quote type
|
||||
// This could happen if they were Resolution.Minute/Second/Tick
|
||||
matchingSubscriptions = matchingSubscriptions.Where(s => s.TickType != TickType.Quote);
|
||||
return matchingSubscriptions.Where(s => s.TickType != TickType.Quote);
|
||||
}
|
||||
|
||||
return matchingSubscriptions;
|
||||
|
||||
@@ -1027,6 +1027,56 @@ namespace QuantConnect.Algorithm
|
||||
return meanAbsoluteDeviation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an Market Profile indicator for the symbol with Volume Profile (VOL) mode. The indicator will be automatically
|
||||
/// updated on the given resolution.
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol whose VP we want</param>
|
||||
/// <param name="period">The period of the VP</param>
|
||||
/// <param name="valueAreaVolumePercentage">The percentage of volume contained in the value area</param>
|
||||
/// <param name="priceRangeRoundOff">How many digits you want to round and the precision. i.e 0.01 round to two digits exactly.</param>
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The Volume Profile indicator for the given parameters</returns>
|
||||
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);
|
||||
var marketProfile = new VolumeProfile(name, period, valueAreaVolumePercentage, priceRangeRoundOff);
|
||||
RegisterIndicator(symbol, marketProfile, resolution, selector);
|
||||
|
||||
if (EnableAutomaticIndicatorWarmUp)
|
||||
{
|
||||
WarmUpIndicator(symbol, marketProfile, resolution);
|
||||
}
|
||||
|
||||
return marketProfile;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an Market Profile indicator for the symbol with Time Price Opportunity (TPO) mode. The indicator will be automatically
|
||||
/// updated on the given resolution.
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol whose TP we want</param>
|
||||
/// <param name="period">The period of the TP</param>
|
||||
/// <param name="valueAreaVolumePercentage">The percentage of volume contained in the value area</param>
|
||||
/// <param name="priceRangeRoundOff">How many digits you want to round and the precision. i.e 0.01 round to two digits exactly.</param>
|
||||
/// <param name="resolution">The resolution</param>
|
||||
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
|
||||
/// <returns>The Time Profile indicator for the given parameters</returns>
|
||||
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);
|
||||
var marketProfile = new TimeProfile(name, period, valueAreaVolumePercentage, priceRangeRoundOff);
|
||||
RegisterIndicator(symbol, marketProfile, resolution, selector);
|
||||
|
||||
if (EnableAutomaticIndicatorWarmUp)
|
||||
{
|
||||
WarmUpIndicator(symbol, marketProfile, resolution);
|
||||
}
|
||||
|
||||
return marketProfile;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Maximum indicator to compute the maximum value
|
||||
/// </summary>
|
||||
|
||||
@@ -268,8 +268,7 @@ namespace QuantConnect.Algorithm
|
||||
extendedMarketHours: true);
|
||||
var security = Securities.CreateSecurity(symbol, config, leverage, addToSymbolCache: false);
|
||||
|
||||
AddToUserDefinedUniverse(security, new List<SubscriptionDataConfig> { config });
|
||||
return security;
|
||||
return AddToUserDefinedUniverse(security, new List<SubscriptionDataConfig> { config });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -14,21 +14,21 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Securities.Option;
|
||||
using static QuantConnect.StringExtensions;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
|
||||
namespace QuantConnect.Algorithm
|
||||
{
|
||||
public partial class QCAlgorithm
|
||||
{
|
||||
private int _maxOrders = 10000;
|
||||
private bool _isMarketOnOpenOrderWarningSent = false;
|
||||
private bool _isMarketOnOpenOrderWarningSent;
|
||||
|
||||
/// <summary>
|
||||
/// Transaction Manager - Process transaction fills and order management.
|
||||
@@ -41,6 +41,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">string Symbol of the asset to trade</param>
|
||||
/// <param name="quantity">int Quantity of the asset to trade</param>
|
||||
/// <seealso cref="Buy(Symbol, double)"/>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket Buy(Symbol symbol, int quantity)
|
||||
{
|
||||
return Order(symbol, (decimal)Math.Abs(quantity));
|
||||
@@ -52,6 +53,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">string Symbol of the asset to trade</param>
|
||||
/// <param name="quantity">double Quantity of the asset to trade</param>
|
||||
/// <seealso cref="Buy(Symbol, decimal)"/>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket Buy(Symbol symbol, double quantity)
|
||||
{
|
||||
return Order(symbol, Math.Abs(quantity).SafeDecimalCast());
|
||||
@@ -63,6 +65,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">string Symbol of the asset to trade</param>
|
||||
/// <param name="quantity">decimal Quantity of the asset to trade</param>
|
||||
/// <seealso cref="Order(Symbol, int)"/>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket Buy(Symbol symbol, decimal quantity)
|
||||
{
|
||||
return Order(symbol, Math.Abs(quantity));
|
||||
@@ -74,6 +77,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">string Symbol of the asset to trade</param>
|
||||
/// <param name="quantity">float Quantity of the asset to trade</param>
|
||||
/// <seealso cref="Buy(Symbol, decimal)"/>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket Buy(Symbol symbol, float quantity)
|
||||
{
|
||||
return Order(symbol, (decimal)Math.Abs(quantity));
|
||||
@@ -86,6 +90,7 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">string Symbol of the asset to trade</param>
|
||||
/// <param name="quantity">int Quantity of the asset to trade</param>
|
||||
/// <seealso cref="Sell(Symbol, decimal)"/>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket Sell(Symbol symbol, int quantity)
|
||||
{
|
||||
return Order(symbol, (decimal)Math.Abs(quantity) * -1);
|
||||
@@ -96,7 +101,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="symbol">String symbol to sell</param>
|
||||
/// <param name="quantity">Quantity to order</param>
|
||||
/// <returns>int Order Id.</returns>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket Sell(Symbol symbol, double quantity)
|
||||
{
|
||||
return Order(symbol, Math.Abs(quantity).SafeDecimalCast() * -1m);
|
||||
@@ -107,7 +112,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="symbol">String symbol</param>
|
||||
/// <param name="quantity">Quantity to sell</param>
|
||||
/// <returns>int order id</returns>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket Sell(Symbol symbol, float quantity)
|
||||
{
|
||||
return Order(symbol, (decimal)Math.Abs(quantity) * -1m);
|
||||
@@ -118,7 +123,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="symbol">String symbol to sell</param>
|
||||
/// <param name="quantity">Quantity to sell</param>
|
||||
/// <returns>Int Order Id.</returns>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket Sell(Symbol symbol, decimal quantity)
|
||||
{
|
||||
return Order(symbol, Math.Abs(quantity) * -1);
|
||||
@@ -127,7 +132,10 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Issue an order/trade for asset: Alias wrapper for Order(string, int);
|
||||
/// </summary>
|
||||
/// <param name="symbol">Symbol to order</param>
|
||||
/// <param name="quantity">Quantity to order</param>
|
||||
/// <seealso cref="Order(Symbol, decimal)"/>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket Order(Symbol symbol, double quantity)
|
||||
{
|
||||
return Order(symbol, quantity.SafeDecimalCast());
|
||||
@@ -136,7 +144,9 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Issue an order/trade for asset
|
||||
/// </summary>
|
||||
/// <remarks></remarks>
|
||||
/// <param name="symbol">Symbol to order</param>
|
||||
/// <param name="quantity">Quantity to order</param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket Order(Symbol symbol, int quantity)
|
||||
{
|
||||
return MarketOrder(symbol, (decimal)quantity);
|
||||
@@ -145,7 +155,9 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Issue an order/trade for asset
|
||||
/// </summary>
|
||||
/// <remarks></remarks>
|
||||
/// <param name="symbol">Symbol to order</param>
|
||||
/// <param name="quantity">Quantity to order</param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket Order(Symbol symbol, decimal quantity)
|
||||
{
|
||||
return MarketOrder(symbol, quantity);
|
||||
@@ -158,10 +170,12 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Number of shares to request.</param>
|
||||
/// <param name="asynchronous">Send the order asynchronously (false). Otherwise we'll block until it fills</param>
|
||||
/// <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>
|
||||
/// <seealso cref="MarketOrder(Symbol, decimal, bool, string)"/>
|
||||
public OrderTicket Order(Symbol symbol, decimal quantity, bool asynchronous = false, string tag = "")
|
||||
public OrderTicket Order(Symbol symbol, decimal quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return MarketOrder(symbol, quantity, asynchronous, tag);
|
||||
return MarketOrder(symbol, quantity, asynchronous, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -171,10 +185,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Number of shares to request.</param>
|
||||
/// <param name="asynchronous">Send the order asynchronously (false). Otherwise we'll block until it fills</param>
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <returns>int Order id</returns>
|
||||
public OrderTicket MarketOrder(Symbol symbol, int quantity, bool asynchronous = false, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket MarketOrder(Symbol symbol, int quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return MarketOrder(symbol, (decimal)quantity, asynchronous, tag);
|
||||
return MarketOrder(symbol, (decimal)quantity, asynchronous, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -184,10 +199,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Number of shares to request.</param>
|
||||
/// <param name="asynchronous">Send the order asynchronously (false). Otherwise we'll block until it fills</param>
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <returns>int Order id</returns>
|
||||
public OrderTicket MarketOrder(Symbol symbol, double quantity, bool asynchronous = false, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket MarketOrder(Symbol symbol, double quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return MarketOrder(symbol, quantity.SafeDecimalCast(), asynchronous, tag);
|
||||
return MarketOrder(symbol, quantity.SafeDecimalCast(), asynchronous, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -197,11 +213,25 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Number of shares to request.</param>
|
||||
/// <param name="asynchronous">Send the order asynchronously (false). Otherwise we'll block until it fills</param>
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <returns>int Order id</returns>
|
||||
public OrderTicket MarketOrder(Symbol symbol, decimal quantity, bool asynchronous = false, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket MarketOrder(Symbol symbol, decimal quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
return MarketOrder(security, quantity, asynchronous, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Market order implementation: Send a market order and wait for it to be filled.
|
||||
/// </summary>
|
||||
/// <param name="security">Symbol of the MarketType Required.</param>
|
||||
/// <param name="quantity">Number of shares to request.</param>
|
||||
/// <param name="asynchronous">Send the order asynchronously (false). Otherwise we'll block until it fills</param>
|
||||
/// <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>
|
||||
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
|
||||
// then convert it into a market on open order
|
||||
if (!security.Exchange.ExchangeOpen)
|
||||
@@ -219,7 +249,7 @@ namespace QuantConnect.Algorithm
|
||||
return mooTicket;
|
||||
}
|
||||
|
||||
var request = CreateSubmitOrderRequest(OrderType.Market, security, quantity, tag, DefaultOrderProperties?.Clone());
|
||||
var request = CreateSubmitOrderRequest(OrderType.Market, security, quantity, tag, orderProperties ?? DefaultOrderProperties?.Clone());
|
||||
|
||||
// If warming up, do not submit
|
||||
if (IsWarmingUp)
|
||||
@@ -252,10 +282,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">The symbol to be ordered</param>
|
||||
/// <param name="quantity">The number of shares to required</param>
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <returns>The order ID</returns>
|
||||
public OrderTicket MarketOnOpenOrder(Symbol symbol, double quantity, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket MarketOnOpenOrder(Symbol symbol, double quantity, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return MarketOnOpenOrder(symbol, quantity.SafeDecimalCast(), tag);
|
||||
return MarketOnOpenOrder(symbol, quantity.SafeDecimalCast(), tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -264,10 +295,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">The symbol to be ordered</param>
|
||||
/// <param name="quantity">The number of shares to required</param>
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <returns>The order ID</returns>
|
||||
public OrderTicket MarketOnOpenOrder(Symbol symbol, int quantity, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket MarketOnOpenOrder(Symbol symbol, int quantity, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return MarketOnOpenOrder(symbol, (decimal)quantity, tag);
|
||||
return MarketOnOpenOrder(symbol, (decimal)quantity, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -276,11 +308,12 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">The symbol to be ordered</param>
|
||||
/// <param name="quantity">The number of shares to required</param>
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <returns>The order ID</returns>
|
||||
public OrderTicket MarketOnOpenOrder(Symbol symbol, decimal quantity, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket MarketOnOpenOrder(Symbol symbol, decimal quantity, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
var request = CreateSubmitOrderRequest(OrderType.MarketOnOpen, security, quantity, tag, DefaultOrderProperties?.Clone());
|
||||
var request = CreateSubmitOrderRequest(OrderType.MarketOnOpen, security, quantity, tag, orderProperties ?? DefaultOrderProperties?.Clone());
|
||||
var response = PreOrderChecks(request);
|
||||
if (response.IsError)
|
||||
{
|
||||
@@ -296,10 +329,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">The symbol to be ordered</param>
|
||||
/// <param name="quantity">The number of shares to required</param>
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <returns>The order ID</returns>
|
||||
public OrderTicket MarketOnCloseOrder(Symbol symbol, int quantity, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket MarketOnCloseOrder(Symbol symbol, int quantity, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return MarketOnCloseOrder(symbol, (decimal)quantity, tag);
|
||||
return MarketOnCloseOrder(symbol, (decimal)quantity, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -308,10 +342,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">The symbol to be ordered</param>
|
||||
/// <param name="quantity">The number of shares to required</param>
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <returns>The order ID</returns>
|
||||
public OrderTicket MarketOnCloseOrder(Symbol symbol, double quantity, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket MarketOnCloseOrder(Symbol symbol, double quantity, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return MarketOnCloseOrder(symbol, quantity.SafeDecimalCast(), tag);
|
||||
return MarketOnCloseOrder(symbol, quantity.SafeDecimalCast(), tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -320,11 +355,12 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">The symbol to be ordered</param>
|
||||
/// <param name="quantity">The number of shares to required</param>
|
||||
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
|
||||
/// <returns>The order ID</returns>
|
||||
public OrderTicket MarketOnCloseOrder(Symbol symbol, decimal quantity, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket MarketOnCloseOrder(Symbol symbol, decimal quantity, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
var request = CreateSubmitOrderRequest(OrderType.MarketOnClose, security, quantity, tag, DefaultOrderProperties?.Clone());
|
||||
var request = CreateSubmitOrderRequest(OrderType.MarketOnClose, security, quantity, tag, orderProperties ?? DefaultOrderProperties?.Clone());
|
||||
var response = PreOrderChecks(request);
|
||||
if (response.IsError)
|
||||
{
|
||||
@@ -341,10 +377,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Quantity of shares for limit order</param>
|
||||
/// <param name="limitPrice">Limit price to fill this order</param>
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <returns>Order id</returns>
|
||||
public OrderTicket LimitOrder(Symbol symbol, int quantity, decimal limitPrice, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket LimitOrder(Symbol symbol, int quantity, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return LimitOrder(symbol, (decimal)quantity, limitPrice, tag);
|
||||
return LimitOrder(symbol, (decimal)quantity, limitPrice, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -354,10 +391,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Quantity of shares for limit order</param>
|
||||
/// <param name="limitPrice">Limit price to fill this order</param>
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <returns>Order id</returns>
|
||||
public OrderTicket LimitOrder(Symbol symbol, double quantity, decimal limitPrice, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket LimitOrder(Symbol symbol, double quantity, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return LimitOrder(symbol, quantity.SafeDecimalCast(), limitPrice, tag);
|
||||
return LimitOrder(symbol, quantity.SafeDecimalCast(), limitPrice, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -367,11 +405,12 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Quantity of shares for limit order</param>
|
||||
/// <param name="limitPrice">Limit price to fill this order</param>
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <returns>Order id</returns>
|
||||
public OrderTicket LimitOrder(Symbol symbol, decimal quantity, decimal limitPrice, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket LimitOrder(Symbol symbol, decimal quantity, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
var request = CreateSubmitOrderRequest(OrderType.Limit, security, quantity, tag, limitPrice: limitPrice, properties: DefaultOrderProperties?.Clone());
|
||||
var request = CreateSubmitOrderRequest(OrderType.Limit, security, quantity, tag, limitPrice: limitPrice, properties: orderProperties ?? DefaultOrderProperties?.Clone());
|
||||
var response = PreOrderChecks(request);
|
||||
if (response.IsError)
|
||||
{
|
||||
@@ -388,10 +427,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Quantity to be traded</param>
|
||||
/// <param name="stopPrice">Price to fill the stop order</param>
|
||||
/// <param name="tag">Optional string data tag for the order</param>
|
||||
/// <returns>Int orderId for the new order.</returns>
|
||||
public OrderTicket StopMarketOrder(Symbol symbol, int quantity, decimal stopPrice, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket StopMarketOrder(Symbol symbol, int quantity, decimal stopPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return StopMarketOrder(symbol, (decimal)quantity, stopPrice, tag);
|
||||
return StopMarketOrder(symbol, (decimal)quantity, stopPrice, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -401,10 +441,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Quantity to be traded</param>
|
||||
/// <param name="stopPrice">Price to fill the stop order</param>
|
||||
/// <param name="tag">Optional string data tag for the order</param>
|
||||
/// <returns>Int orderId for the new order.</returns>
|
||||
public OrderTicket StopMarketOrder(Symbol symbol, double quantity, decimal stopPrice, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket StopMarketOrder(Symbol symbol, double quantity, decimal stopPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return StopMarketOrder(symbol, quantity.SafeDecimalCast(), stopPrice, tag);
|
||||
return StopMarketOrder(symbol, quantity.SafeDecimalCast(), stopPrice, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -414,11 +455,12 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Quantity to be traded</param>
|
||||
/// <param name="stopPrice">Price to fill the stop order</param>
|
||||
/// <param name="tag">Optional string data tag for the order</param>
|
||||
/// <returns>Int orderId for the new order.</returns>
|
||||
public OrderTicket StopMarketOrder(Symbol symbol, decimal quantity, decimal stopPrice, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket StopMarketOrder(Symbol symbol, decimal quantity, decimal stopPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
var request = CreateSubmitOrderRequest(OrderType.StopMarket, security, quantity, tag, stopPrice: stopPrice, properties: DefaultOrderProperties?.Clone());
|
||||
var request = CreateSubmitOrderRequest(OrderType.StopMarket, security, quantity, tag, stopPrice: stopPrice, properties: orderProperties ?? DefaultOrderProperties?.Clone());
|
||||
var response = PreOrderChecks(request);
|
||||
if (response.IsError)
|
||||
{
|
||||
@@ -436,10 +478,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="stopPrice">Stop price for this order</param>
|
||||
/// <param name="limitPrice">Limit price to fill this order</param>
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <returns>Order id</returns>
|
||||
public OrderTicket StopLimitOrder(Symbol symbol, int quantity, decimal stopPrice, decimal limitPrice, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket StopLimitOrder(Symbol symbol, int quantity, decimal stopPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return StopLimitOrder(symbol, (decimal)quantity, stopPrice, limitPrice, tag);
|
||||
return StopLimitOrder(symbol, (decimal)quantity, stopPrice, limitPrice, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -450,10 +493,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="stopPrice">Stop price for this order</param>
|
||||
/// <param name="limitPrice">Limit price to fill this order</param>
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <returns>Order id</returns>
|
||||
public OrderTicket StopLimitOrder(Symbol symbol, double quantity, decimal stopPrice, decimal limitPrice, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket StopLimitOrder(Symbol symbol, double quantity, decimal stopPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return StopLimitOrder(symbol, quantity.SafeDecimalCast(), stopPrice, limitPrice, tag);
|
||||
return StopLimitOrder(symbol, quantity.SafeDecimalCast(), stopPrice, limitPrice, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -464,11 +508,12 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="stopPrice">Stop price for this order</param>
|
||||
/// <param name="limitPrice">Limit price to fill this order</param>
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <returns>Order id</returns>
|
||||
public OrderTicket StopLimitOrder(Symbol symbol, decimal quantity, decimal stopPrice, decimal limitPrice, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket StopLimitOrder(Symbol symbol, decimal quantity, decimal stopPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
var request = CreateSubmitOrderRequest(OrderType.StopLimit, security, quantity, tag, stopPrice: stopPrice, limitPrice: limitPrice, properties: DefaultOrderProperties?.Clone());
|
||||
var request = CreateSubmitOrderRequest(OrderType.StopLimit, security, quantity, tag, stopPrice: stopPrice, limitPrice: limitPrice, properties: orderProperties ?? DefaultOrderProperties?.Clone());
|
||||
var response = PreOrderChecks(request);
|
||||
if (response.IsError)
|
||||
{
|
||||
@@ -487,10 +532,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="triggerPrice">Trigger price for this order</param>
|
||||
/// <param name="limitPrice">Limit price to fill this order</param>
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <returns>Order id</returns>
|
||||
public OrderTicket LimitIfTouchedOrder(Symbol symbol, int quantity, decimal triggerPrice, decimal limitPrice, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket LimitIfTouchedOrder(Symbol symbol, int quantity, decimal triggerPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return LimitIfTouchedOrder(symbol, (decimal)quantity, triggerPrice, limitPrice, tag);
|
||||
return LimitIfTouchedOrder(symbol, (decimal)quantity, triggerPrice, limitPrice, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -501,10 +547,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="triggerPrice">Trigger price for this order</param>
|
||||
/// <param name="limitPrice">Limit price to fill this order</param>
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <returns>Order id</returns>
|
||||
public OrderTicket LimitIfTouchedOrder(Symbol symbol, double quantity, decimal triggerPrice, decimal limitPrice, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket LimitIfTouchedOrder(Symbol symbol, double quantity, decimal triggerPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return LimitIfTouchedOrder(symbol, quantity.SafeDecimalCast(), triggerPrice, limitPrice, tag);
|
||||
return LimitIfTouchedOrder(symbol, quantity.SafeDecimalCast(), triggerPrice, limitPrice, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -515,11 +562,12 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="triggerPrice">Trigger price for this order</param>
|
||||
/// <param name="limitPrice">Limit price to fill this order</param>
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
/// <returns>Order id</returns>
|
||||
public OrderTicket LimitIfTouchedOrder(Symbol symbol, decimal quantity, decimal triggerPrice, decimal limitPrice, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket LimitIfTouchedOrder(Symbol symbol, decimal quantity, decimal triggerPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var security = Securities[symbol];
|
||||
var request = CreateSubmitOrderRequest(OrderType.LimitIfTouched, security, quantity, tag, triggerPrice: triggerPrice, limitPrice: limitPrice, properties: DefaultOrderProperties?.Clone());
|
||||
var request = CreateSubmitOrderRequest(OrderType.LimitIfTouched, security, quantity, tag, triggerPrice: triggerPrice, limitPrice: limitPrice, properties: orderProperties ?? DefaultOrderProperties?.Clone());
|
||||
var response = PreOrderChecks(request);
|
||||
if (response.IsError)
|
||||
{
|
||||
@@ -537,13 +585,15 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="quantity">Quantity of options contracts</param>
|
||||
/// <param name="asynchronous">Send the order asynchronously (false). Otherwise we'll block until it fills</param>
|
||||
/// <param name="tag">String tag for the order (optional)</param>
|
||||
public OrderTicket ExerciseOption(Symbol optionSymbol, int quantity, bool asynchronous = false, string tag = "")
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>The order ticket instance.</returns>
|
||||
public OrderTicket ExerciseOption(Symbol optionSymbol, int quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
var option = (Option) Securities[optionSymbol];
|
||||
|
||||
// SubmitOrderRequest.Quantity indicates the change in holdings quantity, therefore manual exercise quantities must be negative
|
||||
// PreOrderChecksImpl confirms that we don't hold a short position, so we're lenient here and accept +/- quantity values
|
||||
var request = CreateSubmitOrderRequest(OrderType.OptionExercise, option, -Math.Abs(quantity), tag, DefaultOrderProperties?.Clone());
|
||||
var request = CreateSubmitOrderRequest(OrderType.OptionExercise, option, -Math.Abs(quantity), tag, orderProperties ?? DefaultOrderProperties?.Clone());
|
||||
|
||||
// If warming up, do not submit
|
||||
if (IsWarmingUp)
|
||||
@@ -577,10 +627,11 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="strategy">Specification of the strategy to trade</param>
|
||||
/// <param name="quantity">Quantity of the strategy to trade</param>
|
||||
/// <returns>Sequence of order ids</returns>
|
||||
public IEnumerable<OrderTicket> Buy(OptionStrategy strategy, int quantity)
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>Sequence of order tickets</returns>
|
||||
public IEnumerable<OrderTicket> Buy(OptionStrategy strategy, int quantity, IOrderProperties orderProperties = null)
|
||||
{
|
||||
return Order(strategy, Math.Abs(quantity));
|
||||
return Order(strategy, Math.Abs(quantity), orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -588,10 +639,11 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="strategy">Specification of the strategy to trade</param>
|
||||
/// <param name="quantity">Quantity of the strategy to trade</param>
|
||||
/// <returns>Sequence of order ids</returns>
|
||||
public IEnumerable<OrderTicket> Sell(OptionStrategy strategy, int quantity)
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>Sequence of order tickets</returns>
|
||||
public IEnumerable<OrderTicket> Sell(OptionStrategy strategy, int quantity, IOrderProperties orderProperties = null)
|
||||
{
|
||||
return Order(strategy, Math.Abs(quantity) * -1);
|
||||
return Order(strategy, Math.Abs(quantity) * -1, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -599,13 +651,14 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="strategy">Specification of the strategy to trade</param>
|
||||
/// <param name="quantity">Quantity of the strategy to trade</param>
|
||||
/// <returns>Sequence of order ids</returns>
|
||||
public IEnumerable<OrderTicket> Order(OptionStrategy strategy, int quantity)
|
||||
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
|
||||
/// <returns>Sequence of order tickets</returns>
|
||||
public IEnumerable<OrderTicket> Order(OptionStrategy strategy, int quantity, IOrderProperties orderProperties = null)
|
||||
{
|
||||
return GenerateOrders(strategy, quantity);
|
||||
return GenerateOrders(strategy, quantity, orderProperties);
|
||||
}
|
||||
|
||||
private IEnumerable<OrderTicket> GenerateOrders(OptionStrategy strategy, int strategyQuantity)
|
||||
private IEnumerable<OrderTicket> GenerateOrders(OptionStrategy strategy, int strategyQuantity, IOrderProperties orderProperties = null)
|
||||
{
|
||||
var orders = new List<OrderTicket>();
|
||||
|
||||
@@ -638,11 +691,11 @@ namespace QuantConnect.Algorithm
|
||||
switch (optionLeg.OrderType)
|
||||
{
|
||||
case OrderType.Market:
|
||||
orders.Add(MarketOrder(contract.Symbol, orderQuantity, tag: tag));
|
||||
orders.Add(MarketOrder(contract.Symbol, orderQuantity, tag: tag, orderProperties: orderProperties));
|
||||
break;
|
||||
|
||||
case OrderType.Limit:
|
||||
orders.Add(LimitOrder(contract.Symbol, orderQuantity, optionLeg.OrderPrice, tag));
|
||||
orders.Add(LimitOrder(contract.Symbol, orderQuantity, optionLeg.OrderPrice, tag, orderProperties));
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -667,11 +720,11 @@ namespace QuantConnect.Algorithm
|
||||
switch (underlyingLeg.OrderType)
|
||||
{
|
||||
case OrderType.Market:
|
||||
orders.Add(MarketOrder(strategy.Underlying, orderQuantity, tag: tag));
|
||||
orders.Add(MarketOrder(strategy.Underlying, orderQuantity, tag: tag, orderProperties: orderProperties));
|
||||
break;
|
||||
|
||||
case OrderType.Limit:
|
||||
orders.Add(LimitOrder(strategy.Underlying, orderQuantity, underlyingLeg.OrderPrice, tag));
|
||||
orders.Add(LimitOrder(strategy.Underlying, orderQuantity, underlyingLeg.OrderPrice, tag, orderProperties));
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -959,15 +1012,17 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="targets">The portfolio desired quantities as percentages</param>
|
||||
/// <param name="liquidateExistingHoldings">True will liquidate existing holdings</param>
|
||||
/// <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)"/>
|
||||
public void SetHoldings(List<PortfolioTarget> targets, bool liquidateExistingHoldings = false)
|
||||
public void SetHoldings(List<PortfolioTarget> targets, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
foreach (var portfolioTarget in targets
|
||||
// we need to create targets with quantities for OrderTargetsByMarginImpact
|
||||
.Select(target => new PortfolioTarget(target.Symbol, CalculateOrderQuantity(target.Symbol, target.Quantity)))
|
||||
.OrderTargetsByMarginImpact(this, targetIsDelta:true))
|
||||
{
|
||||
SetHoldingsImpl(portfolioTarget.Symbol, portfolioTarget.Quantity, liquidateExistingHoldings);
|
||||
SetHoldingsImpl(portfolioTarget.Symbol, portfolioTarget.Quantity, liquidateExistingHoldings, tag, orderProperties);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -977,10 +1032,12 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="symbol">string symbol we wish to hold</param>
|
||||
/// <param name="percentage">double percentage of holdings desired</param>
|
||||
/// <param name="liquidateExistingHoldings">liquidate existing holdings if necessary to hold this stock</param>
|
||||
/// <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)"/>
|
||||
public void SetHoldings(Symbol symbol, double percentage, bool liquidateExistingHoldings = false)
|
||||
public void SetHoldings(Symbol symbol, double percentage, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
SetHoldings(symbol, percentage.SafeDecimalCast(), liquidateExistingHoldings);
|
||||
SetHoldings(symbol, percentage.SafeDecimalCast(), liquidateExistingHoldings, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -990,10 +1047,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="percentage">float percentage of holdings desired</param>
|
||||
/// <param name="liquidateExistingHoldings">bool liquidate existing holdings if necessary to hold this stock</param>
|
||||
/// <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)"/>
|
||||
public void SetHoldings(Symbol symbol, float percentage, bool liquidateExistingHoldings = false, string tag = "")
|
||||
public void SetHoldings(Symbol symbol, float percentage, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
SetHoldings(symbol, (decimal)percentage, liquidateExistingHoldings, tag);
|
||||
SetHoldings(symbol, (decimal)percentage, liquidateExistingHoldings, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1003,10 +1061,11 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="percentage">float percentage of holdings desired</param>
|
||||
/// <param name="liquidateExistingHoldings">bool liquidate existing holdings if necessary to hold this stock</param>
|
||||
/// <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)"/>
|
||||
public void SetHoldings(Symbol symbol, int percentage, bool liquidateExistingHoldings = false, string tag = "")
|
||||
public void SetHoldings(Symbol symbol, int percentage, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
SetHoldings(symbol, (decimal)percentage, liquidateExistingHoldings, tag);
|
||||
SetHoldings(symbol, (decimal)percentage, liquidateExistingHoldings, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1019,16 +1078,17 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="percentage">decimal fraction of portfolio to set stock</param>
|
||||
/// <param name="liquidateExistingHoldings">bool flag to clean all existing holdings before setting new faction.</param>
|
||||
/// <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)"/>
|
||||
public void SetHoldings(Symbol symbol, decimal percentage, bool liquidateExistingHoldings = false, string tag = "")
|
||||
public void SetHoldings(Symbol symbol, decimal percentage, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
SetHoldingsImpl(symbol, CalculateOrderQuantity(symbol, percentage), liquidateExistingHoldings, tag);
|
||||
SetHoldingsImpl(symbol, CalculateOrderQuantity(symbol, percentage), liquidateExistingHoldings, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set holdings implementation, which uses order quantities (delta) not percentage nor target final quantity
|
||||
/// </summary>
|
||||
private void SetHoldingsImpl(Symbol symbol, decimal orderQuantity, bool liquidateExistingHoldings = false, string tag = "")
|
||||
private void SetHoldingsImpl(Symbol symbol, decimal orderQuantity, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
//If they triggered a liquidate
|
||||
if (liquidateExistingHoldings)
|
||||
@@ -1041,7 +1101,7 @@ namespace QuantConnect.Algorithm
|
||||
{
|
||||
//Go through all existing holdings [synchronously], market order the inverse quantity:
|
||||
var liquidationQuantity = CalculateOrderQuantity(holdingSymbol, 0m);
|
||||
Order(holdingSymbol, liquidationQuantity, false, tag);
|
||||
Order(holdingSymbol, liquidationQuantity, false, tag, orderProperties);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1067,11 +1127,11 @@ namespace QuantConnect.Algorithm
|
||||
//Check whether the exchange is open to send a market order. If not, send a market on open order instead
|
||||
if (security.Exchange.ExchangeOpen)
|
||||
{
|
||||
MarketOrder(symbol, quantity, false, tag);
|
||||
MarketOrder(symbol, quantity, false, tag, orderProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
MarketOnOpenOrder(symbol, quantity, tag);
|
||||
MarketOnOpenOrder(symbol, quantity, tag, orderProperties);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1115,19 +1175,21 @@ namespace QuantConnect.Algorithm
|
||||
/// <param name="type">Order Type</param>
|
||||
/// <param name="asynchronous">Don't wait for the response, just submit order and move on.</param>
|
||||
/// <param name="tag">Custom data for this order</param>
|
||||
/// <returns>Integer Order ID.</returns>
|
||||
/// <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.")]
|
||||
public OrderTicket Order(Symbol symbol, int quantity, OrderType type, bool asynchronous = false, string tag = "")
|
||||
public OrderTicket Order(Symbol symbol, int quantity, OrderType type, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
|
||||
{
|
||||
return Order(symbol, quantity, asynchronous, tag);
|
||||
return Order(symbol, quantity, asynchronous, tag, orderProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obsolete method for placing orders.
|
||||
/// </summary>
|
||||
/// <param name="symbol"></param>
|
||||
/// <param name="quantity"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="symbol">Symbol we want to order</param>
|
||||
/// <param name="quantity">The quantity to order</param>
|
||||
/// <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.")]
|
||||
public OrderTicket Order(Symbol symbol, decimal quantity, OrderType type)
|
||||
{
|
||||
@@ -1137,9 +1199,10 @@ namespace QuantConnect.Algorithm
|
||||
/// <summary>
|
||||
/// Obsolete method for placing orders.
|
||||
/// </summary>
|
||||
/// <param name="symbol"></param>
|
||||
/// <param name="quantity"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="symbol">Symbol we want to order</param>
|
||||
/// <param name="quantity">The quantity to order</param>
|
||||
/// <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.")]
|
||||
public OrderTicket Order(Symbol symbol, int quantity, OrderType type)
|
||||
{
|
||||
|
||||
@@ -517,7 +517,7 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
/// <param name="security">The security to add</param>
|
||||
/// <param name="configurations">The <see cref="SubscriptionDataConfig"/> instances we want to add</param>
|
||||
private void AddToUserDefinedUniverse(
|
||||
private Security AddToUserDefinedUniverse(
|
||||
Security security,
|
||||
List<SubscriptionDataConfig> configurations)
|
||||
{
|
||||
@@ -532,10 +532,18 @@ namespace QuantConnect.Algorithm
|
||||
securityUniverse?.Remove(security.Symbol);
|
||||
|
||||
Securities.Remove(security.Symbol);
|
||||
Securities.Add(security);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we will reuse existing so we return it to the user
|
||||
security = existingSecurity;
|
||||
}
|
||||
}
|
||||
|
||||
Securities.Add(security);
|
||||
else
|
||||
{
|
||||
Securities.Add(security);
|
||||
}
|
||||
|
||||
// add this security to the user defined universe
|
||||
Universe universe;
|
||||
@@ -587,6 +595,8 @@ namespace QuantConnect.Algorithm
|
||||
// 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.");
|
||||
}
|
||||
|
||||
return security;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1508,8 +1508,7 @@ namespace QuantConnect.Algorithm
|
||||
return security;
|
||||
}
|
||||
|
||||
AddToUserDefinedUniverse(security, configs);
|
||||
return security;
|
||||
return AddToUserDefinedUniverse(security, configs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -2268,8 +2267,7 @@ namespace QuantConnect.Algorithm
|
||||
var configs = SubscriptionManager.SubscriptionDataConfigService.Add(symbol, resolution, fillDataForward, extendedMarketHours, dataNormalizationMode: UniverseSettings.DataNormalizationMode);
|
||||
var security = Securities.CreateSecurity(symbol, configs, leverage);
|
||||
|
||||
AddToUserDefinedUniverse(security, configs);
|
||||
return (T)security;
|
||||
return (T) AddToUserDefinedUniverse(security, configs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.5" />
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.6" />
|
||||
<PackageReference Include="MathNet.Numerics" Version="4.15.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
||||
@@ -11,16 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Algorithm import *
|
||||
from QuantConnect.Algorithm.Framework import *
|
||||
from QuantConnect.Algorithm.Framework.Risk import *
|
||||
from AlgorithmImports import *
|
||||
|
||||
class CompositeRiskManagementModel(RiskManagementModel):
|
||||
'''Provides an implementation of IRiskManagementModel that combines multiple risk models
|
||||
|
||||
@@ -11,9 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from clr import AddReference
|
||||
AddReference("QuantConnect.Algorithm")
|
||||
from QuantConnect.Algorithm.Framework.Risk import *
|
||||
from AlgorithmImports import *
|
||||
|
||||
class NullRiskManagementModel(RiskManagementModel):
|
||||
'''Provides an implementation of IRiskManagementModel that does nothing'''
|
||||
|
||||
@@ -11,17 +11,9 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from AlgorithmImports import *
|
||||
from clr import GetClrType as typeof
|
||||
from clr import AddReference
|
||||
AddReference("System")
|
||||
AddReference("QuantConnect.Common")
|
||||
AddReference("QuantConnect.Algorithm.Framework")
|
||||
|
||||
from QuantConnect import *
|
||||
from QuantConnect.Data import *
|
||||
from QuantConnect.Data.Market import *
|
||||
from QuantConnect.Securities import *
|
||||
from QuantConnect.Algorithm.Framework.Selection import *
|
||||
from Selection.UniverseSelectionModel import UniverseSelectionModel
|
||||
from itertools import groupby
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from datetime import datetime
|
||||
from AlgorithmImports import *
|
||||
|
||||
class UniverseSelectionModel:
|
||||
'''Provides a base class for universe selection models.'''
|
||||
@@ -26,4 +26,4 @@ class UniverseSelectionModel:
|
||||
algorithm: The algorithm instance to create universes for</param>
|
||||
Returns:
|
||||
The universes to be used by the algorithm'''
|
||||
raise NotImplementedError("Types deriving from 'UniverseSelectionModel' must implement the 'def CreateUniverses(QCAlgorithm) method.")
|
||||
raise NotImplementedError("Types deriving from 'UniverseSelectionModel' must implement the 'def CreateUniverses(QCAlgorithm) method.")
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Python.Runtime;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm
|
||||
@@ -23,35 +28,298 @@ namespace QuantConnect.Algorithm
|
||||
/// </summary>
|
||||
public class UniverseDefinitions
|
||||
{
|
||||
private readonly QCAlgorithm _algorithm;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a helper that provides methods for creating universes based on daily dollar volumes
|
||||
/// </summary>
|
||||
public DollarVolumeUniverseDefinitions DollarVolume { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies that universe selection should not make changes on this iteration
|
||||
/// </summary>
|
||||
public Universe.UnchangedUniverse Unchanged => Universe.Unchanged;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a helper that provides methods for creating universes based on daily dollar volumes
|
||||
/// </summary>
|
||||
public DollarVolumeUniverseDefinitions DollarVolume { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a helper that provides methods for creating universes based on index definitions
|
||||
/// </summary>
|
||||
public IndexUniverseDefinitions Index { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a helper that provides methods for creating constituent universes
|
||||
/// </summary>
|
||||
public ConstituentUniverseDefinitions Constituent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UniverseDefinitions"/> class
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance, used for obtaining the default <see cref="UniverseSettings"/></param>
|
||||
public UniverseDefinitions(QCAlgorithm algorithm)
|
||||
{
|
||||
_algorithm = algorithm;
|
||||
DollarVolume = new DollarVolumeUniverseDefinitions(algorithm);
|
||||
Index = new IndexUniverseDefinitions(algorithm);
|
||||
Constituent = new ConstituentUniverseDefinitions(algorithm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="etfTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="etfTicker">Ticker of the ETF to get constituents for</param>
|
||||
/// <param name="market">Market of the ETF</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New ETF constituents Universe</returns>
|
||||
public Universe ETF(
|
||||
string etfTicker,
|
||||
string market = null,
|
||||
UniverseSettings universeSettings = null,
|
||||
Func<IEnumerable<ETFConstituentData>, IEnumerable<Symbol>> universeFilterFunc = null)
|
||||
{
|
||||
market ??= _algorithm.BrokerageModel.DefaultMarkets.TryGetValue(SecurityType.Equity, out var defaultMarket)
|
||||
? defaultMarket
|
||||
: throw new Exception("No default market set for security type: Equity");
|
||||
|
||||
var etfSymbol = new Symbol(
|
||||
SecurityIdentifier.GenerateEquity(
|
||||
etfTicker,
|
||||
market,
|
||||
true,
|
||||
mappingResolveDate: _algorithm.Time.Date),
|
||||
etfTicker);
|
||||
|
||||
return ETF(etfSymbol, universeSettings, universeFilterFunc);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="etfTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="etfTicker">Ticker of the ETF to get constituents for</param>
|
||||
/// <param name="market">Market of the ETF</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New ETF constituents Universe</returns>
|
||||
public Universe ETF(
|
||||
string etfTicker,
|
||||
string market = null,
|
||||
UniverseSettings universeSettings = null,
|
||||
PyObject universeFilterFunc = null)
|
||||
{
|
||||
return ETF(etfTicker, market, universeSettings, universeFilterFunc.ConvertPythonUniverseFilterFunction<ETFConstituentData>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided ETF <paramref name="symbol"/>
|
||||
/// </summary>
|
||||
/// <param name="symbol">ETF Symbol to get constituents for</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New ETF constituents Universe</returns>
|
||||
public Universe ETF(
|
||||
Symbol symbol,
|
||||
UniverseSettings universeSettings = null,
|
||||
Func<IEnumerable<ETFConstituentData>, IEnumerable<Symbol>> universeFilterFunc = null)
|
||||
{
|
||||
return new ETFConstituentsUniverse(symbol, universeSettings ?? _algorithm.UniverseSettings, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided ETF <paramref name="symbol"/>
|
||||
/// </summary>
|
||||
/// <param name="symbol">ETF Symbol to get constituents for</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New ETF constituents Universe</returns>
|
||||
public Universe ETF(
|
||||
Symbol symbol,
|
||||
UniverseSettings universeSettings = null,
|
||||
PyObject universeFilterFunc = null)
|
||||
{
|
||||
return ETF(symbol, universeSettings, universeFilterFunc.ConvertPythonUniverseFilterFunction<ETFConstituentData>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="indexTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="indexTicker">Ticker of the index to get constituents for</param>
|
||||
/// <param name="market">Market of the index</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New index constituents Universe</returns>
|
||||
public Universe Index(
|
||||
string indexTicker,
|
||||
string market = null,
|
||||
UniverseSettings universeSettings = null,
|
||||
Func<IEnumerable<ETFConstituentData>, IEnumerable<Symbol>> universeFilterFunc = null)
|
||||
{
|
||||
market ??= _algorithm.BrokerageModel.DefaultMarkets.TryGetValue(SecurityType.Index, out var defaultMarket)
|
||||
? defaultMarket
|
||||
: throw new Exception("No default market set for security type: Index");
|
||||
|
||||
return Index(
|
||||
Symbol.Create(indexTicker, SecurityType.Index, market),
|
||||
universeSettings,
|
||||
universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="indexTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="indexTicker">Ticker of the index to get constituents for</param>
|
||||
/// <param name="market">Market of the index</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New index constituents Universe</returns>
|
||||
public Universe Index(
|
||||
string indexTicker,
|
||||
string market = null,
|
||||
UniverseSettings universeSettings = null,
|
||||
PyObject universeFilterFunc = null)
|
||||
{
|
||||
return Index(indexTicker, market, universeSettings, universeFilterFunc.ConvertPythonUniverseFilterFunction<ETFConstituentData>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="indexSymbol"/>
|
||||
/// </summary>
|
||||
/// <param name="indexSymbol">Index Symbol to get constituents for</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New index constituents Universe</returns>
|
||||
public Universe Index(
|
||||
Symbol indexSymbol,
|
||||
UniverseSettings universeSettings = null,
|
||||
Func<IEnumerable<ETFConstituentData>, IEnumerable<Symbol>> universeFilterFunc = null)
|
||||
{
|
||||
return new ETFConstituentsUniverse(indexSymbol, universeSettings ?? _algorithm.UniverseSettings, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="indexSymbol"/>
|
||||
/// </summary>
|
||||
/// <param name="indexSymbol">Index Symbol to get constituents for</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New index constituents Universe</returns>
|
||||
public Universe Index(
|
||||
Symbol indexSymbol,
|
||||
UniverseSettings universeSettings = null,
|
||||
PyObject universeFilterFunc = null)
|
||||
{
|
||||
return Index(indexSymbol, universeSettings, universeFilterFunc.ConvertPythonUniverseFilterFunction<ETFConstituentData>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new fine universe that contains the constituents of QC500 index based onthe company fundamentals
|
||||
/// The algorithm creates a default tradable and liquid universe containing 500 US equities
|
||||
/// which are chosen at the first trading day of each month.
|
||||
/// </summary>
|
||||
/// <returns>A new coarse universe for the top count of stocks by dollar volume</returns>
|
||||
public Universe QC500
|
||||
{
|
||||
get
|
||||
{
|
||||
var lastMonth = -1;
|
||||
var numberOfSymbolsCoarse = 1000;
|
||||
var numberOfSymbolsFine = 500;
|
||||
var dollarVolumeBySymbol = new Dictionary<Symbol, decimal>();
|
||||
var symbol = Symbol.Create("qc-500", SecurityType.Equity, Market.USA);
|
||||
|
||||
var coarseUniverse = new CoarseFundamentalUniverse(
|
||||
symbol,
|
||||
_algorithm.UniverseSettings,
|
||||
coarse =>
|
||||
{
|
||||
if (_algorithm.Time.Month == lastMonth)
|
||||
{
|
||||
return Universe.Unchanged;
|
||||
}
|
||||
|
||||
// The stocks must have fundamental data
|
||||
// The stock must have positive previous-day close price
|
||||
// The stock must have positive volume on the previous trading day
|
||||
var sortedByDollarVolume =
|
||||
(from x in coarse
|
||||
where x.HasFundamentalData && x.Volume > 0 && x.Price > 0
|
||||
orderby x.DollarVolume descending
|
||||
select x).Take(numberOfSymbolsCoarse).ToList();
|
||||
|
||||
dollarVolumeBySymbol.Clear();
|
||||
foreach (var x in sortedByDollarVolume)
|
||||
{
|
||||
dollarVolumeBySymbol[x.Symbol] = x.DollarVolume;
|
||||
}
|
||||
|
||||
// If no security has met the QC500 criteria, the universe is unchanged.
|
||||
// A new selection will be attempted on the next trading day as lastMonth is not updated
|
||||
if (dollarVolumeBySymbol.Count == 0)
|
||||
{
|
||||
return Universe.Unchanged;
|
||||
}
|
||||
|
||||
return dollarVolumeBySymbol.Keys;
|
||||
});
|
||||
|
||||
return new FineFundamentalFilteredUniverse(
|
||||
coarseUniverse,
|
||||
fine =>
|
||||
{
|
||||
// The company's headquarter must in the U.S.
|
||||
// The stock must be traded on either the NYSE or NASDAQ
|
||||
// At least half a year since its initial public offering
|
||||
// The stock's market cap must be greater than 500 million
|
||||
var filteredFine =
|
||||
(from x in fine
|
||||
where x.CompanyReference.CountryId == "USA" &&
|
||||
(x.CompanyReference.PrimaryExchangeID == "NYS" ||
|
||||
x.CompanyReference.PrimaryExchangeID == "NAS") &&
|
||||
(_algorithm.Time - x.SecurityReference.IPODate).Days > 180 &&
|
||||
x.MarketCap > 500000000m
|
||||
select x).ToList();
|
||||
|
||||
var count = filteredFine.Count;
|
||||
|
||||
// If no security has met the QC500 criteria, the universe is unchanged.
|
||||
// A new selection will be attempted on the next trading day as lastMonth is not updated
|
||||
if (count == 0)
|
||||
{
|
||||
return Universe.Unchanged;
|
||||
}
|
||||
|
||||
// Update _lastMonth after all QC500 criteria checks passed
|
||||
lastMonth = _algorithm.Time.Month;
|
||||
|
||||
var percent = numberOfSymbolsFine / (double) count;
|
||||
|
||||
// select stocks with top dollar volume in every single sector
|
||||
var topFineBySector =
|
||||
(from x in filteredFine
|
||||
// Group by sector
|
||||
group x by x.CompanyReference.IndustryTemplateCode
|
||||
into g
|
||||
let y = from item in g
|
||||
orderby dollarVolumeBySymbol[item.Symbol] descending
|
||||
select item
|
||||
let c = (int) Math.Ceiling(y.Count() * percent)
|
||||
select new {g.Key, Value = y.Take(c)}
|
||||
).ToDictionary(x => x.Key, x => x.Value);
|
||||
|
||||
return topFineBySector.SelectMany(x => x.Value)
|
||||
.OrderByDescending(x => dollarVolumeBySymbol[x.Symbol])
|
||||
.Take(numberOfSymbolsFine)
|
||||
.Select(x => x.Symbol);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new coarse universe that contains the top count of stocks
|
||||
/// by daily dollar volume
|
||||
/// </summary>
|
||||
/// <param name="count">The number of stock to select</param>
|
||||
/// <param name="universeSettings">The settings for stocks added by this universe.
|
||||
/// Defaults to <see cref="QCAlgorithm.UniverseSettings"/></param>
|
||||
/// <returns>A new coarse universe for the top count of stocks by dollar volume</returns>
|
||||
public Universe Top(int count, UniverseSettings universeSettings = null)
|
||||
{
|
||||
universeSettings ??= _algorithm.UniverseSettings;
|
||||
|
||||
var symbol = Symbol.Create("us-equity-dollar-volume-top-" + count, SecurityType.Equity, Market.USA);
|
||||
var config = new SubscriptionDataConfig(typeof(CoarseFundamental), symbol, Resolution.Daily, TimeZones.NewYork, TimeZones.NewYork, false, false, true);
|
||||
return new FuncUniverse(config, universeSettings, selectionData => (
|
||||
from c in selectionData.OfType<CoarseFundamental>()
|
||||
orderby c.DollarVolume descending
|
||||
select c.Symbol).Take(count)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.5" />
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.6" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
@@ -51,4 +51,4 @@
|
||||
<PackagePath></PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
@@ -12,22 +12,22 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace QuantConnect.Brokerages
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper for WebSocket4Net to enhance testability
|
||||
/// </summary>
|
||||
public interface IWebSocket
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Wraps constructor
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
void Initialize(string url);
|
||||
/// <param name="url">The target websocket url</param>
|
||||
/// <param name="sessionToken">The websocket session token</param>
|
||||
void Initialize(string url, string sessionToken = null);
|
||||
|
||||
/// <summary>
|
||||
/// Wraps send method
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
|
||||
{ Market.COMEX, "NYMEX" },
|
||||
{ Market.CBOT, "ECBOT" },
|
||||
{ Market.ICE, "NYBOT" },
|
||||
{ Market.CBOE, "CFE" }
|
||||
{ Market.CFE, "CFE" }
|
||||
};
|
||||
|
||||
private readonly SymbolPropertiesDatabase _symbolPropertiesDatabase = SymbolPropertiesDatabase.FromDataFolder();
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="NodaTime" Version="3.0.5" />
|
||||
<PackageReference Include="QuantConnect.IBAutomater" Version="2.0.52" />
|
||||
<PackageReference Include="QuantConnect.IBAutomater" Version="2.0.56" />
|
||||
<PackageReference Include="RestSharp" Version="106.12.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -20,6 +20,7 @@ using System.Linq;
|
||||
using NodaTime;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Logging;
|
||||
using HistoryRequest = QuantConnect.Data.HistoryRequest;
|
||||
|
||||
namespace QuantConnect.Brokerages.Tradier
|
||||
@@ -81,7 +82,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
{
|
||||
foreach (var request in requests)
|
||||
{
|
||||
if (request.Symbol.ID.SecurityType != SecurityType.Equity)
|
||||
if (request.Symbol.ID.SecurityType != SecurityType.Equity && request.Symbol.ID.SecurityType != SecurityType.Option)
|
||||
{
|
||||
throw new ArgumentException("Invalid security type: " + request.Symbol.ID.SecurityType);
|
||||
}
|
||||
@@ -91,6 +92,17 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
throw new ArgumentException("Invalid date range specified");
|
||||
}
|
||||
|
||||
if (request.Symbol.IsCanonical())
|
||||
{
|
||||
throw new ArgumentException("Invalid symbol, cannot use canonical symbols for history request");
|
||||
}
|
||||
|
||||
if (request.DataType == typeof(QuoteBar))
|
||||
{
|
||||
Log.Error("TradierBrokerage.GetHistory(): Tradier only supports TradeBars");
|
||||
yield break;
|
||||
}
|
||||
|
||||
var start = request.StartTimeUtc.ConvertTo(DateTimeZone.Utc, TimeZones.NewYork);
|
||||
var end = request.EndTimeUtc.ConvertTo(DateTimeZone.Utc, TimeZones.NewYork);
|
||||
|
||||
@@ -164,7 +176,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
|
||||
private IEnumerable<Slice> GetHistoryTick(Symbol symbol, DateTime start, DateTime end)
|
||||
{
|
||||
var history = GetTimeSeries(symbol.Value, start, end, TradierTimeSeriesIntervals.Tick);
|
||||
var history = GetTimeSeries(symbol, start, end, TradierTimeSeriesIntervals.Tick);
|
||||
|
||||
if (history == null)
|
||||
return Enumerable.Empty<Slice>();
|
||||
@@ -185,7 +197,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
|
||||
private IEnumerable<Slice> GetHistorySecond(Symbol symbol, DateTime start, DateTime end)
|
||||
{
|
||||
var history = GetTimeSeries(symbol.Value, start, end, TradierTimeSeriesIntervals.Tick);
|
||||
var history = GetTimeSeries(symbol, start, end, TradierTimeSeriesIntervals.Tick);
|
||||
|
||||
if (history == null)
|
||||
return Enumerable.Empty<Slice>();
|
||||
@@ -220,7 +232,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
|
||||
private IEnumerable<Slice> GetHistoryMinute(Symbol symbol, DateTime start, DateTime end)
|
||||
{
|
||||
var history = GetTimeSeries(symbol.Value, start, end, TradierTimeSeriesIntervals.OneMinute);
|
||||
var history = GetTimeSeries(symbol, start, end, TradierTimeSeriesIntervals.OneMinute);
|
||||
|
||||
if (history == null)
|
||||
return Enumerable.Empty<Slice>();
|
||||
@@ -234,7 +246,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
|
||||
private IEnumerable<Slice> GetHistoryHour(Symbol symbol, DateTime start, DateTime end)
|
||||
{
|
||||
var history = GetTimeSeries(symbol.Value, start, end, TradierTimeSeriesIntervals.FifteenMinutes);
|
||||
var history = GetTimeSeries(symbol, start, end, TradierTimeSeriesIntervals.FifteenMinutes);
|
||||
|
||||
if (history == null)
|
||||
return Enumerable.Empty<Slice>();
|
||||
@@ -262,7 +274,7 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
|
||||
private IEnumerable<Slice> GetHistoryDaily(Symbol symbol, DateTime start, DateTime end)
|
||||
{
|
||||
var history = GetHistoricalData(symbol.Value, start, end);
|
||||
var history = GetHistoricalData(symbol, start, end);
|
||||
|
||||
DataPointCount += history.Count;
|
||||
|
||||
|
||||
@@ -494,11 +494,12 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
/// <summary>
|
||||
/// Get the historical bars for this period
|
||||
/// </summary>
|
||||
public List<TradierTimeSeries> GetTimeSeries(string symbol, DateTime start, DateTime end, TradierTimeSeriesIntervals interval)
|
||||
public List<TradierTimeSeries> GetTimeSeries(Symbol symbol, DateTime start, DateTime end, TradierTimeSeriesIntervals interval)
|
||||
{
|
||||
//Send Request:
|
||||
// Create and send request
|
||||
var ticker = _symbolMapper.GetBrokerageSymbol(symbol);
|
||||
var request = new RestRequest("markets/timesales", Method.GET);
|
||||
request.AddParameter("symbol", symbol, ParameterType.QueryString);
|
||||
request.AddParameter("symbol", ticker, ParameterType.QueryString);
|
||||
request.AddParameter("interval", GetEnumDescription(interval), ParameterType.QueryString);
|
||||
request.AddParameter("start", start.ToStringInvariant("yyyy-MM-dd HH:mm"), ParameterType.QueryString);
|
||||
request.AddParameter("end", end.ToStringInvariant("yyyy-MM-dd HH:mm"), ParameterType.QueryString);
|
||||
@@ -509,13 +510,15 @@ namespace QuantConnect.Brokerages.Tradier
|
||||
/// <summary>
|
||||
/// Get full daily, weekly or monthly bars of historical periods:
|
||||
/// </summary>
|
||||
public List<TradierHistoryBar> GetHistoricalData(string symbol,
|
||||
public List<TradierHistoryBar> GetHistoricalData(Symbol symbol,
|
||||
DateTime start,
|
||||
DateTime end,
|
||||
TradierHistoricalDataIntervals interval = TradierHistoricalDataIntervals.Daily)
|
||||
{
|
||||
// Create and send request
|
||||
var ticker = _symbolMapper.GetBrokerageSymbol(symbol);
|
||||
var request = new RestRequest("markets/history", Method.GET);
|
||||
request.AddParameter("symbol", symbol, ParameterType.QueryString);
|
||||
request.AddParameter("symbol", ticker, ParameterType.QueryString);
|
||||
request.AddParameter("start", start.ToStringInvariant("yyyy-MM-dd"), ParameterType.QueryString);
|
||||
request.AddParameter("end", end.ToStringInvariant("yyyy-MM-dd"), ParameterType.QueryString);
|
||||
request.AddParameter("interval", GetEnumDescription(interval));
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Logging;
|
||||
using QuantConnect.Util;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using QuantConnect.Logging;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Brokerages
|
||||
{
|
||||
@@ -32,6 +32,7 @@ namespace QuantConnect.Brokerages
|
||||
private const int ReceiveBufferSize = 8192;
|
||||
|
||||
private string _url;
|
||||
private string _sessionToken;
|
||||
private CancellationTokenSource _cts;
|
||||
private ClientWebSocket _client;
|
||||
private Task _taskConnect;
|
||||
@@ -40,10 +41,12 @@ namespace QuantConnect.Brokerages
|
||||
/// <summary>
|
||||
/// Wraps constructor
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
public void Initialize(string url)
|
||||
/// <param name="url">The target websocket url</param>
|
||||
/// <param name="sessionToken">The websocket session token</param>
|
||||
public void Initialize(string url, string sessionToken = null)
|
||||
{
|
||||
_url = url;
|
||||
_sessionToken = sessionToken;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -209,10 +212,14 @@ namespace QuantConnect.Brokerages
|
||||
{
|
||||
try
|
||||
{
|
||||
lock(_locker)
|
||||
lock (_locker)
|
||||
{
|
||||
_client.DisposeSafely();
|
||||
_client = new ClientWebSocket();
|
||||
if (_sessionToken != null)
|
||||
{
|
||||
_client.Options.SetRequestHeader("x-session-token", _sessionToken);
|
||||
}
|
||||
_client.ConnectAsync(new Uri(_url), connectionCts.Token).SynchronouslyAwaitTask();
|
||||
}
|
||||
OnOpen();
|
||||
@@ -280,12 +287,12 @@ namespace QuantConnect.Brokerages
|
||||
{
|
||||
return new TextMessage
|
||||
{
|
||||
Message = Encoding.UTF8.GetString(ms.GetBuffer(), 0 , (int)ms.Length),
|
||||
Message = Encoding.UTF8.GetString(ms.GetBuffer(), 0, (int)ms.Length),
|
||||
};
|
||||
}
|
||||
else if (result.MessageType == WebSocketMessageType.Close)
|
||||
{
|
||||
Log.Trace($"WebSocketClientWrapper.HandleConnection({_url}): WebSocketMessageType.Close - Data: {Encoding.UTF8.GetString(ms.GetBuffer(), 0 , (int)ms.Length)}");
|
||||
Log.Trace($"WebSocketClientWrapper.HandleConnection({_url}): WebSocketMessageType.Close - Data: {Encoding.UTF8.GetString(ms.GetBuffer(), 0, (int)ms.Length)}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,12 +266,8 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
.Value;
|
||||
if (order == null)
|
||||
{
|
||||
order = _algorithm.Transactions.GetOrderByBrokerageId(brokerId);
|
||||
if (order == null)
|
||||
{
|
||||
// not our order, nothing else to do here
|
||||
return;
|
||||
}
|
||||
Log.Error($"ZerodhaBrokerage.OnOrderUpdate(): order not found: BrokerId: {brokerId}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (orderUpdate.Status == "CANCELLED")
|
||||
@@ -295,7 +291,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
{
|
||||
var symbol = _symbolMapper.ConvertZerodhaSymbolToLeanSymbol(orderUpdate.InstrumentToken);
|
||||
var fillPrice = orderUpdate.AveragePrice;
|
||||
var fillQuantity = orderUpdate.FilledQuantity;
|
||||
decimal cumulativeFillQuantity = orderUpdate.FilledQuantity;
|
||||
var direction = orderUpdate.TransactionType == "SELL" ? OrderDirection.Sell : OrderDirection.Buy;
|
||||
var updTime = orderUpdate.OrderTimestamp.GetValueOrDefault();
|
||||
|
||||
@@ -303,27 +299,32 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
var orderFee = security.FeeModel.GetOrderFee(
|
||||
new OrderFeeParameters(security, order));
|
||||
|
||||
|
||||
if (direction == OrderDirection.Sell)
|
||||
{
|
||||
fillQuantity = -1 * fillQuantity;
|
||||
cumulativeFillQuantity = -1 * cumulativeFillQuantity;
|
||||
}
|
||||
|
||||
var status = OrderStatus.Filled;
|
||||
if (fillQuantity != order.Quantity)
|
||||
if (cumulativeFillQuantity != order.Quantity)
|
||||
{
|
||||
decimal totalFillQuantity;
|
||||
_fills.TryGetValue(order.Id, out totalFillQuantity);
|
||||
totalFillQuantity += fillQuantity;
|
||||
_fills[order.Id] = totalFillQuantity;
|
||||
status = totalFillQuantity == order.Quantity
|
||||
? OrderStatus.Filled
|
||||
: OrderStatus.PartiallyFilled;
|
||||
status = OrderStatus.PartiallyFilled;
|
||||
}
|
||||
|
||||
decimal totalRegisteredFillQuantity;
|
||||
_fills.TryGetValue(order.Id, out totalRegisteredFillQuantity);
|
||||
//async events received from zerodha: https://kite.trade/forum/discussion/comment/34752/#Comment_34752
|
||||
if (Math.Abs(cumulativeFillQuantity) <= Math.Abs(totalRegisteredFillQuantity))
|
||||
{
|
||||
// already filled more quantity
|
||||
return;
|
||||
}
|
||||
_fills[order.Id] = cumulativeFillQuantity;
|
||||
var fillQuantityInThisEvewnt = cumulativeFillQuantity - totalRegisteredFillQuantity;
|
||||
|
||||
var orderEvent = new OrderEvent
|
||||
(
|
||||
order.Id, symbol, updTime, status,
|
||||
direction, fillPrice, fillQuantity,
|
||||
direction, fillPrice, fillQuantityInThisEvewnt,
|
||||
orderFee, $"Zerodha Order Event {direction}"
|
||||
);
|
||||
|
||||
@@ -417,7 +418,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
var security = _securityProvider.GetSecurity(order.Symbol);
|
||||
var orderFee = security.FeeModel.GetOrderFee(
|
||||
new OrderFeeParameters(security, order));
|
||||
var orderProperties = order.Properties as ZerodhaOrderProperties;
|
||||
var orderProperties = order.Properties as IndiaOrderProperties;
|
||||
var zerodhaProductType = _zerodhaProductType;
|
||||
if (orderProperties == null || orderProperties.Exchange == null)
|
||||
{
|
||||
@@ -436,7 +437,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
}
|
||||
try
|
||||
{
|
||||
orderResponse = _kite.PlaceOrder(orderProperties.Exchange.ToUpperInvariant(), order.Symbol.ID.Symbol, order.Direction.ToString().ToUpperInvariant(),
|
||||
orderResponse = _kite.PlaceOrder(orderProperties.Exchange.ToString(), order.Symbol.ID.Symbol, order.Direction.ToString().ToUpperInvariant(),
|
||||
orderQuantity, orderPrice, zerodhaProductType, kiteOrderType, null, null, triggerPrice);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -572,7 +573,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
return;
|
||||
}
|
||||
|
||||
var orderProperties = order.Properties as ZerodhaOrderProperties;
|
||||
var orderProperties = order.Properties as IndiaOrderProperties;
|
||||
var zerodhaProductType = _zerodhaProductType;
|
||||
if (orderProperties == null || orderProperties.Exchange == null)
|
||||
{
|
||||
@@ -600,7 +601,7 @@ namespace QuantConnect.Brokerages.Zerodha
|
||||
{
|
||||
orderResponse = _kite.ModifyOrder(order.BrokerId[0].ToStringInvariant(),
|
||||
null,
|
||||
orderProperties.Exchange.ToUpperInvariant(),
|
||||
orderProperties.Exchange.ToString(),
|
||||
order.Symbol.ID.Symbol,
|
||||
order.Direction.ToString().ToUpperInvariant(),
|
||||
orderQuantity,
|
||||
|
||||
@@ -53,6 +53,7 @@ from QuantConnect.Lean.Engine import *
|
||||
from QuantConnect.Orders.Fills import *
|
||||
from QuantConnect.Configuration import *
|
||||
from QuantConnect.Notifications import *
|
||||
from QuantConnect.Data.Auxiliary import *
|
||||
from QuantConnect.Data.Shortable import *
|
||||
from QuantConnect.Orders.Slippage import *
|
||||
from QuantConnect.Securities.Forex import *
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
@@ -81,6 +81,11 @@ namespace QuantConnect.Brokerages
|
||||
/// </summary>
|
||||
Zerodha,
|
||||
|
||||
/// <summary>
|
||||
/// Transaction and submit/execution rules will use Samco models
|
||||
/// </summary>
|
||||
Samco,
|
||||
|
||||
/// <summary>
|
||||
/// Transaction and submit/execution rules will use atreyu models
|
||||
/// </summary>
|
||||
@@ -89,6 +94,11 @@ namespace QuantConnect.Brokerages
|
||||
/// <summary>
|
||||
/// Transaction and submit/execution rules will use TradingTechnologies models
|
||||
/// </summary>
|
||||
TradingTechnologies
|
||||
TradingTechnologies,
|
||||
|
||||
/// <summary>
|
||||
/// Transaction and submit/execution rules will use Kraken models
|
||||
/// </summary>
|
||||
Kraken
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,6 +221,12 @@ namespace QuantConnect.Brokerages
|
||||
|
||||
case BrokerageName.TradingTechnologies:
|
||||
return new TradingTechnologiesBrokerageModel(accountType);
|
||||
|
||||
case BrokerageName.Samco:
|
||||
return new SamcoBrokerageModel(accountType);
|
||||
|
||||
case BrokerageName.Kraken:
|
||||
return new KrakenBrokerageModel(accountType);
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(brokerage), brokerage, null);
|
||||
|
||||
197
Common/Brokerages/KrakenBrokerageModel.cs
Normal file
197
Common/Brokerages/KrakenBrokerageModel.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Benchmarks;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Brokerages
|
||||
{
|
||||
/// <summary>
|
||||
/// Kraken Brokerage model
|
||||
/// </summary>
|
||||
public class KrakenBrokerageModel : DefaultBrokerageModel
|
||||
{
|
||||
private readonly List<string> _fiatsAvailableMargin = new() {"USD", "EUR"};
|
||||
private readonly List<string> _onlyFiatsAvailableMargin = new() {"BTC", "USDT", "USDC"};
|
||||
private readonly List<string> _ethAvailableMargin = new() {"REP", "XTZ", "ADA", "EOS", "TRX", "LINK" };
|
||||
|
||||
/// <summary>
|
||||
/// Gets a map of the default markets to be used for each security type
|
||||
/// </summary>
|
||||
public override IReadOnlyDictionary<SecurityType, string> DefaultMarkets { get; } = GetDefaultMarkets();
|
||||
|
||||
/// <summary>
|
||||
/// Leverage map of different coins
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, decimal> CoinLeverage { get; } = new Dictionary<string, decimal>
|
||||
{
|
||||
{"BTC", 5}, // only with fiats
|
||||
{"ETH", 5},
|
||||
{"USDT", 2}, // only with fiats
|
||||
{"XMR", 2},
|
||||
{"REP", 2}, // eth available
|
||||
{"XRP", 3},
|
||||
{"BCH", 2},
|
||||
{"XTZ", 2}, // eth available
|
||||
{"LTC", 3},
|
||||
{"ADA", 3}, // eth available
|
||||
{"EOS", 3}, // eth available
|
||||
{"DASH", 3},
|
||||
{"TRX", 3}, // eth available
|
||||
{"LINK", 3}, // eth available
|
||||
{"USDC", 3}, // only with fiats
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for Kraken brokerage model
|
||||
/// </summary>
|
||||
/// <param name="accountType">Cash or Margin</param>
|
||||
public KrakenBrokerageModel(AccountType accountType = AccountType.Cash) : base(accountType)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the brokerage could accept this order. This takes into account
|
||||
/// order type, security type, and order size limits.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For example, a brokerage may have no connectivity at certain times, or an order rate/size limit
|
||||
/// </remarks>
|
||||
/// <param name="security"></param>
|
||||
/// <param name="order">The order to be processed</param>
|
||||
/// <param name="message">If this function returns false, a brokerage message detailing why the order may not be submitted</param>
|
||||
/// <returns>True if the brokerage could process the order, false otherwise</returns>
|
||||
public override bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message)
|
||||
{
|
||||
message = null;
|
||||
if (security.Type != SecurityType.Crypto)
|
||||
{
|
||||
message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
|
||||
StringExtensions.Invariant($"The {nameof(KrakenBrokerageModel)} does not support {security.Type} security type.")
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
return base.CanSubmitOrder(security, order, out message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Kraken does no support update of orders
|
||||
/// </summary>
|
||||
/// <param name="security">Security</param>
|
||||
/// <param name="order">Order that should be updated</param>
|
||||
/// <param name="request">Update request</param>
|
||||
/// <param name="message">Outgoing message</param>
|
||||
/// <returns>Always false as Kraken does no support update of orders</returns>
|
||||
public override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message)
|
||||
{
|
||||
message = new BrokerageMessageEvent(BrokerageMessageType.Warning, 0, "Brokerage does not support update. You must cancel and re-create instead."); ;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides Kraken fee model
|
||||
/// </summary>
|
||||
/// <param name="security">Security</param>
|
||||
/// <returns>Kraken fee model</returns>
|
||||
public override IFeeModel GetFeeModel(Security security)
|
||||
{
|
||||
return new KrakenFeeModel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a new buying power model for the security, returning the default model with the security's configured leverage.
|
||||
/// For cash accounts, leverage = 1 is used.
|
||||
/// For margin trading, max leverage = 5
|
||||
/// </summary>
|
||||
/// <param name="security">The security to get a buying power model for</param>
|
||||
/// <returns>The buying power model for this brokerage/security</returns>
|
||||
public override IBuyingPowerModel GetBuyingPowerModel(Security security)
|
||||
{
|
||||
if (AccountType == AccountType.Margin)
|
||||
{
|
||||
return new SecurityMarginModel(GetLeverage(security));
|
||||
}
|
||||
|
||||
return new CashBuyingPowerModel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Kraken global leverage rule
|
||||
/// </summary>
|
||||
/// <param name="security"></param>
|
||||
/// <returns></returns>
|
||||
public override decimal GetLeverage(Security security)
|
||||
{
|
||||
if (AccountType == AccountType.Cash)
|
||||
{
|
||||
return 1m;
|
||||
}
|
||||
|
||||
// first check whether this security support margin only with fiats.
|
||||
foreach (var coin in _onlyFiatsAvailableMargin.Where(coin => security.Symbol.ID.Symbol.StartsWith(coin)).Where(coin => _fiatsAvailableMargin.Any(rightFiat => security.Symbol.Value.EndsWith(rightFiat))))
|
||||
{
|
||||
return CoinLeverage[coin];
|
||||
}
|
||||
|
||||
List<string> extendedCoinArray = new() {"BTC", "ETH"};
|
||||
extendedCoinArray.AddRange(_fiatsAvailableMargin);
|
||||
// Then check whether this security support margin with ETH.
|
||||
foreach (var coin in _ethAvailableMargin.Where(coin => security.Symbol.ID.Symbol.StartsWith(coin)).Where(coin => extendedCoinArray.Any(rightFiat => security.Symbol.Value.EndsWith(rightFiat))))
|
||||
{
|
||||
return CoinLeverage[coin];
|
||||
}
|
||||
|
||||
extendedCoinArray.Remove("ETH");
|
||||
// At the end check all others.
|
||||
foreach (var coin in CoinLeverage.Keys.Where(coin => security.Symbol.ID.Symbol.StartsWith(coin)).Where(coin => extendedCoinArray.Any(rightFiat => security.Symbol.Value.EndsWith(rightFiat))))
|
||||
{
|
||||
return CoinLeverage[coin];
|
||||
}
|
||||
|
||||
return 1m;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the benchmark for this model
|
||||
/// </summary>
|
||||
/// <param name="securities">SecurityService to create the security with if needed</param>
|
||||
/// <returns>The benchmark for this brokerage</returns>
|
||||
public override IBenchmark GetBenchmark(SecurityManager securities)
|
||||
{
|
||||
var symbol = Symbol.Create("BTCUSD", SecurityType.Crypto, Market.Kraken);
|
||||
return SecurityBenchmark.CreateInstance(securities, symbol);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get default markets and specify Kraken as crypto market
|
||||
/// </summary>
|
||||
/// <returns>default markets</returns>
|
||||
private static IReadOnlyDictionary<SecurityType, string> GetDefaultMarkets()
|
||||
{
|
||||
var map = DefaultMarketMap.ToDictionary();
|
||||
map[SecurityType.Crypto] = Market.Kraken;
|
||||
return map.ToReadOnlyDictionary();
|
||||
}
|
||||
}
|
||||
}
|
||||
208
Common/Brokerages/SamcoBrokerageModel.cs
Normal file
208
Common/Brokerages/SamcoBrokerageModel.cs
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* 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.Benchmarks;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using QuantConnect.Orders.TimeInForces;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Util;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static QuantConnect.StringExtensions;
|
||||
|
||||
namespace QuantConnect.Brokerages
|
||||
{
|
||||
/// <summary>
|
||||
/// Brokerage Model implementation for Samco
|
||||
/// </summary>
|
||||
public class SamcoBrokerageModel : DefaultBrokerageModel
|
||||
{
|
||||
private readonly Type[] _supportedTimeInForces =
|
||||
{
|
||||
typeof(GoodTilCanceledTimeInForce),
|
||||
typeof(DayTimeInForce),
|
||||
typeof(GoodTilDateTimeInForce)
|
||||
};
|
||||
|
||||
private const decimal _maxLeverage = 7m;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SamcoBrokerageModel"/> class
|
||||
/// </summary>
|
||||
/// <param name="accountType">The type of account to be modelled, defaults to <see cref="AccountType.Margin"/></param>
|
||||
public SamcoBrokerageModel(AccountType accountType = AccountType.Margin) : base(accountType)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the brokerage would be able to execute this order at this time assuming
|
||||
/// market prices are sufficient for the fill to take place. This is used to emulate the
|
||||
/// brokerage fills in backtesting and paper trading. For example some brokerages may not
|
||||
/// perform executions during extended market hours. This is not intended to be checking
|
||||
/// whether or not the exchange is open, that is handled in the Security.Exchange property.
|
||||
/// </summary>
|
||||
/// <param name="security"></param>
|
||||
/// <param name="order">The order to test for execution</param>
|
||||
/// <returns>True if the brokerage would be able to perform the execution, false otherwise</returns>
|
||||
public override bool CanExecuteOrder(Security security, Order order)
|
||||
{
|
||||
// validate security type
|
||||
if (security.Type != SecurityType.Equity &&
|
||||
security.Type != SecurityType.Option &&
|
||||
security.Type != SecurityType.Future)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// validate time in force
|
||||
if (!_supportedTimeInForces.Contains(order.TimeInForce.GetType()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the brokerage could accept this order. This takes into account order
|
||||
/// type, security type, and order size limits.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For example, a brokerage may have no connectivity at certain times, or an order
|
||||
/// rate/size limit
|
||||
/// </remarks>
|
||||
/// <param name="security">The security being ordered</param>
|
||||
/// <param name="order">The order to be processed</param>
|
||||
/// <param name="message">
|
||||
/// If this function returns false, a brokerage message detailing why the order may not be submitted
|
||||
/// </param>
|
||||
/// <returns>True if the brokerage could process the order, false otherwise</returns>
|
||||
public override bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message)
|
||||
{
|
||||
message = null;
|
||||
|
||||
// validate security type
|
||||
if (security.Type != SecurityType.Equity &&
|
||||
security.Type != SecurityType.Option &&
|
||||
security.Type != SecurityType.Future)
|
||||
{
|
||||
message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
|
||||
Invariant($"The {nameof(SamcoBrokerageModel)} does not support {security.Type} security type.")
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// validate time in force
|
||||
if (!_supportedTimeInForces.Contains(order.TimeInForce.GetType()))
|
||||
{
|
||||
message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
|
||||
Invariant($"The {nameof(SamcoBrokerageModel)} does not support {order.TimeInForce.GetType().Name} time in force.")
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the brokerage would allow updating the order as specified by the request
|
||||
/// </summary>
|
||||
/// <param name="security">The security of the order</param>
|
||||
/// <param name="order">The order to be updated</param>
|
||||
/// <param name="request">The requested update to be made to the order</param>
|
||||
/// <param name="message">
|
||||
/// If this function returns false, a brokerage message detailing why the order may not be updated
|
||||
/// </param>
|
||||
/// <returns>True if the brokerage would allow updating the order, false otherwise</returns>
|
||||
public override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message)
|
||||
{
|
||||
message = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a map of the default markets to be used for each security type
|
||||
/// </summary>
|
||||
public override IReadOnlyDictionary<SecurityType, string> DefaultMarkets { get; } = GetDefaultMarkets();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a new buying power model for the security, returning the default model with the
|
||||
/// security's configured leverage. For cash accounts, leverage = 1 is used. For margin
|
||||
/// trading, max leverage = 7
|
||||
/// </summary>
|
||||
/// <param name="security">The security to get a buying power model for</param>
|
||||
/// <returns>The buying power model for this brokerage/security</returns>
|
||||
public override IBuyingPowerModel GetBuyingPowerModel(Security security)
|
||||
{
|
||||
return AccountType == AccountType.Cash
|
||||
? (IBuyingPowerModel)new CashBuyingPowerModel()
|
||||
: new SecurityMarginModel(_maxLeverage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Samco global leverage rule
|
||||
/// </summary>
|
||||
/// <param name="security"></param>
|
||||
/// <returns></returns>
|
||||
public override decimal GetLeverage(Security security)
|
||||
{
|
||||
if (AccountType == AccountType.Cash || security.IsInternalFeed() || security.Type == SecurityType.Base)
|
||||
{
|
||||
return 1m;
|
||||
}
|
||||
|
||||
if (security.Type == SecurityType.Equity || security.Type == SecurityType.Future || security.Type == SecurityType.Option)
|
||||
{
|
||||
return _maxLeverage;
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Invalid security type: {security.Type}", nameof(security));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the benchmark for this model
|
||||
/// </summary>
|
||||
/// <param name="securities">SecurityService to create the security with if needed</param>
|
||||
/// <returns>The benchmark for this brokerage</returns>
|
||||
public override IBenchmark GetBenchmark(SecurityManager securities)
|
||||
{
|
||||
var symbol = Symbol.Create("NIFTYBEES", SecurityType.Equity, Market.India);
|
||||
return SecurityBenchmark.CreateInstance(securities, symbol);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides Samco fee model
|
||||
/// </summary>
|
||||
/// <param name="security"></param>
|
||||
/// <returns></returns>
|
||||
public override IFeeModel GetFeeModel(Security security)
|
||||
{
|
||||
return new SamcoFeeModel();
|
||||
}
|
||||
|
||||
private static IReadOnlyDictionary<SecurityType, string> GetDefaultMarkets()
|
||||
{
|
||||
var map = DefaultMarketMap.ToDictionary();
|
||||
map[SecurityType.Equity] = Market.India;
|
||||
map[SecurityType.Future] = Market.India;
|
||||
map[SecurityType.Option] = Market.India;
|
||||
return map.ToReadOnlyDictionary();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,7 @@ namespace QuantConnect.Data.Auxiliary
|
||||
{
|
||||
FactorFile factorFile = null;
|
||||
|
||||
var path = Path.Combine(Globals.DataFolder, "equity", market, "factor_files", permtick.ToLowerInvariant() + ".csv");
|
||||
var path = Path.Combine(Globals.CacheDataFolder, "equity", market, "factor_files", permtick.ToLowerInvariant() + ".csv");
|
||||
|
||||
var factorFileStream = _dataProvider.Fetch(path);
|
||||
if (factorFileStream != null)
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace QuantConnect.Data.Auxiliary
|
||||
public class MapFilePrimaryExchangeProvider : IPrimaryExchangeProvider
|
||||
{
|
||||
private readonly IMapFileProvider _mapFileProvider;
|
||||
private readonly ConcurrentDictionary<SecurityIdentifier, PrimaryExchange> _primaryExchangeBySid;
|
||||
private readonly ConcurrentDictionary<SecurityIdentifier, Exchange> _primaryExchangeBySid;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for Primary Exchange Provider from MapFiles
|
||||
@@ -35,7 +35,7 @@ namespace QuantConnect.Data.Auxiliary
|
||||
public MapFilePrimaryExchangeProvider(IMapFileProvider mapFileProvider)
|
||||
{
|
||||
_mapFileProvider = mapFileProvider;
|
||||
_primaryExchangeBySid = new ConcurrentDictionary<SecurityIdentifier, PrimaryExchange>();
|
||||
_primaryExchangeBySid = new ConcurrentDictionary<SecurityIdentifier, Exchange>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -43,9 +43,9 @@ namespace QuantConnect.Data.Auxiliary
|
||||
/// </summary>
|
||||
/// <param name="securityIdentifier">The security identifier to get the primary exchange for</param>
|
||||
/// <returns>Returns the primary exchange or null if not found</returns>
|
||||
public PrimaryExchange GetPrimaryExchange(SecurityIdentifier securityIdentifier)
|
||||
public Exchange GetPrimaryExchange(SecurityIdentifier securityIdentifier)
|
||||
{
|
||||
PrimaryExchange primaryExchange;
|
||||
Exchange primaryExchange;
|
||||
if (!_primaryExchangeBySid.TryGetValue(securityIdentifier, out primaryExchange))
|
||||
{
|
||||
var mapFile = _mapFileProvider.Get(securityIdentifier.Market).ResolveMapFile(securityIdentifier.Symbol, securityIdentifier.Date);
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace QuantConnect.Data.Auxiliary
|
||||
/// <summary>
|
||||
/// Gets the mapped symbol
|
||||
/// </summary>
|
||||
public PrimaryExchange PrimaryExchange { get; }
|
||||
public Exchange PrimaryExchange { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MapFileRow"/> class.
|
||||
@@ -52,7 +52,7 @@ namespace QuantConnect.Data.Auxiliary
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MapFileRow"/> class.
|
||||
/// </summary>
|
||||
public MapFileRow(DateTime date, string mappedSymbol, PrimaryExchange primaryExchange)
|
||||
public MapFileRow(DateTime date, string mappedSymbol, Exchange primaryExchange)
|
||||
{
|
||||
Date = date;
|
||||
MappedSymbol = mappedSymbol.LazyToUpper();
|
||||
@@ -84,7 +84,7 @@ namespace QuantConnect.Data.Auxiliary
|
||||
public static MapFileRow Parse(string line)
|
||||
{
|
||||
var csv = line.Split(',');
|
||||
var primaryExchange = PrimaryExchange.UNKNOWN;
|
||||
var primaryExchange = Exchange.UNKNOWN;
|
||||
if (csv.Length == 3)
|
||||
{
|
||||
primaryExchange = Exchanges.GetPrimaryExchange(Convert.ToChar(csv[2], CultureInfo.InvariantCulture));
|
||||
@@ -166,7 +166,7 @@ namespace QuantConnect.Data.Auxiliary
|
||||
/// </summary>
|
||||
public string ToCsv()
|
||||
{
|
||||
var encodedExchange = PrimaryExchange == PrimaryExchange.UNKNOWN? string.Empty : $",{Convert.ToChar((byte) PrimaryExchange)}";
|
||||
var encodedExchange = PrimaryExchange == Exchange.UNKNOWN? string.Empty : $",{Convert.ToChar((byte) PrimaryExchange)}";
|
||||
return $"{Date.ToStringInvariant(DateFormat.EightCharacter)},{MappedSymbol.ToLowerInvariant()}{encodedExchange}";
|
||||
}
|
||||
|
||||
@@ -176,8 +176,8 @@ namespace QuantConnect.Data.Auxiliary
|
||||
/// <returns>resulting string</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
var mainExchange = PrimaryExchange == PrimaryExchange.UNKNOWN ? string.Empty : $" - {PrimaryExchange.ToString()}";
|
||||
var mainExchange = PrimaryExchange == Exchange.UNKNOWN ? string.Empty : $" - {PrimaryExchange.ToString()}";
|
||||
return Date.ToShortDateString() + ": " + MappedSymbol + mainExchange;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user