| Overall Statistics |
|
Total Trades 392 Average Win 1.56% Average Loss -1.94% Compounding Annual Return 7.210% Drawdown 43.800% Expectancy 0.121 Net Profit 50.145% Sharpe Ratio 0.336 Probabilistic Sharpe Ratio 2.424% Loss Rate 38% Win Rate 62% Profit-Loss Ratio 0.80 Alpha -0.005 Beta 0.879 Annual Standard Deviation 0.23 Annual Variance 0.053 Information Ratio -0.091 Tracking Error 0.18 Treynor Ratio 0.088 Total Fees $1194.06 Estimated Strategy Capacity $5700000.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 Dictionary<Symbol, MomentumPercent> _momentumBySymbol = new();
private bool _rebalance = false;
private Dictionary<DateTime, decimal> _portfolioValues = new();
private int _numEtfs = 3;
public override void Initialize()
{
SetStartDate(2017, 1, 1);
SetEndDate(2022, 11, 1);
SetCash(100000);
// 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 symbol = AddEquity(ticker, Resolution.Daily).Symbol;
var momentum = MOMP(symbol, 22);
WarmUpIndicator(symbol, momentum);
_momentumBySymbol[symbol] = momentum;
}
// 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;
// Select target ETFs
var targetSymbols = _momentumBySymbol.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);
}
}
}