forked from QuantConnect/Lean
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request QuantConnect#3718 from AlexCatarino/feature-3672-c…
…onfidence-weighted-pcm Implements ConfidenceWeightedPortfolioConstructionModel
- Loading branch information
Showing
11 changed files
with
730 additions
and
10 deletions.
There are no files selected for viewing
111 changes: 111 additions & 0 deletions
111
Algorithm.CSharp/ConfidenceWeightedFrameworkAlgorithm.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 System; | ||
using System.Collections.Generic; | ||
using QuantConnect.Algorithm.Framework.Alphas; | ||
using QuantConnect.Algorithm.Framework.Execution; | ||
using QuantConnect.Algorithm.Framework.Portfolio; | ||
using QuantConnect.Algorithm.Framework.Selection; | ||
using QuantConnect.Interfaces; | ||
|
||
namespace QuantConnect.Algorithm.CSharp | ||
{ | ||
/// <summary> | ||
/// Test algorithm using <see cref="ConfidenceWeightedPortfolioConstructionModel"/> and <see cref="ConstantAlphaModel"/> | ||
/// generating a constant <see cref="Insight"/> with a 0.25 confidence | ||
/// </summary> | ||
public class ConfidenceWeightedFrameworkAlgorithm : 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() | ||
{ | ||
// Set requested data resolution | ||
UniverseSettings.Resolution = Resolution.Minute; | ||
|
||
SetStartDate(2013, 10, 07); //Set Start Date | ||
SetEndDate(2013, 10, 11); //Set End Date | ||
SetCash(100000); //Set Strategy Cash | ||
|
||
// set algorithm framework models | ||
SetUniverseSelection(new ManualUniverseSelectionModel(QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA))); | ||
SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, 0.25)); | ||
SetPortfolioConstruction(new ConfidenceWeightedPortfolioConstructionModel()); | ||
SetExecution(new ImmediateExecutionModel()); | ||
} | ||
|
||
public override void OnEndOfAlgorithm() | ||
{ | ||
if (// holdings value should be 0.25 - to avoid price fluctuation issue we compare with 0.28 and 0.23 | ||
Portfolio.TotalHoldingsValue > Portfolio.TotalPortfolioValue * 0.28m | ||
|| | ||
Portfolio.TotalHoldingsValue < Portfolio.TotalPortfolioValue * 0.23m) | ||
{ | ||
throw new Exception($"Unexpected Total Holdings Value: {Portfolio.TotalHoldingsValue}"); | ||
} | ||
} | ||
|
||
/// <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", "6"}, | ||
{"Average Win", "0.00%"}, | ||
{"Average Loss", "0.00%"}, | ||
{"Compounding Annual Return", "34.982%"}, | ||
{"Drawdown", "0.600%"}, | ||
{"Expectancy", "-0.495"}, | ||
{"Net Profit", "0.412%"}, | ||
{"Sharpe Ratio", "4.016"}, | ||
{"Loss Rate", "67%"}, | ||
{"Win Rate", "33%"}, | ||
{"Profit-Loss Ratio", "0.52"}, | ||
{"Alpha", "0.146"}, | ||
{"Beta", "0.077"}, | ||
{"Annual Standard Deviation", "0.043"}, | ||
{"Annual Variance", "0.002"}, | ||
{"Information Ratio", "-1.027"}, | ||
{"Tracking Error", "0.179"}, | ||
{"Treynor Ratio", "2.239"}, | ||
{"Total Fees", "$6.00"}, | ||
{"Total Insights Generated", "100"}, | ||
{"Total Insights Closed", "99"}, | ||
{"Total Insights Analysis Completed", "99"}, | ||
{"Long Insight Count", "100"}, | ||
{"Short Insight Count", "0"}, | ||
{"Long/Short Ratio", "100%"}, | ||
{"Estimated Monthly Alpha Value", "$148197.8440"}, | ||
{"Total Accumulated Estimated Alpha Value", "$25522.9620"}, | ||
{"Mean Population Estimated Insight Value", "$257.8077"}, | ||
{"Mean Population Direction", "54.5455%"}, | ||
{"Mean Population Magnitude", "54.5455%"}, | ||
{"Rolling Averaged Population Direction", "59.8056%"}, | ||
{"Rolling Averaged Population Magnitude", "59.8056%"} | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
Algorithm.Framework/Portfolio/ConfidenceWeightedPortfolioConstructionModel.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* 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.Algorithm.Framework.Alphas; | ||
|
||
namespace QuantConnect.Algorithm.Framework.Portfolio | ||
{ | ||
/// <summary> | ||
/// Provides an implementation of <see cref="IPortfolioConstructionModel"/> that generates percent targets based on the | ||
/// <see cref="Insight.Confidence"/>. The target percent holdings of each Symbol is given by the <see cref="Insight.Confidence"/> | ||
/// from the last active <see cref="Insight"/> for that symbol. | ||
/// For insights of direction <see cref="InsightDirection.Up"/>, long targets are returned and for insights of direction | ||
/// <see cref="InsightDirection.Down"/>, short targets are returned. | ||
/// If the sum of all the last active <see cref="Insight"/> per symbol is bigger than 1, it will factor down each target | ||
/// percent holdings proportionally so the sum is 1. | ||
/// It will ignore <see cref="Insight"/> that have no <see cref="Insight.Confidence"/> value. | ||
/// </summary> | ||
public class ConfidenceWeightedPortfolioConstructionModel : InsightWeightingPortfolioConstructionModel | ||
{ | ||
/// <summary> | ||
/// Initialize a new instance of <see cref="ConfidenceWeightedPortfolioConstructionModel"/> | ||
/// </summary> | ||
/// <param name="resolution">Rebalancing frequency</param> | ||
public ConfidenceWeightedPortfolioConstructionModel(Resolution resolution = Resolution.Daily) | ||
: base(resolution) | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Method that will determine if the portfolio construction model should create a | ||
/// target for this insight | ||
/// </summary> | ||
/// <param name="insight">The insight to create a target for</param> | ||
/// <returns>True if the portfolio should create a target for the insight</returns> | ||
public override bool ShouldCreateTargetForInsight(Insight insight) | ||
{ | ||
return insight.Confidence.HasValue; | ||
} | ||
|
||
/// <summary> | ||
/// Method that will determine which member will be used to compute the weights and gets its value | ||
/// </summary> | ||
/// <param name="insight">The insight to create a target for</param> | ||
/// <returns>The value of the selected insight member</returns> | ||
protected override double GetValue(Insight insight) => insight.Confidence ?? 0; | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
Algorithm.Framework/Portfolio/ConfidenceWeightedPortfolioConstructionModel.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# 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 clr import AddReference | ||
AddReference("QuantConnect.Common") | ||
AddReference("QuantConnect.Algorithm.Framework") | ||
|
||
from QuantConnect import Resolution | ||
from InsightWeightingPortfolioConstructionModel import InsightWeightingPortfolioConstructionModel | ||
|
||
class ConfidenceWeightedPortfolioConstructionModel(InsightWeightingPortfolioConstructionModel): | ||
'''Provides an implementation of IPortfolioConstructionModel that generates percent targets based on the | ||
Insight.Confidence. The target percent holdings of each Symbol is given by the Insight.Confidence from the last | ||
active Insight for that symbol. | ||
For insights of direction InsightDirection.Up, long targets are returned and for insights of direction | ||
InsightDirection.Down, short targets are returned. | ||
If the sum of all the last active Insight per symbol is bigger than 1, it will factor down each target | ||
percent holdings proportionally so the sum is 1. | ||
It will ignore Insight that have no Insight.Confidence value.''' | ||
|
||
def __init__(self, resolution = Resolution.Daily): | ||
'''Initialize a new instance of ConfidenceWeightedPortfolioConstructionModel | ||
Args: | ||
resolution: Rebalancing frequency''' | ||
super().__init__(resolution) | ||
|
||
def ShouldCreateTargetForInsight(self, insight): | ||
'''Method that will determine if the portfolio construction model should create a | ||
target for this insight | ||
Args: | ||
insight: The insight to create a target for''' | ||
# Ignore insights that don't have Confidence value | ||
return insight.Confidence is not None | ||
|
||
def GetValue(self, insight): | ||
'''Method that will determine which member will be used to compute the weights and gets its value | ||
Args: | ||
insight: The insight to create a target for | ||
Returns: | ||
The value of the selected insight member''' | ||
return insight.Confidence |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# 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 clr import AddReference | ||
AddReference("System") | ||
AddReference("QuantConnect.Algorithm") | ||
AddReference("QuantConnect.Algorithm.Framework") | ||
AddReference("QuantConnect.Common") | ||
|
||
from System import * | ||
from QuantConnect import * | ||
from QuantConnect.Orders import * | ||
from QuantConnect.Algorithm import * | ||
from QuantConnect.Algorithm.Framework import * | ||
from QuantConnect.Algorithm.Framework.Alphas import * | ||
from QuantConnect.Algorithm.Framework.Execution import * | ||
from QuantConnect.Algorithm.Framework.Portfolio import * | ||
from QuantConnect.Algorithm.Framework.Risk import * | ||
from QuantConnect.Algorithm.Framework.Selection import * | ||
from datetime import timedelta | ||
|
||
### <summary> | ||
### Test algorithm using 'ConfidenceWeightedPortfolioConstructionModel' and 'ConstantAlphaModel' | ||
### generating a constant 'Insight' with a 0.25 confidence | ||
### </summary> | ||
class ConfidenceWeightedFrameworkAlgorithm(QCAlgorithm): | ||
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.''' | ||
|
||
# Set requested data resolution | ||
self.UniverseSettings.Resolution = Resolution.Minute | ||
|
||
self.SetStartDate(2013,10,7) #Set Start Date | ||
self.SetEndDate(2013,10,11) #Set End Date | ||
self.SetCash(100000) #Set Strategy Cash | ||
|
||
symbols = [ Symbol.Create("SPY", SecurityType.Equity, Market.USA) ] | ||
|
||
# set algorithm framework models | ||
self.SetUniverseSelection(ManualUniverseSelectionModel(symbols)) | ||
self.SetAlpha(ConstantAlphaModel(InsightType.Price, InsightDirection.Up, timedelta(minutes = 20), 0.025, 0.25)) | ||
self.SetPortfolioConstruction(ConfidenceWeightedPortfolioConstructionModel()) | ||
self.SetExecution(ImmediateExecutionModel()) | ||
|
||
def OnEndOfAlgorithm(self): | ||
# holdings value should be 0.25 - to avoid price fluctuation issue we compare with 0.28 and 0.23 | ||
if (self.Portfolio.TotalHoldingsValue > self.Portfolio.TotalPortfolioValue * 0.28 | ||
or self.Portfolio.TotalHoldingsValue < self.Portfolio.TotalPortfolioValue * 0.23): | ||
raise ValueError("Unexpected Total Holdings Value: " + str(self.Portfolio.TotalHoldingsValue)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.