Files
quantconnect--lean/Common/Python/FillModelPythonWrapper.cs
T
Aaron Janeiro Stone 643e8754ed Feature 5162 - LimitIfTouched Orders (#5164)
* Adds LimitIfTouched order.

TODO:
-- Add tests.
-- Add into existing regression algorithms.
-- Refactors (?)

* Fixes

- Remove unrequired space changes
- Fix EquityFillModel min/max limit price fill
- Add TriggerPrice for UpdateOrderRequest.

Quote info used w.r.t. comparing against Limit prices for LIT

FillModel.cs implementation is fixed to use quotes when comparing against set limit prices.
Also changes test implementations to assert which of quotes/trade-bars are being used

Reviewer-suggested fixes
------------
Merge remote-tracking branch 'origin/limiftouched' into limiftouched
Styling
Adds missing null check for quotebar
Styling
Adds missing null check for quotebar
Merge remote-tracking branch 'origin/limiftouched' into limiftouched
High/Low w.r.t. trigger price for determining if TriggerTouched changed to Current price
https://github.com/QuantConnect/Lean/pull/5164/files/0462ad668a5fe65e771122165f36c72d56b92df6#r569832380
fill fixes:
FillModel.cs: Fills exactly at the limit
EquityFillModel.cs: https://www1.interactivebrokers.com/en/index.php?f=608
Equity fill now uses quotebars
Revert - use new constructor which emulates former SubmitOrderRequest
Style changes
Reverts order model to original by means if new constructor
High/Low w.r.t. trigger price for determining if TriggerTouched changed to Current price
https://github.com/QuantConnect/Lean/pull/5164/files/0462ad668a5fe65e771122165f36c72d56b92df6#r569832380
fill fixes:
FillModel.cs: Fills exactly at the limit
EquityFillModel.cs: https://www1.interactivebrokers.com/en/index.php?f=608
Equity fill now uses quotebars
Revert - use new constructor which emulates former SubmitOrderRequest
Style changes
Reverts order model to original by means if new constructor
Merge commit 'bf4c96d2a055ea808fa4293662528c11a89b72c7'

* Suggested style fixes

* Review fixes
-------------------
- Suggested style fixes
- Changes LIT regression to better incorporate order modifications
- TODO: orderlisthash must be fixed
Fixed LIT regression algo
-----------------------
- Includes asserts in OnOrderEvent

* Fix OrderListHash

OrderListHash -> -292689487

* Re-adds quote nullchecks

* EquityFillModelTests fixes asserts

* Reordering FillModel.cs

* Fixes quote logic, adds methods in FillModel.cs

* Refactoring + LIT regression fixes
-- revert unneeded changes

* Fixes list hash

* Rebase -- catch up upstream

* OrderListHash fix

* Various fixes by reviewer

* Final requested changes

* tagged time -> utcinvariant

* Fixes listorderhash

* Time changed to UtcTime.ToString(DateFormat.US, CultureInfo.InvariantCulture)

* Adds Python LimitIfTouchedRegressionAlgorithm

* adds LimitIfTouchedRegressionAlgorithm.py

* adds LimitIfTouchedRegressionAlgorithm.py

* Minor changes to LIT regression algorithms

Co-authored-by: Martin Molinero <martin.molinero1@gmail.com>
2021-02-15 10:29:51 -03:00

179 lines
7.6 KiB
C#

/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Python.Runtime;
using QuantConnect.Orders;
using QuantConnect.Orders.Fills;
using QuantConnect.Securities;
namespace QuantConnect.Python
{
/// <summary>
/// Wraps a <see cref="PyObject"/> object that represents a model that simulates order fill events
/// </summary>
public class FillModelPythonWrapper : FillModel
{
private readonly dynamic _model;
/// <summary>
/// Constructor for initialising the <see cref="FillModelPythonWrapper"/> class with wrapped <see cref="PyObject"/> object
/// </summary>
/// <param name="model">Represents a model that simulates order fill events</param>
public FillModelPythonWrapper(PyObject model)
{
_model = model;
using (Py.GIL())
{
_model.SetPythonWrapper(this);
}
}
/// <summary>
/// Return an order event with the fill details
/// </summary>
/// <param name="parameters">A parameters object containing the security and order</param>
/// <returns>Order fill information detailing the average price and quantity filled.</returns>
public override Fill Fill(FillModelParameters parameters)
{
Parameters = parameters;
using (Py.GIL())
{
return (_model.Fill(parameters) as PyObject).GetAndDispose<Fill>();
}
}
/// <summary>
/// Limit Fill Model. Return an order event with the fill details.
/// </summary>
/// <param name="asset">Stock Object to use to help model limit fill</param>
/// <param name="order">Order to fill. Alter the values directly if filled.</param>
/// <returns>Order fill information detailing the average price and quantity filled.</returns>
public override OrderEvent LimitFill(Security asset, LimitOrder order)
{
using (Py.GIL())
{
return (_model.LimitFill(asset, order) as PyObject).GetAndDispose<OrderEvent>();
}
}
/// <summary>
/// Limit if Touched Fill Model. Return an order event with the fill details.
/// </summary>
/// <param name="asset">Asset we're trading this order</param>
/// <param name="order"><see cref="LimitIfTouchedOrder"/> Order to Check, return filled if true</param>
/// <returns>Order fill information detailing the average price and quantity filled.</returns>
public override OrderEvent LimitIfTouchedFill(Security asset, LimitIfTouchedOrder order)
{
using (Py.GIL())
{
return (_model.LimitIfTouchedFill(asset, order) as PyObject).GetAndDispose<OrderEvent>();
}
}
/// <summary>
/// Model the slippage on a market order: fixed percentage of order price
/// </summary>
/// <param name="asset">Asset we're trading this order</param>
/// <param name="order">Order to update</param>
/// <returns>Order fill information detailing the average price and quantity filled.</returns>
public override OrderEvent MarketFill(Security asset, MarketOrder order)
{
using (Py.GIL())
{
return (_model.MarketFill(asset, order) as PyObject).GetAndDispose<OrderEvent>();
}
}
/// <summary>
/// Market on Close Fill Model. Return an order event with the fill details
/// </summary>
/// <param name="asset">Asset we're trading with this order</param>
/// <param name="order">Order to be filled</param>
/// <returns>Order fill information detailing the average price and quantity filled.</returns>
public override OrderEvent MarketOnCloseFill(Security asset, MarketOnCloseOrder order)
{
using (Py.GIL())
{
return (_model.MarketOnCloseFill(asset, order) as PyObject).GetAndDispose<OrderEvent>();
}
}
/// <summary>
/// Market on Open Fill Model. Return an order event with the fill details
/// </summary>
/// <param name="asset">Asset we're trading with this order</param>
/// <param name="order">Order to be filled</param>
/// <returns>Order fill information detailing the average price and quantity filled.</returns>
public override OrderEvent MarketOnOpenFill(Security asset, MarketOnOpenOrder order)
{
using (Py.GIL())
{
return (_model.MarketOnOpenFill(asset, order) as PyObject).GetAndDispose<OrderEvent>();
}
}
/// <summary>
/// Stop Limit Fill Model. Return an order event with the fill details.
/// </summary>
/// <param name="asset">Asset we're trading this order</param>
/// <param name="order">Stop Limit Order to Check, return filled if true</param>
/// <returns>Order fill information detailing the average price and quantity filled.</returns>
public override OrderEvent StopLimitFill(Security asset, StopLimitOrder order)
{
using (Py.GIL())
{
return (_model.StopLimitFill(asset, order) as PyObject).GetAndDispose<OrderEvent>();
}
}
/// <summary>
/// Stop Market Fill Model. Return an order event with the fill details.
/// </summary>
/// <param name="asset">Asset we're trading this order</param>
/// <param name="order">Stop Order to Check, return filled if true</param>
/// <returns>Order fill information detailing the average price and quantity filled.</returns>
public override OrderEvent StopMarketFill(Security asset, StopMarketOrder order)
{
using (Py.GIL())
{
return (_model.StopMarketFill(asset, order) as PyObject).GetAndDispose<OrderEvent>();
}
}
/// <summary>
/// Get the minimum and maximum price for this security in the last bar:
/// </summary>
/// <param name="asset">Security asset we're checking</param>
/// <param name="direction">The order direction, decides whether to pick bid or ask</param>
protected override Prices GetPrices(Security asset, OrderDirection direction)
{
using (Py.GIL())
{
return (_model.GetPrices(asset, direction) as PyObject).GetAndDispose<Prices>();
}
}
/// <summary>
/// Get the minimum and maximum price for this security in the last bar:
/// </summary>
/// <param name="asset">Security asset we're checking</param>
/// <param name="direction">The order direction, decides whether to pick bid or ask</param>
/// <remarks>This method was implemented temporarily to help the refactoring of fill models (GH #4567)</remarks>
internal Prices GetPricesInternal(Security asset, OrderDirection direction)
{
return GetPrices(asset, direction);
}
}
}