/*
* 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 System;
using System.Collections.Generic;
using Python.Runtime;
using QuantConnect.Benchmarks;
using QuantConnect.Brokerages;
using QuantConnect.Data.Market;
using QuantConnect.Data.Shortable;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;
using QuantConnect.Orders.Fills;
using QuantConnect.Orders.Slippage;
using QuantConnect.Securities;
namespace QuantConnect.Python
{
///
/// Provides an implementation of that wraps a object
///
public class BrokerageModelPythonWrapper : BasePythonWrapper, IBrokerageModel
{
///
/// Constructor for initialising the class with wrapped object
///
/// Models brokerage transactions, fees, and order
public BrokerageModelPythonWrapper(PyObject model)
: base(model)
{
}
///
/// Gets or sets the account type used by this model
///
public AccountType AccountType
{
get
{
return GetProperty(nameof(AccountType));
}
}
///
/// Gets the brokerages model percentage factor used to determine the required unused buying power for the account.
/// From 1 to 0. Example: 0 means no unused buying power is required. 0.5 means 50% of the buying power should be left unused.
///
public decimal RequiredFreeBuyingPowerPercent
{
get
{
return GetProperty(nameof(RequiredFreeBuyingPowerPercent));
}
}
///
/// Gets a map of the default markets to be used for each security type
///
public IReadOnlyDictionary DefaultMarkets
{
get
{
using (Py.GIL())
{
var markets = GetProperty(nameof(DefaultMarkets)) as dynamic;
if ((markets as PyObject).TryConvert(out IReadOnlyDictionary csharpDic))
{
return csharpDic;
}
var dic = new Dictionary();
foreach (var item in markets)
{
using var pyItem = item as PyObject;
var market = pyItem.As();
dic[market] = markets[item];
}
(markets as PyObject).Dispose();
return dic;
}
}
}
///
/// Applies the split to the specified order ticket
///
/// The open tickets matching the split event
/// The split event data
public void ApplySplit(List tickets, Split split)
{
InvokeMethod(nameof(ApplySplit), tickets, split);
}
///
/// Returns true if the brokerage would be able to execute this order at this time assuming
/// market prices are sufficient for the fill to take place. This is used to emulate the
/// brokerage fills in backtesting and paper trading. For example some brokerages may not perform
/// executions during extended market hours. This is not intended to be checking whether or not
/// the exchange is open, that is handled in the Security.Exchange property.
///
/// The security being ordered
/// The order to test for execution
/// True if the brokerage would be able to perform the execution, false otherwise
public bool CanExecuteOrder(Security security, Order order)
{
return InvokeMethod(nameof(CanExecuteOrder), security, order);
}
///
/// Returns true if the brokerage could accept this order. This takes into account
/// order type, security type, and order size limits.
///
///
/// For example, a brokerage may have no connectivity at certain times, or an order rate/size limit
///
/// The security being ordered
/// The order to be processed
/// If this function returns false, a brokerage message detailing why the order may not be submitted
/// True if the brokerage could process the order, false otherwise
public bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message)
{
message = null;
var result = InvokeMethodWithOutParameters(nameof(CanSubmitOrder), new[] { typeof(BrokerageMessageEvent) },
out var outParameters, security, order, message);
message = outParameters[0] as BrokerageMessageEvent;
return result;
}
///
/// Returns true if the brokerage would allow updating the order as specified by the request
///
/// The security of the order
/// The order to be updated
/// The requested updated to be made to the order
/// If this function returns false, a brokerage message detailing why the order may not be updated
/// True if the brokerage would allow updating the order, false otherwise
public bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message)
{
message = null;
var result = InvokeMethodWithOutParameters(nameof(CanUpdateOrder), new[] { typeof(BrokerageMessageEvent) }, out var outParameters,
security, order, request, message);
message = outParameters[0] as BrokerageMessageEvent;
return result;
}
///
/// Get the benchmark for this model
///
/// SecurityService to create the security with if needed
/// The benchmark for this brokerage
public IBenchmark GetBenchmark(SecurityManager securities)
{
return InvokeMethodAndWrapResult(nameof(GetBenchmark), (pyInstance) => new BenchmarkPythonWrapper(pyInstance), securities);
}
///
/// Gets a new fee model that represents this brokerage's fee structure
///
/// The security to get a fee model for
/// The new fee model for this brokerage
public IFeeModel GetFeeModel(Security security)
{
return InvokeMethodAndWrapResult(nameof(GetFeeModel), (pyInstance) => new FeeModelPythonWrapper(pyInstance), security);
}
///
/// Gets a new fill model that represents this brokerage's fill behavior
///
/// The security to get fill model for
/// The new fill model for this brokerage
public IFillModel GetFillModel(Security security)
{
return InvokeMethodAndWrapResult(nameof(GetFillModel), (pyInstance) => new FillModelPythonWrapper(pyInstance), security);
}
///
/// Gets the brokerage's leverage for the specified security
///
/// The security's whose leverage we seek
/// The leverage for the specified security
public decimal GetLeverage(Security security)
{
return InvokeMethod(nameof(GetLeverage), security);
}
///
/// Gets a new settlement model for the security
///
/// The security to get a settlement model for
/// The settlement model for this brokerage
public ISettlementModel GetSettlementModel(Security security)
{
return InvokeMethodAndWrapResult(nameof(GetSettlementModel),
(pyInstance) => new SettlementModelPythonWrapper(pyInstance), security);
}
///
/// Gets a new settlement model for the security
///
/// The security to get a settlement model for
/// The account type
/// The settlement model for this brokerage
[Obsolete("Flagged deprecated and will remove December 1st 2018")]
public ISettlementModel GetSettlementModel(Security security, AccountType accountType)
{
return InvokeMethod(nameof(GetSettlementModel), security, accountType);
}
///
/// Gets a new slippage model that represents this brokerage's fill slippage behavior
///
/// The security to get a slippage model for
/// The new slippage model for this brokerage
public ISlippageModel GetSlippageModel(Security security)
{
return InvokeMethodAndWrapResult(nameof(GetSlippageModel),
(pyInstance) => new SlippageModelPythonWrapper(pyInstance), security);
}
///
/// Determine if this symbol is shortable
///
/// The algorithm running
/// The symbol to short
/// The amount to short
///
public bool Shortable(IAlgorithm algorithm, Symbol symbol, decimal quantity)
{
return InvokeMethod(nameof(Shortable), algorithm, symbol, quantity);
}
///
/// Gets a new buying power model for the security, returning the default model with the security's configured leverage.
/// For cash accounts, leverage = 1 is used.
///
/// The security to get a buying power model for
/// The buying power model for this brokerage/security
public IBuyingPowerModel GetBuyingPowerModel(Security security)
{
return InvokeMethodAndWrapResult(nameof(GetBuyingPowerModel),
(pyInstance) => new BuyingPowerModelPythonWrapper(pyInstance), security);
}
///
/// Gets a new buying power model for the security
///
/// The security to get a buying power model for
/// The account type
/// The buying power model for this brokerage/security
[Obsolete("Flagged deprecated and will remove December 1st 2018")]
public IBuyingPowerModel GetBuyingPowerModel(Security security, AccountType accountType)
{
return InvokeMethod(nameof(GetBuyingPowerModel), security, accountType);
}
///
/// Gets the shortable provider
///
/// Shortable provider
public IShortableProvider GetShortableProvider(Security security)
{
return InvokeMethodAndWrapResult(nameof(GetShortableProvider),
(pyInstance) => new ShortableProviderPythonWrapper(pyInstance), security);
}
///
/// Convenience method to get the underlying object from the wrapper.
///
/// Underlying object
public IBrokerageModel GetModel()
{
using (Py.GIL())
{
return Instance.As();
}
}
///
/// Gets a new margin interest rate model for the security
///
/// The security to get a margin interest rate model for
/// The margin interest rate model for this brokerage
public IMarginInterestRateModel GetMarginInterestRateModel(Security security)
{
return InvokeMethodAndWrapResult(nameof(GetMarginInterestRateModel),
(pyInstance) => new MarginInterestRateModelPythonWrapper(pyInstance), security);
}
}
}