| Overall Statistics |
|
Total Trades 366 Average Win 1.55% Average Loss -1.49% Compounding Annual Return 16.111% Drawdown 27.000% Expectancy 0.307 Net Profit 139.193% Sharpe Ratio 0.697 Probabilistic Sharpe Ratio 16.184% Loss Rate 36% Win Rate 64% Profit-Loss Ratio 1.04 Alpha 0.05 Beta 0.822 Annual Standard Deviation 0.183 Annual Variance 0.033 Information Ratio 0.266 Tracking Error 0.127 Treynor Ratio 0.155 Total Fees $1382.59 Estimated Strategy Capacity $6000000.00 Lowest Capacity Asset IYE RVLEALAHHC2T |
#region imports
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Drawing;
using QuantConnect;
using QuantConnect.Algorithm.Framework;
using QuantConnect.Algorithm.Framework.Selection;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Risk;
using QuantConnect.Parameters;
using QuantConnect.Benchmarks;
using QuantConnect.Brokerages;
using QuantConnect.Util;
using QuantConnect.Interfaces;
using QuantConnect.Algorithm;
using QuantConnect.Indicators;
using QuantConnect.Data;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Custom;
using QuantConnect.DataSource;
using QuantConnect.Data.Fundamental;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Notifications;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;
using QuantConnect.Orders.Fills;
using QuantConnect.Orders.Slippage;
using QuantConnect.Scheduling;
using QuantConnect.Securities;
using QuantConnect.Securities.Equity;
using QuantConnect.Securities.Future;
using QuantConnect.Securities.Option;
using QuantConnect.Securities.Forex;
using QuantConnect.Securities.Crypto;
using QuantConnect.Securities.Interfaces;
using QuantConnect.Storage;
using QuantConnect.Data.Custom.AlphaStreams;
using QCAlgorithmFramework = QuantConnect.Algorithm.QCAlgorithm;
using QCAlgorithmFrameworkBridge = QuantConnect.Algorithm.QCAlgorithm;
#endregion
namespace QuantConnect.Algorithm.CSharp
{
public class WellDressedVioletChinchilla : QCAlgorithm
{
private List<BrainSentimentIndicatorUniverse> _brainUniverseData;
private Dictionary<Symbol, IEnumerable<ETFConstituentData>> _etfConstituentsDataBySymbol = new();
private Dictionary<Symbol, decimal?> _scoreBySector = new();
private bool _rebalance = false;
private int _numEtfs;
private double _pctConstituents;
private Dictionary<DateTime, decimal> _portfolioValues = new();
public override void Initialize()
{
SetStartDate(2017, 1, 1);
SetEndDate(2022, 11, 1);
SetCash(100000);
Settings.FreePortfolioValuePercentage = 0.025m;
_numEtfs = GetParameter("numEtfs", 3);
_pctConstituents = GetParameter("pctConstituents", 0.5);
AddUniverse<BrainSentimentIndicatorUniverse>(
"BrainSentimentIndicatorUniverse", Resolution.Daily,
altCoarse =>
{
_brainUniverseData = altCoarse.ToList();
return Enumerable.Empty<Symbol>();
});
// Sector ETFs from https://www.cnbc.com/sector-etfs/
var tickers = new[]
{
"XLE", // Energy Select Sector SPDR Fund
"XLF", // Financial Select Sector SPDR Fund
"XLU", // Utilities Select Sector SPDR Fund
"XLI", // Industrial Select Sector SPDR Fund
"GDX", // VanEck Gold Miners ETF
"XLK", // Technology Select Sector SPDR Fund
"XLV", // Health Care Select Sector SPDR Fund
"XLY", // Consumer Discretionary Select Sector SPDR Fund
"XLP", // Consumer Staples Select Sector SPDR Fund
"XLB", // Materials Select Sector SPDR Fund
"XOP", // Spdr S&P Oil & Gas Exploration & Production Etf
"IYR", // iShares U.S. Real Estate ETF
"XHB", // Spdr S&P Homebuilders Etf
"ITB", // iShares U.S. Home Construction ETF
"VNQ", // Vanguard Real Estate Index Fund ETF Shares
"GDXJ",// VanEck Junior Gold Miners ETF
"IYE", // iShares U.S. Energy ETF
"OIH", // VanEck Oil Services ETF
"XME", // SPDR S&P Metals & Mining ETF
"XRT", // Spdr S&P Retail Etf
"SMH", // VanEck Semiconductor ETF
"IBB", // iShares Biotechnology ETF
"KBE", // SPDR S&P Bank ETF
"KRE", // SPDR S&P Regional Banking ETF
"XTL" // SPDR S&P Telecom ETF
};
foreach (var ticker in tickers)
{
var etfSymbol = AddEquity(ticker, Resolution.Daily).Symbol;
AddUniverse(Universe.ETF(etfSymbol, Market.USA, UniverseSettings,
constituents =>
{
_etfConstituentsDataBySymbol[etfSymbol] = constituents;
return Enumerable.Empty<Symbol>();
})
);
}
// Schedule the rebalance
Schedule.On(DateRules.MonthStart(GetParameter("rebalance-day", 0)),
TimeRules.Midnight,
() =>
{
_rebalance = true;
});
}
public override void OnData(Slice data)
{
// Record net portfolio value
_portfolioValues[Time] = Portfolio.TotalPortfolioValue;
// Rebalance?
if (!_rebalance)
{
return;
}
_rebalance = false;
// Calculate sector sentiment
foreach (var kvp in _etfConstituentsDataBySymbol)
{
// Select constituents with largest weight
var etfSymbol = kvp.Key;
var constituentsData = kvp.Value;
var symbols = constituentsData
.OrderByDescending(x => x.Weight)
.Take((int)(_pctConstituents * (double)constituentsData.Count()))
.Select(x => x.Symbol);
// Calculate average sentiment of sector subset
_scoreBySector[etfSymbol] = _brainUniverseData
.Where(brainSentiment => symbols.Contains(brainSentiment.Symbol))
.Select(brainSentiment => brainSentiment.Sentiment30Days)
.Average();
}
// Select target ETFs
var targetSymbols = _scoreBySector.OrderByDescending(x => x.Value).Take(_numEtfs).Select(kvp => kvp.Key);;
// Liquidate ETFs that are no longer targeted
SetHoldings(Portfolio.Where(kvp => kvp.Value.Invested && !targetSymbols.Contains(kvp.Key)).Select(kvp => new PortfolioTarget(kvp.Key, 0)).ToList());
// Rebalance targeted ETFs
var weight = 1.0m / _numEtfs;
SetHoldings(targetSymbols.Select(symbol => new PortfolioTarget(symbol, weight)).ToList());
}
public override void OnEndOfAlgorithm()
{
// Save daily portfolio values to ObjectStore
ObjectStore.SaveJson<Dictionary<DateTime, decimal>>($"{ProjectId}/portfolioValues", _portfolioValues);
}
}
}