| Overall Statistics |
|
Total Orders 29 Average Win 0% Average Loss 0% Compounding Annual Return 429.561% Drawdown 10.700% Expectancy 0 Start Equity 1000000 End Equity 1746019.22 Net Profit 74.602% Sharpe Ratio 5.499 Sortino Ratio 8.861 Probabilistic Sharpe Ratio 90.900% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 2.312 Beta 3.028 Annual Standard Deviation 0.448 Annual Variance 0.201 Information Ratio 6.366 Tracking Error 0.379 Treynor Ratio 0.814 Total Fees $72.19 Estimated Strategy Capacity $1300000000.00 Lowest Capacity Asset TSLA UNU3P8Y3WFAD Portfolio Turnover 1.68% Drawdown Recovery 14 |
# 2025-11-22 07:40:22.963 | CodeBlock(path='./03 Writing Algorithms/34 Algorithm Framework/06 Execution/01 Key Concepts/99 Examples.html', div=1, pre=0, language=csharp, url='quantconnect.com/docs/v2/writing-algorithms/algorithm-framework/execution/key-concepts#99-Examples')
# 2025-11-22 07:40:22.963 | -> Backtest failed. Error: Failed queries: ['Insufficient buying power to complete orders', '']
# 2025-11-22 07:40:22.963 |
# 2025-11-22 08:57:12.452 | CodeBlock(path='./03 Writing Algorithms/34 Algorithm Framework/06 Execution/01 Key Concepts/99 Examples.html', div=1, pre=1, language=python, url='quantconnect.com/docs/v2/writing-algorithms/algorithm-framework/execution/key-concepts#99-Examples')
# 2025-11-22 08:57:12.453 | -> Backtest failed. Error: Failed queries: ['Insufficient buying power to complete orders', '']
# 2025-11-22 07:40:22.963 | CodeBlock(path='./03 Writing Algorithms/34 Algorithm Framework/06 Execution/01 Key Concepts/99 Examples.html', div=1, pre=0, language=csharp, url='quantconnect.com/docs/v2/writing-algorithms/algorithm-framework/execution/key-concepts#99-Examples')
# 2025-11-22 07:40:22.963 | -> Backtest failed. Error: Failed queries: ['Insufficient buying power to complete orders', '']
# 2025-11-22 07:40:22.963 |
# 2025-11-22 08:57:12.452 | CodeBlock(path='./03 Writing Algorithms/34 Algorithm Framework/06 Execution/01 Key Concepts/99 Examples.html', div=1, pre=1, language=python, url='quantconnect.com/docs/v2/writing-algorithms/algorithm-framework/execution/key-concepts#99-Examples')
# 2025-11-22 08:57:12.453 | -> Backtest failed. Error: Failed queries: ['Insufficient buying power to complete orders', '']
# region imports
from AlgorithmImports import *
# endregion
class FrameworkExecutionModelAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
self.set_cash(1000000)
self.universe_settings.resolution = Resolution.DAILY
# Add a universe of the most liquid stocks since their trend is more capital-supported.
self.add_universe(self.universe.top(2))
# Emit insights all for selected stocks.
self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(7)))
# Equal weighting on each insight is needed to dissipate capital risk evenly.
self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
# To place bracket orders besides basic orders as well.
self.set_execution(StopLossExecutionModel(0.05))
class StopLossExecutionModel(ExecutionModel):
def __init__(self, stop_loss: float = 0.05) -> None:
self.targets_collection = PortfolioTargetCollection()
self.stop_loss = stop_loss
self.stop_loss_tickets = {}
# Track market order tickets waiting for fill to set stop-loss
self.pending_stop_loss = {}
def execute(self, algorithm: QCAlgorithm, targets: List[IPortfolioTarget]) -> None:
self.targets_collection.add_range(targets)
if not self.targets_collection.is_empty:
for target in self.targets_collection.order_by_margin_impact(algorithm):
security = algorithm.securities[target.symbol]
quantity = target.quantity - security.holdings.quantity
if quantity == 0: continue
above_minimum_portfolio = BuyingPowerModelExtensions.above_minimum_order_margin_portfolio_percentage(
security.buying_power_model,
security,
quantity,
algorithm.portfolio,
algorithm.settings.minimum_order_margin_portfolio_percentage)
if above_minimum_portfolio:
# Cancel existing stop-loss orders
if target.symbol in self.stop_loss_tickets:
for ticket in self.stop_loss_tickets[target.symbol]:
if ticket.status == OrderStatus.SUBMITTED or ticket.status == OrderStatus.PARTIALLY_FILLED:
ticket.cancel()
self.stop_loss_tickets[target.symbol] = []
# Place market order and track it for stop-loss placement
if quantity > 0:
market_ticket = algorithm.market_order(security.symbol, quantity)
self.pending_stop_loss[market_ticket.order_id] = (target.symbol, quantity)
elif not PortfolioTarget.minimum_order_margin_percentage_warning_sent:
PortfolioTarget.minimum_order_margin_percentage_warning_sent = False
self.targets_collection.clear_fulfilled(algorithm)
def on_order_event(self, algorithm: QCAlgorithm, order_event: OrderEvent) -> None:
if order_event.status == OrderStatus.FILLED:
# Check if this is a market order we need to set a stop-loss for
if order_event.order_id in self.pending_stop_loss:
symbol, quantity = self.pending_stop_loss.pop(order_event.order_id)
# Use the actual fill price to calculate stop-loss
stop_loss_price = order_event.fill_price * (1 - self.stop_loss)
ticket = algorithm.stop_market_order(symbol, -quantity, stop_loss_price)
if symbol not in self.stop_loss_tickets:
self.stop_loss_tickets[symbol] = []
self.stop_loss_tickets[symbol].append(ticket)
# Handle stop-loss fills
elif order_event.ticket.order_type == OrderType.STOP_MARKET:
algorithm.insights.cancel([order_event.symbol])
if order_event.symbol in self.stop_loss_tickets:
self.stop_loss_tickets[order_event.symbol] = [
t for t in self.stop_loss_tickets[order_event.symbol]
if t.order_id != order_event.order_id
]