diff --git a/04 Research Environment/10 Meta Analysis/05 Live Reconciliation/05 Plot Order Fills.php b/04 Research Environment/10 Meta Analysis/05 Live Reconciliation/05 Plot Order Fills.php index d613a72ce8..b0821343c2 100644 --- a/04 Research Environment/10 Meta Analysis/05 Live Reconciliation/05 Plot Order Fills.php +++ b/04 Research Environment/10 Meta Analysis/05 Live Reconciliation/05 Plot Order Fills.php @@ -1,37 +1,67 @@

Follow these steps to overlay live and OOS backtest order fills on a single marker-only chart per symbol. The chart deliberately omits candlesticks and any price history so the comparison between live and backtest executions is not drowned out by other series.

    -
  1. Read the live and backtest orders. Both endpoints can take a few seconds to load the first time, so retry until the response is non-empty.
  2. +
  3. Read the live and backtest orders. Each call to ReadLiveOrdersread_live_orders and ReadBacktestOrdersread_backtest_orders returns at most 100 orders, so paginate in 100-Id windows until the endpoint returns an empty window. The first window can take a few seconds to load, so retry while it is empty.
  4. -
    List<ApiOrderResponse> ReadOrders(Func<List<ApiOrderResponse>> fetch)
    +        
    List<ApiOrderResponse> ReadAllOrders(Func<int, int, List<ApiOrderResponse>> fetchWindow)
     {
    +    var all = new List<ApiOrderResponse>();
    +    // Retry the first window while the response is empty (may be loading).
    +    List<ApiOrderResponse> first = null;
         for (var attempt = 0; attempt < 10; attempt++)
         {
    -        var result = fetch();
    -        if (result.Any()) return result;
    +        first = fetchWindow(0, 100);
    +        if (first.Any()) break;
             Console.WriteLine($"Orders loading... (attempt {attempt + 1}/10)");
             Thread.Sleep(10000);
         }
    -    throw new Exception("Failed to read orders after 10 attempts");
    +    if (first == null || !first.Any()) return all;
    +    all.AddRange(first);
    +    // Paginate in 100-Id windows until the endpoint returns an empty window.
    +    var start = 100;
    +    while (true)
    +    {
    +        var window = fetchWindow(start, start + 100);
    +        if (!window.Any()) break;
    +        all.AddRange(window);
    +        start += 100;
    +    }
    +    return all;
     }
     
    -var liveOrders = ReadOrders(() => api.ReadLiveOrders(projectId, 0, 100));
    -var backtestOrders = ReadOrders(() => api.ReadBacktestOrders(projectId, backtestId, 0, 100));
    +var liveOrders = ReadAllOrders((s, e) => api.ReadLiveOrders(projectId, s, e)); +var backtestOrders = ReadAllOrders((s, e) => api.ReadBacktestOrders(projectId, backtestId, s, e)); +Console.WriteLine($"Live orders: {liveOrders.Count}, OOS orders: {backtestOrders.Count}");
    from time import sleep
     
    -def read_orders(fetch):
    +def read_all_orders(fetch_window):
    +    orders = []
    +    # Retry the first window while the response is empty (may be loading).
    +    first = []
         for attempt in range(10):
    -        result = fetch()
    -        if result:
    -            return result
    +        first = fetch_window(0, 100)
    +        if first:
    +            break
             print(f"Orders loading... (attempt {attempt + 1}/10)")
             sleep(10)
    -    raise RuntimeError("Failed to read orders after 10 attempts")
    -
    -live_orders = read_orders(lambda: api.read_live_orders(project_id, 0, 100))
    -backtest_orders = read_orders(lambda: api.read_backtest_orders(project_id, backtest_id, 0, 100))
    + if not first: + return orders + orders.extend(first) + # Paginate in 100-Id windows until the endpoint returns an empty window. + start = 100 + while True: + window = fetch_window(start, start + 100) + if not window: + break + orders.extend(window) + start += 100 + return orders + +live_orders = read_all_orders(lambda s, e: api.read_live_orders(project_id, s, e)) +backtest_orders = read_all_orders(lambda s, e: api.read_backtest_orders(project_id, backtest_id, s, e)) +print(f"Live orders: {len(live_orders)}, OOS orders: {len(backtest_orders)}")
    -

    By default, you receive the orders with an Id between 0 and 100. To read more, call the method repeatedly in windows of up to 100 Ids. For more on the order objects returned, see Plot Order Fills in the Live Analysis documentation.

    +

    For more on the order objects returned, see Plot Order Fills in the Live Analysis documentation.

  5. Organize the trade times and prices for each security into a dictionary for both the live and backtest fills.
  6. diff --git a/04 Research Environment/10 Meta Analysis/05 Live Reconciliation/99 Examples.html b/04 Research Environment/10 Meta Analysis/05 Live Reconciliation/99 Examples.html index 930f510653..3839c9a5bf 100644 --- a/04 Research Environment/10 Meta Analysis/05 Live Reconciliation/99 Examples.html +++ b/04 Research Environment/10 Meta Analysis/05 Live Reconciliation/99 Examples.html @@ -59,21 +59,34 @@

    Example 1: Generate an OOS Reconciliation Curve

    // Read the backtest Strategy Equity chart. var backtestEquity = api.ReadBacktestChart(projectId, "Strategy Equity", 0, nowSec, 500, backtestId).Chart; -// Read live and backtest orders for the fill overlay. Both endpoints can take -// a few seconds to load the first time, so retry until the list is non-empty. -List<ApiOrderResponse> ReadOrders(Func<List<ApiOrderResponse>> fetch) +// Read live and backtest orders for the fill overlay. Each call returns at +// most 100 orders, so paginate in 100-Id windows until we get an empty window. +// The first window can take a few seconds to load, so retry while empty. +List<ApiOrderResponse> ReadAllOrders(Func<int, int, List<ApiOrderResponse>> fetchWindow) { + var all = new List<ApiOrderResponse>(); + List<ApiOrderResponse> first = null; for (var attempt = 0; attempt < 10; attempt++) { - var result = fetch(); - if (result.Any()) return result; + first = fetchWindow(0, 100); + if (first.Any()) break; Thread.Sleep(10000); } - throw new Exception("Failed to read orders after 10 attempts"); + if (first == null || !first.Any()) return all; + all.AddRange(first); + var start = 100; + while (true) + { + var window = fetchWindow(start, start + 100); + if (!window.Any()) break; + all.AddRange(window); + start += 100; + } + return all; } -var liveOrders = ReadOrders(() => api.ReadLiveOrders(projectId, 0, 100)); -var backtestOrders = ReadOrders(() => api.ReadBacktestOrders(projectId, backtestId, 0, 100)); +var liveOrders = ReadAllOrders((s, e) => api.ReadLiveOrders(projectId, s, e)); +var backtestOrders = ReadAllOrders((s, e) => api.ReadBacktestOrders(projectId, backtestId, s, e)); Console.WriteLine($"Start: {startDate}, Starting cash: {startingCash}, End: {endDate}"); Console.WriteLine($"Live orders: {liveOrders.Count}, OOS orders: {backtestOrders.Count}"); @@ -235,16 +248,28 @@

    Example 1: Generate an OOS Reconciliation Curve

    (d.buy_fill_prices if is_buy else d.sell_fill_prices).append(order.price) return out -def read_orders(fetch): +def read_all_orders(fetch_window): + orders = [] + first = [] for attempt in range(10): - result = fetch() - if result: - return result + first = fetch_window(0, 100) + if first: + break sleep(10) - raise RuntimeError("Failed to read orders after 10 attempts") + if not first: + return orders + orders.extend(first) + start = 100 + while True: + window = fetch_window(start, start + 100) + if not window: + break + orders.extend(window) + start += 100 + return orders -live_by_symbol = group_by_symbol(read_orders(lambda: api.read_live_orders(project_id, 0, 100))) -backtest_by_symbol = group_by_symbol(read_orders(lambda: api.read_backtest_orders(project_id, backtest_id, 0, 100))) +live_by_symbol = group_by_symbol(read_all_orders(lambda s, e: api.read_live_orders(project_id, s, e))) +backtest_by_symbol = group_by_symbol(read_all_orders(lambda s, e: api.read_backtest_orders(project_id, backtest_id, s, e))) for symbol in set(live_by_symbol) | set(backtest_by_symbol): live = live_by_symbol.get(symbol, OrderData()) diff --git a/09 AI Assistance/03 MCP Server/01 Key Concepts/04 Tools.html b/09 AI Assistance/03 MCP Server/01 Key Concepts/04 Tools.html index 7171c3deb4..20f7b81788 100644 --- a/09 AI Assistance/03 MCP Server/01 Key Concepts/04 Tools.html +++ b/09 AI Assistance/03 MCP Server/01 Key Concepts/04 Tools.html @@ -49,3 +49,39 @@

    Live Trading

  7. stop_live_algorithm - Stop a live algorithm.
  8. liquidate_live_algorithm - Liquidate and stop a live algorithm.
  9. + +

    Research

    +

    The following tools operate on a Jupyter notebook in the QuantConnect Cloud Research environment:

    + + +

    News

    +

    The following tools fetch financial news and blog posts from a curated list of more than 20 sources:

    + + +

    Environment

    + + +

    Notifications

    +

    + The following tools send messages from QuantConnect Cloud to you using the Live Trading Notifications system: +

    +