Skip to content

Commit 529f782

Browse files
committed
Fix MOO slippage reference price
1 parent c503571 commit 529f782

5 files changed

Lines changed: 110 additions & 6 deletions

File tree

Common/Orders/Fills/EquityFillModel.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -563,9 +563,6 @@ public override OrderEvent MarketOnOpenFill(Security asset, MarketOnOpenOrder or
563563
fill.FillQuantity = order.Quantity;
564564
fill.Status = OrderStatus.Filled;
565565

566-
//Calculate the model slippage: e.g. 0.01c
567-
var slip = asset.SlippageModel.GetSlippageApproximation(asset, order);
568-
569566
var bestEffortMessage = "";
570567

571568
// If there is no trade information, get the bid or ask, then apply the slippage
@@ -578,7 +575,7 @@ public override OrderEvent MarketOnOpenFill(Security asset, MarketOnOpenOrder or
578575
fill.Message += bestEffortMessage;
579576
}
580577

581-
fill.FillPrice += slip;
578+
fill.FillPrice += asset.SlippageModel.GetSlippageApproximation(asset, order, fill.FillPrice);
582579
break;
583580
case OrderDirection.Sell:
584581
if (fill.FillPrice == 0)
@@ -587,7 +584,7 @@ public override OrderEvent MarketOnOpenFill(Security asset, MarketOnOpenOrder or
587584
fill.Message += bestEffortMessage;
588585
}
589586

590-
fill.FillPrice -= slip;
587+
fill.FillPrice -= asset.SlippageModel.GetSlippageApproximation(asset, order, fill.FillPrice);
591588
break;
592589
}
593590

Common/Orders/Slippage/ConstantSlippageModel.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,18 @@ public decimal GetSlippageApproximation(Security asset, Order order)
4343

4444
return lastData.Value*_slippagePercent;
4545
}
46+
47+
/// <summary>
48+
/// Slippage Model. Return a decimal cash slippage approximation on the order
49+
/// using the provided reference price.
50+
/// </summary>
51+
/// <param name="asset">The security matching the order</param>
52+
/// <param name="order">The order to compute slippage for</param>
53+
/// <param name="referencePrice">The price used as the reference for the slippage calculation</param>
54+
/// <returns>The slippage approximation</returns>
55+
public decimal GetSlippageApproximation(Security asset, Order order, decimal referencePrice)
56+
{
57+
return referencePrice * _slippagePercent;
58+
}
4659
}
4760
}

Common/Orders/Slippage/ISlippageModel.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,18 @@ public interface ISlippageModel
2626
/// Slippage Model. Return a decimal cash slippage approximation on the order.
2727
/// </summary>
2828
decimal GetSlippageApproximation(Security asset, Order order);
29+
30+
/// <summary>
31+
/// Slippage Model. Return a decimal cash slippage approximation on the order
32+
/// using the provided reference price.
33+
/// </summary>
34+
/// <param name="asset">The security matching the order</param>
35+
/// <param name="order">The order to compute slippage for</param>
36+
/// <param name="referencePrice">The price used as the reference for the slippage calculation</param>
37+
/// <returns>The slippage approximation</returns>
38+
decimal GetSlippageApproximation(Security asset, Order order, decimal referencePrice)
39+
{
40+
return GetSlippageApproximation(asset, order);
41+
}
2942
}
30-
}
43+
}

Tests/Common/Orders/Fills/EquityFillModelTests.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
using QuantConnect.Indicators;
2323
using QuantConnect.Orders;
2424
using QuantConnect.Orders.Fills;
25+
using QuantConnect.Orders.Slippage;
2526
using QuantConnect.Securities;
2627
using QuantConnect.Securities.Forex;
2728
using QuantConnect.Tests.Common.Data;
@@ -446,6 +447,69 @@ public void PerformsMarketOnOpenUsingOpenPriceWithMinuteSubscription(int quantit
446447
Assert.AreEqual(expected, fill.FillPrice);
447448
}
448449

450+
[TestCase(-100, 103.896)]
451+
[TestCase(100, 104.104)]
452+
public void PerformsMarketOnOpenUsingOpenPriceForConstantSlippageWithDailySubscription(int quantity, decimal expected)
453+
{
454+
const decimal open = 104m;
455+
const decimal baselineClose = 105m;
456+
const decimal mutatedClose = 103.5m;
457+
const decimal slippagePercent = 0.001m;
458+
459+
var reference = new DateTime(2015, 06, 05, 12, 0, 0);
460+
var config = CreateTradeBarConfig(Symbols.SPY, Resolution.Daily);
461+
462+
var baselineEquity = CreateEquity(config);
463+
var mutatedEquity = CreateEquity(config);
464+
465+
baselineEquity.SetSlippageModel(new ConstantSlippageModel(slippagePercent));
466+
mutatedEquity.SetSlippageModel(new ConstantSlippageModel(slippagePercent));
467+
468+
var time = baselineEquity.Exchange.Hours.GetNextMarketOpen(reference, false);
469+
TimeKeeper.SetUtcDateTime(time.ConvertToUtc(TimeZones.NewYork));
470+
471+
TradeBar GetTradeBar(decimal close) => new TradeBar(
472+
time.RoundDown(Time.OneDay),
473+
Symbols.SPY,
474+
open,
475+
106m,
476+
100m,
477+
close,
478+
100,
479+
Time.OneDay);
480+
481+
baselineEquity.SetMarketPrice(GetTradeBar(baselineClose));
482+
mutatedEquity.SetMarketPrice(GetTradeBar(mutatedClose));
483+
484+
var baselineOrder = new MarketOnOpenOrder(Symbols.SPY, quantity, reference);
485+
var mutatedOrder = new MarketOnOpenOrder(Symbols.SPY, quantity, reference);
486+
487+
var configProvider = new MockSubscriptionDataConfigProvider(config);
488+
489+
var baselineFill = ((EquityFillModel)baselineEquity.FillModel)
490+
.Fill(new FillModelParameters(
491+
baselineEquity,
492+
baselineOrder,
493+
configProvider,
494+
Time.OneHour,
495+
null))
496+
.Single();
497+
498+
var mutatedFill = ((EquityFillModel)mutatedEquity.FillModel)
499+
.Fill(new FillModelParameters(
500+
mutatedEquity,
501+
mutatedOrder,
502+
configProvider,
503+
Time.OneHour,
504+
null))
505+
.Single();
506+
507+
Assert.AreEqual(quantity, baselineFill.FillQuantity);
508+
Assert.AreEqual(quantity, mutatedFill.FillQuantity);
509+
Assert.AreEqual(expected, baselineFill.FillPrice);
510+
Assert.AreEqual(baselineFill.FillPrice, mutatedFill.FillPrice);
511+
}
512+
449513
[TestCase(-100)]
450514
[TestCase(100)]
451515
public void PerformsMarketOnOpenUsingOpenPriceWithDailySubscription(int quantity)

Tests/Common/Orders/Slippage/SlippageModelsTests.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,5 +161,22 @@ public void AlphaStreamsSlippageModel_ForexTest()
161161
var actual = model.GetSlippageApproximation(_forex, _forexBuyOrder);
162162
Assert.AreEqual(expected, actual);
163163
}
164+
[Test]
165+
public void SlippageModelReferencePriceOverloadIsBackwardsCompatible()
166+
{
167+
ISlippageModel model = new LegacySlippageModel();
168+
169+
var actual = model.GetSlippageApproximation(_equity, _equityBuyOrder, 123m);
170+
171+
Assert.AreEqual(42m, actual);
172+
}
173+
174+
private sealed class LegacySlippageModel : ISlippageModel
175+
{
176+
public decimal GetSlippageApproximation(Security asset, Order order)
177+
{
178+
return 42m;
179+
}
180+
}
164181
}
165182
}

0 commit comments

Comments
 (0)