Skip to content

Commit a565dfa

Browse files
authored
Wait for fresh data before filling market orders on stale data (#9563)
* Wait for first session bar before filling equity market orders at open EquityFillModel.MarketFill could fill a market order placed right after market open using data from the previous trading date, because the first bar of the current session has not been emitted yet. ShouldWaitForFreshData only covered hour/daily resolutions, so minute/second orders filled on stale prices. Add IsWithinFirstResolutionSpanAfterMarketOpen: when the order time is within the lowest subscribed resolution span after the open and the price is stale, wait for the first bar instead of filling on the previous date's price. * Share opening-bar stale-fill wait across fill models Move IsWithinFirstResolutionSpanAfterMarketOpen to the base FillModel and add a ShouldWaitForFreshDataOnStale sibling helper that combines it with the existing coarse-resolution ShouldWaitForFreshData check. The base FillModel, FutureFillModel and EquityFillModel market fills now share this single wait decision at their stale-data guards. ShouldWaitForFreshData is intentionally left untouched at its GetMarketFillPrice call site, which uses it to choose the bar open vs current price and is not gated by staleness, so fill prices for finer resolutions are unchanged. The opening-bar helper is guarded against always-open markets, which have no session open to wait for. * Add regression algorithm for stale fill at market open Reproduces the opening-bar stale fill issue: a market order placed one second after the open while subscribed to minute resolution. Without the fix the order fills on the previous trading date's stale price; the algorithm asserts in OnOrderEvent that a fill never happens within the first minute after the open, so it errors without the fix and passes with it. Uses SPY minute data over 2013-10-07 to 2013-10-11, which is available in the repository Data folder. * Add unit tests for stale fill wait at market open Cover the opening-bar stale fill scenario directly at the fill model level: a market order placed within the first bar after the session open, while only the previous session's stale bar is available, must wait instead of filling on the stale price, and fills once the first session bar arrives. EquityFillModel also asserts the boundary (orders past the first bar still fill on stale data), and FutureFillModel covers the shared base helper from the future path. * Generalize stale market-order fill wait to any time of day Replace the market-open-specific wait with a generic check: a market order that would be filled on stale data waits for fresh data when the latest available data is more than one subscribed resolution bar behind the current time. This no longer considers the market open explicitly; it covers the opening bar (the first session bar has not been emitted yet) and any intraday data gap larger than the resolution. ShouldWaitForFreshDataOnStale now takes the latest data end time and the current time instead of the order time, and is shared by FillModel, FutureFillModel and EquityFillModel. Coarse resolutions (hour/daily) still always wait; tick never waits. Internal configurations are included when sizing the resolution bar. EquityFillModel's best-effort price helpers now report the stale data end time so the gap can be measured. Tests: EquityFillModelTests and FutureFillModelTests cover the market-open and mid-session stale cases (wait then fill on fresh data) plus the within-one-bar boundary (fill on stale). The regression algorithm is generalized to assert no fill happens on data staler than the resolution, with orders at the open and mid-session. Pre-existing plumbing/data-selection tests that used degenerate timestamps were given fresh timestamps so they still exercise their original intent. * Add sample data and adjust regression algorithms for stale-fill wait Add minute/daily sample data so market orders that now wait for fresh data can fill (ES futures gap days, TWX/GOOG equities and options, SPXW weeklies, GC futures/options copy for 2020-01-06). Adjust a few regression algorithms to the deferred-fill behavior: cap orders in the extended-market continuous future test, ignore daily-resolution SPY in the automatic-seed data checks, and refresh OptionAssignmentStatistics expected constants. * Update regression expected statistics for stale-fill wait Regenerate ExpectedStatistics, DataPoints and AlgorithmHistoryDataPoints for the regression algorithms affected by the wait-for-fresh-data fill change and the added sample data: futures/options fill-timing shifts, ES data-point count increases, and GOOG 2015-12-28 outcome changes. * Trim SPXW sample data to expiries within filter window The two SPXW algorithms filter with Expiration(0,7), so contracts expiring more than a week out are never subscribed. Drop those far-dated expiries from the 2021-01-06/08 minute files (760KB->108KB and 776KB->108KB on the quote files). Fills, DataPoints and statistics are unchanged; both regression tests still pass. * Trim ES minute and GOOG option sample data to order-fill minimum The ES minute gap-day files source no order fills (daily-resolution algos fill from es_daily); keep only the front contract used for execution and drop the unused back-month contracts. Trim the GOOG 2015-12-28 option file (no fill depends on it) to the morning chain window. Regenerate the back-month futures statistics affected by the dropped back-month bars. Full CSharp regression suite passes (722/722). * Use SMA gap threshold in BasicTemplateContinuousFuture for C#/Python parity At a fast/slow SMA cross the two averages can coincide to within rounding noise, where the C# (decimal) and Python (double) comparisons disagree, producing different orders between languages. Require a minimum gap before acting on a cross so both languages stay in lockstep, and update the shared expected statistics accordingly. * Mirror order cap in Python algorithm and update future history counts Apply the same pre-2013-11-12/3-order cap to the Python BasicTemplateContinuousFutureWithExtendedMarket algorithm for C#/Python parity, and update the QuantBook future-history expected counts to reflect the added ES sample data. * Use SMA gap threshold in BasicTemplateContinuousFutureWithExtendedMarket for C#/Python parity This algorithm had the same fast/slow SMA cross divergence already fixed in BasicTemplateContinuousFutureAlgorithm (ad8fc33): at the 2013-10-29 cross the two averages coincide to within rounding noise (C# decimal diff -1e-25, Python double diff exactly 0.0), so the raw `_fast > _slow` / `_fast < _slow` comparisons disagree between languages. C# fired a liquidate+rebuild that Python skipped, producing 5 orders in C# vs 3 in Python. Require a minimum 0.001 gap before acting on a cross so both languages stay in lockstep, and regenerate the shared expected statistics (Total Orders 5 -> 3). * Document SMA cross threshold as a C#/Python parity workaround Add a short note before the fast/slow SMA comparisons in both continuous-future template algorithms clarifying that the minimum-gap threshold exists only so the C# and Python versions take the exact same trades on the limited sample data in the repository, where decimal vs double rounding can disagree at a cross. * Fetch subscription configs once per equity market fill MarketFill resolved the subscription configs twice per fill: once via the best-effort price helpers (GetSubscribedTypes) and again via ShouldWaitForFreshDataOnStale. Fetch them once and thread them through both paths via optional parameters, leaving existing callers unchanged. * Measure stale-fill wait against order submission time ShouldWaitForFreshDataOnStale compared the latest data end time against the security current time. Compare against the order submission time instead so the decision to wait for fresh data reflects how stale the data is relative to when the order was placed. Realign the stale-price warning fill test accordingly. * Fix stale market data in SendingNewOrderFromOnOrderEvent test The market price tick was timestamped a day before the order submission time, so under the order-time staleness check the market orders waited for fresh data instead of filling. Use a reference time with the tick one minute before the order so the data is fresh and the orders fill. * Centralize internal-inclusive subscription config lookup in fill models ShouldWaitForFreshDataOnStale re-resolved the subscription configs through the ShouldWaitForFreshData call it makes first, and GetMarketFillPrice did the same. Thread the already-fetched configs through ShouldWaitForFreshData and GetMarketFillPrice so each market fill resolves them at most once. Add a GetSubscriptionDataConfigs(Security) helper on the base FillModel that returns the internal-inclusive configs, and route every fill-model call site through it to remove the duplicated lookup and repeated comment. * Avoid list allocation in ShouldWaitForFreshData Replace the Where(...).ToList() + All(...) with a single foreach over the subscription configs, short-circuiting on the first non-coarse resolution.
1 parent 38a78c4 commit a565dfa

98 files changed

Lines changed: 1239 additions & 732 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Algorithm.CSharp/AddOptionContractExpiresRegressionAlgorithm.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -135,33 +135,33 @@ public override void OnData(Slice slice)
135135
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
136136
{
137137
{"Total Orders", "3"},
138-
{"Average Win", "2.73%"},
138+
{"Average Win", "2.67%"},
139139
{"Average Loss", "-2.98%"},
140-
{"Compounding Annual Return", "-4.619%"},
141-
{"Drawdown", "0.300%"},
142-
{"Expectancy", "-0.042"},
140+
{"Compounding Annual Return", "-5.432%"},
141+
{"Drawdown", "0.400%"},
142+
{"Expectancy", "-0.052"},
143143
{"Start Equity", "100000"},
144-
{"End Equity", "99668"},
145-
{"Net Profit", "-0.332%"},
146-
{"Sharpe Ratio", "-4.614"},
147-
{"Sortino Ratio", "0"},
148-
{"Probabilistic Sharpe Ratio", "0.427%"},
144+
{"End Equity", "99608"},
145+
{"Net Profit", "-0.392%"},
146+
{"Sharpe Ratio", "-5.487"},
147+
{"Sortino Ratio", "-2.607"},
148+
{"Probabilistic Sharpe Ratio", "0.016%"},
149149
{"Loss Rate", "50%"},
150150
{"Win Rate", "50%"},
151-
{"Profit-Loss Ratio", "0.92"},
152-
{"Alpha", "-0.022"},
153-
{"Beta", "-0.012"},
151+
{"Profit-Loss Ratio", "0.90"},
152+
{"Alpha", "-0.028"},
153+
{"Beta", "-0.01"},
154154
{"Annual Standard Deviation", "0.005"},
155155
{"Annual Variance", "0"},
156-
{"Information Ratio", "-2.823"},
156+
{"Information Ratio", "-2.949"},
157157
{"Tracking Error", "0.049"},
158-
{"Treynor Ratio", "2.01"},
158+
{"Treynor Ratio", "3.063"},
159159
{"Total Fees", "$2.00"},
160160
{"Estimated Strategy Capacity", "$5700000.00"},
161161
{"Lowest Capacity Asset", "AOL VRKS95ENPM9Y|AOL R735QTJ8XC9X"},
162-
{"Portfolio Turnover", "0.55%"},
162+
{"Portfolio Turnover", "0.54%"},
163163
{"Drawdown Recovery", "0"},
164-
{"OrderListHash", "d314aef81752b6583fd58f9e49054cd4"}
164+
{"OrderListHash", "65d9c6a5991648c8c54a23423a51340d"}
165165
};
166166
}
167167
}

Algorithm.CSharp/AutomaticSeedBaseRegressionAlgorithm.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@ public abstract class AutomaticSeedBaseRegressionAlgorithm : QCAlgorithm, IRegre
3131
protected virtual bool ShouldHaveTradeData { get; }
3232
protected virtual bool ShouldHaveQuoteData { get; }
3333
protected virtual bool ShouldHaveOpenInterestData { get; }
34+
protected virtual List<string> SecuritiesToIgnoreForChecking => Enumerable.Empty<string>().ToList();
3435

3536
public override void OnSecuritiesChanged(SecurityChanges changes)
3637
{
3738
var gotTrades = false;
3839
var gotQuotes = false;
3940
var gotOpenInterest = false;
4041

41-
foreach (var addedSecurity in changes.AddedSecurities.Where(x => !x.Symbol.IsCanonical() || x.Symbol.SecurityType == SecurityType.Future))
42+
var securitiesToCheck = changes.AddedSecurities.Where(x => (!x.Symbol.IsCanonical() || x.Symbol.SecurityType == SecurityType.Future) && !SecuritiesToIgnoreForChecking.Contains(x.Symbol.Value)).ToList();
43+
44+
foreach (var addedSecurity in securitiesToCheck)
4245
{
4346
if (addedSecurity.Price == 0)
4447
{
@@ -55,7 +58,7 @@ public override void OnSecuritiesChanged(SecurityChanges changes)
5558
gotOpenInterest |= addedSecurity.Cache.GetData<OpenInterest>() != null;
5659
}
5760

58-
if (changes.AddedSecurities.Count > 0)
61+
if (securitiesToCheck.Count > 0)
5962
{
6063
if (ShouldHaveTradeData && !gotTrades)
6164
{

Algorithm.CSharp/BacktestingBrokerageRegressionAlgorithm.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -316,30 +316,30 @@ public override OrderEvent MarketFill(Security asset, MarketOrder order)
316316
{"Total Orders", "3"},
317317
{"Average Win", "0%"},
318318
{"Average Loss", "-0.40%"},
319-
{"Compounding Annual Return", "-21.378%"},
320-
{"Drawdown", "0.400%"},
319+
{"Compounding Annual Return", "119.386%"},
320+
{"Drawdown", "0.800%"},
321321
{"Expectancy", "-1"},
322322
{"Start Equity", "100000"},
323-
{"End Equity", "99671.06"},
324-
{"Net Profit", "-0.329%"},
325-
{"Sharpe Ratio", "-14.095"},
323+
{"End Equity", "101082.06"},
324+
{"Net Profit", "1.082%"},
325+
{"Sharpe Ratio", "12.594"},
326326
{"Sortino Ratio", "0"},
327-
{"Probabilistic Sharpe Ratio", "1.216%"},
327+
{"Probabilistic Sharpe Ratio", "95.977%"},
328328
{"Loss Rate", "100%"},
329329
{"Win Rate", "0%"},
330330
{"Profit-Loss Ratio", "0"},
331-
{"Alpha", "-0.01"},
332-
{"Beta", "0.097"},
333-
{"Annual Standard Deviation", "0.002"},
334-
{"Annual Variance", "0"},
335-
{"Information Ratio", "7.39"},
336-
{"Tracking Error", "0.015"},
337-
{"Treynor Ratio", "-0.234"},
331+
{"Alpha", "0.504"},
332+
{"Beta", "-6.672"},
333+
{"Annual Standard Deviation", "0.111"},
334+
{"Annual Variance", "0.012"},
335+
{"Information Ratio", "12.001"},
336+
{"Tracking Error", "0.127"},
337+
{"Treynor Ratio", "-0.209"},
338338
{"Total Fees", "$2.00"},
339339
{"Estimated Strategy Capacity", "$0"},
340340
{"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"},
341341
{"Portfolio Turnover", "17.02%"},
342-
{"Drawdown Recovery", "0"},
342+
{"Drawdown Recovery", "4"},
343343
{"OrderListHash", "1be5073f2cf8802ffa163f7dab7d040e"}
344344
};
345345
}

Algorithm.CSharp/BasicTemplateContinuousFutureAlgorithm.cs

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ public class BasicTemplateContinuousFutureAlgorithm : QCAlgorithm, IRegressionAl
3636
private SimpleMovingAverage _fast;
3737
private SimpleMovingAverage _slow;
3838

39+
// Minimum SMA gap required before acting on a cross; see the workaround note in OnData.
40+
private const decimal CrossThreshold = 0.001m;
41+
3942
/// <summary>
4043
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
4144
/// </summary>
@@ -69,15 +72,17 @@ public override void OnData(Slice slice)
6972
}
7073
}
7174

75+
// Workaround so the C# and Python versions take the exact same trades on the limited
76+
// sample data in the repository (decimal vs double rounding can disagree at a cross).
7277
if (!Portfolio.Invested)
7378
{
74-
if(_fast > _slow)
79+
if(_fast.Current.Value - _slow.Current.Value > CrossThreshold)
7580
{
7681
_currentContract = Securities[_continuousContract.Mapped];
7782
Buy(_currentContract.Symbol, 1);
7883
}
7984
}
80-
else if(_fast < _slow)
85+
else if(_slow.Current.Value - _fast.Current.Value > CrossThreshold)
8186
{
8287
Liquidate();
8388
}
@@ -134,34 +139,34 @@ public override void OnSecuritiesChanged(SecurityChanges changes)
134139
/// </summary>
135140
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
136141
{
137-
{"Total Orders", "5"},
138-
{"Average Win", "2.48%"},
139-
{"Average Loss", "0%"},
140-
{"Compounding Annual Return", "11.325%"},
141-
{"Drawdown", "1.500%"},
142-
{"Expectancy", "0"},
142+
{"Total Orders", "9"},
143+
{"Average Win", "2.85%"},
144+
{"Average Loss", "-0.43%"},
145+
{"Compounding Annual Return", "11.019%"},
146+
{"Drawdown", "0.900%"},
147+
{"Expectancy", "2.818"},
143148
{"Start Equity", "100000"},
144-
{"End Equity", "105549.6"},
145-
{"Net Profit", "5.550%"},
146-
{"Sharpe Ratio", "1.332"},
147-
{"Sortino Ratio", "879.904"},
148-
{"Probabilistic Sharpe Ratio", "79.894%"},
149-
{"Loss Rate", "0%"},
150-
{"Win Rate", "100%"},
151-
{"Profit-Loss Ratio", "0"},
152-
{"Alpha", "0.075"},
153-
{"Beta", "-0.017"},
154-
{"Annual Standard Deviation", "0.053"},
155-
{"Annual Variance", "0.003"},
156-
{"Information Ratio", "-1.48"},
157-
{"Tracking Error", "0.099"},
158-
{"Treynor Ratio", "-4.187"},
159-
{"Total Fees", "$10.75"},
160-
{"Estimated Strategy Capacity", "$7100000.00"},
149+
{"End Equity", "105403.5"},
150+
{"Net Profit", "5.404%"},
151+
{"Sharpe Ratio", "1.531"},
152+
{"Sortino Ratio", "2.106"},
153+
{"Probabilistic Sharpe Ratio", "82.864%"},
154+
{"Loss Rate", "50%"},
155+
{"Win Rate", "50%"},
156+
{"Profit-Loss Ratio", "6.64"},
157+
{"Alpha", "0.067"},
158+
{"Beta", "0.009"},
159+
{"Annual Standard Deviation", "0.045"},
160+
{"Annual Variance", "0.002"},
161+
{"Information Ratio", "-1.606"},
162+
{"Tracking Error", "0.093"},
163+
{"Treynor Ratio", "7.237"},
164+
{"Total Fees", "$19.35"},
165+
{"Estimated Strategy Capacity", "$1000000000.00"},
161166
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
162-
{"Portfolio Turnover", "2.33%"},
163-
{"Drawdown Recovery", "37"},
164-
{"OrderListHash", "223735440010fcec5889bb7becacfa82"}
167+
{"Portfolio Turnover", "4.18%"},
168+
{"Drawdown Recovery", "19"},
169+
{"OrderListHash", "eb3bed9886f79a56c631225a6445adb2"}
165170
};
166171
}
167172
}

Algorithm.CSharp/BasicTemplateContinuousFutureWithExtendedMarketAlgorithm.cs

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ public class BasicTemplateContinuousFutureWithExtendedMarketAlgorithm : QCAlgori
3737
private SimpleMovingAverage _fast;
3838
private SimpleMovingAverage _slow;
3939

40+
// Minimum SMA gap required before acting on a cross; see the workaround note in OnData.
41+
private const decimal CrossThreshold = 0.001m;
42+
4043
/// <summary>
4144
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
4245
/// </summary>
@@ -76,17 +79,24 @@ public override void OnData(Slice slice)
7679
return;
7780
}
7881

79-
if (!Portfolio.Invested)
82+
// This is just to limit the amount of orders done in this regression test, since data in the repo is limited.
83+
// Also limit it to 3 orders so that the continuous contract rolls happens with an open position.
84+
if (Time < new DateTime(2013, 11, 12) && Transactions.OrdersCount < 3)
8085
{
81-
if(_fast > _slow)
86+
// Workaround so the C# and Python versions take the exact same trades on the limited
87+
// sample data in the repository (decimal vs double rounding can disagree at a cross).
88+
if (!Portfolio.Invested)
8289
{
83-
_currentContract = Securities[_continuousContract.Mapped];
84-
Buy(_currentContract.Symbol, 1);
90+
if (_fast.Current.Value - _slow.Current.Value > CrossThreshold)
91+
{
92+
_currentContract = Securities[_continuousContract.Mapped];
93+
Buy(_currentContract.Symbol, 1);
94+
}
95+
}
96+
else if (_slow.Current.Value - _fast.Current.Value > CrossThreshold)
97+
{
98+
Liquidate();
8599
}
86-
}
87-
else if(_fast < _slow)
88-
{
89-
Liquidate();
90100
}
91101

92102
if (_currentContract != null && _currentContract.Symbol != _continuousContract.Mapped)
@@ -140,34 +150,34 @@ public override void OnSecuritiesChanged(SecurityChanges changes)
140150
/// </summary>
141151
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
142152
{
143-
{"Total Orders", "5"},
144-
{"Average Win", "2.86%"},
153+
{"Total Orders", "3"},
154+
{"Average Win", "6.15%"},
145155
{"Average Loss", "0%"},
146-
{"Compounding Annual Return", "12.959%"},
147-
{"Drawdown", "1.100%"},
156+
{"Compounding Annual Return", "13.813%"},
157+
{"Drawdown", "1.400%"},
148158
{"Expectancy", "0"},
149159
{"Start Equity", "100000"},
150-
{"End Equity", "106337.1"},
151-
{"Net Profit", "6.337%"},
152-
{"Sharpe Ratio", "1.41"},
153-
{"Sortino Ratio", "1.242"},
154-
{"Probabilistic Sharpe Ratio", "77.992%"},
160+
{"End Equity", "106741.4"},
161+
{"Net Profit", "6.741%"},
162+
{"Sharpe Ratio", "2.003"},
163+
{"Sortino Ratio", "2.845"},
164+
{"Probabilistic Sharpe Ratio", "92.590%"},
155165
{"Loss Rate", "0%"},
156166
{"Win Rate", "100%"},
157167
{"Profit-Loss Ratio", "0"},
158-
{"Alpha", "0.071"},
159-
{"Beta", "0.054"},
160-
{"Annual Standard Deviation", "0.059"},
161-
{"Annual Variance", "0.003"},
162-
{"Information Ratio", "-1.392"},
163-
{"Tracking Error", "0.097"},
164-
{"Treynor Ratio", "1.518"},
165-
{"Total Fees", "$10.75"},
166-
{"Estimated Strategy Capacity", "$890000000.00"},
168+
{"Alpha", "0.069"},
169+
{"Beta", "0.086"},
170+
{"Annual Standard Deviation", "0.044"},
171+
{"Annual Variance", "0.002"},
172+
{"Information Ratio", "-1.506"},
173+
{"Tracking Error", "0.086"},
174+
{"Treynor Ratio", "1.023"},
175+
{"Total Fees", "$6.45"},
176+
{"Estimated Strategy Capacity", "$3700000000.00"},
167177
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
168-
{"Portfolio Turnover", "2.32%"},
169-
{"Drawdown Recovery", "34"},
170-
{"OrderListHash", "1504a8892da8d8c0650018732f315753"}
178+
{"Portfolio Turnover", "1.37%"},
179+
{"Drawdown Recovery", "18"},
180+
{"OrderListHash", "764ab9f6ea662a60e41daedb9613b246"}
171181
};
172182
}
173183
}

Algorithm.CSharp/BasicTemplateFutureRolloverAlgorithm.cs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -193,34 +193,34 @@ public void Dispose()
193193
/// </summary>
194194
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
195195
{
196-
{"Total Orders", "1"},
197-
{"Average Win", "0%"},
196+
{"Total Orders", "3"},
197+
{"Average Win", "0.14%"},
198198
{"Average Loss", "0%"},
199-
{"Compounding Annual Return", "-0.010%"},
200-
{"Drawdown", "0.000%"},
199+
{"Compounding Annual Return", "0.770%"},
200+
{"Drawdown", "0.100%"},
201201
{"Expectancy", "0"},
202202
{"Start Equity", "1000000"},
203-
{"End Equity", "999983.2"},
204-
{"Net Profit", "-0.002%"},
205-
{"Sharpe Ratio", "-225.214"},
206-
{"Sortino Ratio", "0"},
207-
{"Probabilistic Sharpe Ratio", "0.135%"},
203+
{"End Equity", "1001341.4"},
204+
{"Net Profit", "0.134%"},
205+
{"Sharpe Ratio", "-0.494"},
206+
{"Sortino Ratio", "-0.544"},
207+
{"Probabilistic Sharpe Ratio", "55.093%"},
208208
{"Loss Rate", "0%"},
209-
{"Win Rate", "0%"},
209+
{"Win Rate", "100%"},
210210
{"Profit-Loss Ratio", "0"},
211-
{"Alpha", "-0.008"},
212-
{"Beta", "0"},
213-
{"Annual Standard Deviation", "0"},
211+
{"Alpha", "-0.015"},
212+
{"Beta", "0.03"},
213+
{"Annual Standard Deviation", "0.004"},
214214
{"Annual Variance", "0"},
215-
{"Information Ratio", "-5.146"},
216-
{"Tracking Error", "0.083"},
217-
{"Treynor Ratio", "-542.359"},
218-
{"Total Fees", "$2.15"},
219-
{"Estimated Strategy Capacity", "$0"},
215+
{"Information Ratio", "-5.235"},
216+
{"Tracking Error", "0.081"},
217+
{"Treynor Ratio", "-0.069"},
218+
{"Total Fees", "$6.45"},
219+
{"Estimated Strategy Capacity", "$780000000000.00"},
220220
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
221-
{"Portfolio Turnover", "0.13%"},
222-
{"Drawdown Recovery", "0"},
223-
{"OrderListHash", "a6ccce3a1a7f549f887d83e84bfa878d"}
221+
{"Portfolio Turnover", "0.42%"},
222+
{"Drawdown Recovery", "3"},
223+
{"OrderListHash", "d17bbe62c86730e5178528a3153df0e6"}
224224
};
225225
}
226226
}

0 commit comments

Comments
 (0)