| Overall Statistics |
|
Total Orders 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Start Equity 100000 End Equity 100000 Net Profit 0% Sharpe Ratio 0 Sortino 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 -4.063 Tracking Error 0.074 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset Portfolio Turnover 0% Drawdown Recovery 0 |
#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.Portfolio.SignalExports;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Risk;
using QuantConnect.Algorithm.Selection;
using QuantConnect.Api;
using QuantConnect.Parameters;
using QuantConnect.Benchmarks;
using QuantConnect.Brokerages;
using QuantConnect.Commands;
using QuantConnect.Configuration;
using QuantConnect.Util;
using QuantConnect.Interfaces;
using QuantConnect.Algorithm;
using QuantConnect.Indicators;
using QuantConnect.Data;
using QuantConnect.Data.Auxiliary;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Custom;
using QuantConnect.Data.Custom.IconicTypes;
using QuantConnect.DataSource;
using QuantConnect.Data.Fundamental;
using QuantConnect.Data.Market;
using QuantConnect.Data.Shortable;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Notifications;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;
using QuantConnect.Orders.Fills;
using QuantConnect.Orders.OptionExercise;
using QuantConnect.Orders.Slippage;
using QuantConnect.Orders.TimeInForces;
using QuantConnect.Python;
using QuantConnect.Scheduling;
using QuantConnect.Securities;
using QuantConnect.Securities.Equity;
using QuantConnect.Securities.Future;
using QuantConnect.Securities.Option;
using QuantConnect.Securities.Positions;
using QuantConnect.Securities.Forex;
using QuantConnect.Securities.Crypto;
using QuantConnect.Securities.CryptoFuture;
using QuantConnect.Securities.IndexOption;
using QuantConnect.Securities.Interfaces;
using QuantConnect.Securities.Volatility;
using QuantConnect.Storage;
using QuantConnect.Statistics;
using Calendar = QuantConnect.Data.Consolidators.Calendar;
using QLNet;
#endregion
namespace QuantConnect
{
public partial class IntelligentBreakoutAlgorithm : QCAlgorithm
{
private HashSet<Symbol> _constituents = new();
private Dictionary<Symbol, UniverseProperties> _universe = new ();
private static Symbol[] _blackList = ["GOOCV VP83T1ZUHROL", "FOXBV X2S9UGTP4UHX"];
public static string S = "signal", U = "universe";
public override void Initialize()
{
SetCash(100000);
SetStartDate(2025, 6, 1);
// Initialization
UniverseSettings.Leverage = 4;
Settings.AutomaticIndicatorWarmUp = true;
UniverseSettings.Resolution = Resolution.Second;
UniverseSettings.Schedule.On(DateRules.MonthStart());
// Request Data
AddUniverse(Universe.ETF("QQQ", Market.USA, UniverseSettings, ETFConstituentsFilter));
AddUniverse(Universe.ETF("SPY", Market.USA, UniverseSettings, ETFConstituentsFilter));
AddUniverse(Universe.ETF("IWM", Market.USA, UniverseSettings, ETFConstituentsFilter));
AddUniverse(Filter);
}
public override void OnSecuritiesChanged(SecurityChanges changes)
{
// foreach(var security in changes.AddedSecurities)
// {
// security[S] = new IntelligentBreakoutSignal(this, security);
// }
// foreach(var security in changes.RemovedSecurities)
// {
// security.Get<IntelligentBreakoutSignal>(S).Dispose();
// }
}
}
}#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.Portfolio.SignalExports;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Risk;
using QuantConnect.Algorithm.Selection;
using QuantConnect.Api;
using QuantConnect.Parameters;
using QuantConnect.Benchmarks;
using QuantConnect.Brokerages;
using QuantConnect.Commands;
using QuantConnect.Configuration;
using QuantConnect.Util;
using QuantConnect.Interfaces;
using QuantConnect.Algorithm;
using QuantConnect.Indicators;
using QuantConnect.Data;
using QuantConnect.Data.Auxiliary;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Custom;
using QuantConnect.Data.Custom.IconicTypes;
using QuantConnect.DataSource;
using QuantConnect.Data.Fundamental;
using QuantConnect.Data.Market;
using QuantConnect.Data.Shortable;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Notifications;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;
using QuantConnect.Orders.Fills;
using QuantConnect.Orders.OptionExercise;
using QuantConnect.Orders.Slippage;
using QuantConnect.Orders.TimeInForces;
using QuantConnect.Python;
using QuantConnect.Scheduling;
using QuantConnect.Securities;
using QuantConnect.Securities.Equity;
using QuantConnect.Securities.Future;
using QuantConnect.Securities.Option;
using QuantConnect.Securities.Positions;
using QuantConnect.Securities.Forex;
using QuantConnect.Securities.Crypto;
using QuantConnect.Securities.CryptoFuture;
using QuantConnect.Securities.IndexOption;
using QuantConnect.Securities.Interfaces;
using QuantConnect.Securities.Volatility;
using QuantConnect.Storage;
using QuantConnect.Statistics;
using Calendar = QuantConnect.Data.Consolidators.Calendar;
using QLNet;
#endregion
namespace QuantConnect
{
class IntelligentBreakoutSignal
{
public decimal Price => _security.Price;
public Symbol Symbol => _security.Symbol;
public bool Triggered => RelativeVolume > 1.0m && _atr > (Price * 0.01m) && Price != 0;
public decimal RelativeVolume;
// Signal settings:
private TradeBar _bar;
private Security _security;
private QCAlgorithm _algorithm;
private AverageTrueRange _atr;
private SimpleMovingAverage _sma;
private IDataConsolidator _consolidator;
// Risk settings:
private int _lookback = 14;
private decimal _stopLossAtrDistance = 0.1m; // 0.1 => 10% of ATR
private decimal _stopLossRiskSize = 0.01m; // 0.01 => Lose 1% of the portfolio
private int _maxPositions = 20;
// Trade settings:
private OrderTicket _entry;
private OrderTicket _exit;
private decimal _stopPrice;
public IntelligentBreakoutSignal(QCAlgorithm algorithm, Security security)
{
_security = security;
_algorithm = algorithm;
_bar = new TradeBar();
_sma = new SimpleMovingAverage(_lookback);
_atr = algorithm.ATR(security.Symbol, _lookback, resolution: Resolution.Daily);
_consolidator = algorithm.Consolidate(security.Symbol, TimeSpan.FromMinutes(5), Range);
}
public void Scan()
{
// Calculate position sizes so that if you fill an order at the high (low) of the first 5-minute bar
// and hit a stop loss based on 10% of the ATR, you only lose x% of portfolio value.
if (_bar.Close > _bar.Open)
{
PlaceTrade(_bar.High, _bar.High - _stopLossAtrDistance * _atr);
}
else if (_bar.Close < _bar.Open)
{
PlaceTrade(_bar.Low, _bar.Low + _stopLossAtrDistance * _atr);
}
}
public void PlaceTrade(decimal entryPrice, decimal stopPrice)
{
var quantity = (int)((_stopLossRiskSize * _algorithm.Portfolio.TotalPortfolioValue / _maxPositions) / (entryPrice - stopPrice));
var quantityLimit = _algorithm.CalculateOrderQuantity(_security.Symbol, 1m/_maxPositions);
quantity = (int)(Math.Min(Math.Abs(quantity), quantityLimit) * Math.Sign(quantity));
if (quantity != 0)
{
_stopPrice = stopPrice;
//_entry = _algorithm.StopMarketOrder(_security.Symbol, quantity, entryPrice, $"Entry");
}
}
public void OnOrderEvent(OrderTicket orderTicket)
{
// When the entry order is hit, place the exit order: Stop loss based on ATR.
// if (orderTicket == EntryTicket)
// {
// _algorithm.StopMarketOrder(_security.Symbol, -EntryTicket.Quantity, StopLossPrice, tag: "ATR Stop");
// }
}
public void Dispose()
{
_algorithm.DeregisterIndicator(_atr);
}
private void Range(TradeBar bar)
{
if (_bar.Time.Date == bar.Time.Date) return;
// Update the asset's indicators and save the day's opening bar.
RelativeVolume = _sma.IsReady && _sma > 0 ? bar.Volume / _sma : 0;
_sma.Update(bar.EndTime, bar.Volume);
_bar = bar;
}
}
}#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.Portfolio.SignalExports;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Risk;
using QuantConnect.Algorithm.Selection;
using QuantConnect.Api;
using QuantConnect.Parameters;
using QuantConnect.Benchmarks;
using QuantConnect.Brokerages;
using QuantConnect.Commands;
using QuantConnect.Configuration;
using QuantConnect.Util;
using QuantConnect.Interfaces;
using QuantConnect.Algorithm;
using QuantConnect.Indicators;
using QuantConnect.Data;
using QuantConnect.Data.Auxiliary;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Custom;
using QuantConnect.Data.Custom.IconicTypes;
using QuantConnect.DataSource;
using QuantConnect.Data.Fundamental;
using QuantConnect.Data.Market;
using QuantConnect.Data.Shortable;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Notifications;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;
using QuantConnect.Orders.Fills;
using QuantConnect.Orders.OptionExercise;
using QuantConnect.Orders.Slippage;
using QuantConnect.Orders.TimeInForces;
using QuantConnect.Python;
using QuantConnect.Scheduling;
using QuantConnect.Securities;
using QuantConnect.Securities.Equity;
using QuantConnect.Securities.Future;
using QuantConnect.Securities.Option;
using QuantConnect.Securities.Positions;
using QuantConnect.Securities.Forex;
using QuantConnect.Securities.Crypto;
using QuantConnect.Securities.CryptoFuture;
using QuantConnect.Securities.IndexOption;
using QuantConnect.Securities.Interfaces;
using QuantConnect.Securities.Volatility;
using QuantConnect.Storage;
using QuantConnect.Statistics;
using Calendar = QuantConnect.Data.Consolidators.Calendar;
using QLNet;
#endregion
namespace QuantConnect
{
public partial class IntelligentBreakoutAlgorithm : QCAlgorithm
{
IEnumerable<Symbol> ETFConstituentsFilter(IEnumerable <ETFConstituentUniverse> constituents)
{
_constituents.UnionWith(constituents.Select(x => x.Symbol));
return Universe.Unchanged;
}
IEnumerable<Symbol> Filter(IEnumerable<Fundamental> fundamental)
{
var selected = from f in fundamental
where _constituents.Contains(f.Symbol) &&
!_blackList.Contains(f.Symbol) &&
f.Price > 100m select f;
foreach(var f in selected)
{
if (!_universe.TryGetValue(f.Symbol, out UniverseProperties assetProperties))
{
assetProperties = new UniverseProperties(this, f.Symbol);
_universe[f.Symbol] = assetProperties;
}
assetProperties.Update(f.Time, f.Price, (decimal)f.DollarVolume);
}
var ranked = (from f in _universe.Values
where f.RelativeVolatility > 0.04m
orderby f.DollarVolume descending
select f.Symbol).Take(20).ToList();
Log($"New assets selected {Time} | {string.Join(',', ranked)}");
return Universe.Unchanged;
}
// public override void OnData(Slice slice)
// {
// if (IsWarmingUp || (Time.Hour == 9 && (Time.Minute <= 35 || Time.Minute > 59))) return;
// // Select top 20 stocks in play with the greatest relative volume.
// var filtered = _signals.Values.Where(s => s.Triggered)
// .OrderByDescending(s => s.RelativeVolume).Take(30);
// // Look for trade entries.
// foreach (var signal in filtered)
// {
// signal.Scan();
// }
// }
//Schedule.On(DateRules.EveryDay(qqq), TimeRules.BeforeMarketClose(qqq, 1), () => Liquidate());
class UniverseProperties
{
public Symbol Symbol;
public decimal DollarVolume;
public decimal RelativeVolatility = 0;
public decimal AbsoluteDeviationsFromMean = 0;
private StandardDeviation _std;
private SimpleMovingAverage _mean;
private RelativeStrengthIndex _rsi;
public UniverseProperties(QCAlgorithm algorithm, Symbol symbol)
{
Symbol = symbol;
var history = algorithm.History<TradeBar>(symbol, 15, Resolution.Daily);
_std = new StandardDeviation(14);
_mean = new SimpleMovingAverage(14);
_rsi = new RelativeStrengthIndex(14);
foreach(var bar in history)
{
Update(bar.EndTime, bar.Close, bar.Volume);
}
}
public void Update(DateTime time, decimal price, decimal dollarVolume)
{
DollarVolume = dollarVolume;
_std.Update(time, price);
_mean.Update(time, price);
_rsi.Update(time, price);
if (_std.IsReady)
{
AbsoluteDeviationsFromMean = Math.Abs((price - _mean)/_std);
RelativeVolatility = _std/_mean;
}
}
}
}
}