Lean  $LEAN_TAG$
BuyingPowerModelExtensions.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
16 using System;
17 using QuantConnect.Orders;
18 
20 {
21  /// <summary>
22  /// Provides extension methods as backwards compatibility shims
23  /// </summary>
24  public static class BuyingPowerModelExtensions
25  {
26  /// <summary>
27  /// Gets the amount of buying power reserved to maintain the specified position
28  /// </summary>
29  /// <param name="model">The <see cref="IBuyingPowerModel"/></param>
30  /// <param name="security">The security</param>
31  /// <returns>The reserved buying power in account currency</returns>
32  public static decimal GetReservedBuyingPowerForPosition(this IBuyingPowerModel model, Security security)
33  {
34  var context = new ReservedBuyingPowerForPositionParameters(security);
35  var reservedBuyingPower = model.GetReservedBuyingPowerForPosition(context);
36  return reservedBuyingPower.AbsoluteUsedBuyingPower;
37  }
38 
39  /// <summary>
40  /// Check if there is sufficient buying power to execute this order.
41  /// </summary>
42  /// <param name="model">The <see cref="IBuyingPowerModel"/></param>
43  /// <param name="portfolio">The algorithm's portfolio</param>
44  /// <param name="security">The security to be traded</param>
45  /// <param name="order">The order</param>
46  /// <returns>Returns buying power information for an order</returns>
48  this IBuyingPowerModel model,
49  SecurityPortfolioManager portfolio,
50  Security security,
51  Order order
52  )
53  {
54  var parameters = new HasSufficientBuyingPowerForOrderParameters(portfolio, security, order);
55 
56  return model.HasSufficientBuyingPowerForOrder(parameters);
57  }
58 
59  /// <summary>
60  /// Get the maximum market order quantity to obtain a position with a given value in account currency
61  /// </summary>
62  /// <param name="model">The <see cref="IBuyingPowerModel"/></param>
63  /// <param name="portfolio">The algorithm's portfolio</param>
64  /// <param name="security">The security to be traded</param>
65  /// <param name="target">The target percent holdings</param>
66  /// <param name="minimumOrderMarginPortfolioPercentage">Configurable minimum order margin portfolio percentage to ignore orders with unrealistic small sizes</param>
67  /// <returns>Returns the maximum allowed market order quantity and if zero, also the reason</returns>
69  this IBuyingPowerModel model,
70  SecurityPortfolioManager portfolio,
71  Security security,
72  decimal target,
73  decimal minimumOrderMarginPortfolioPercentage
74  )
75  {
76  var parameters = new GetMaximumOrderQuantityForTargetBuyingPowerParameters(portfolio, security, target, minimumOrderMarginPortfolioPercentage);
77 
78  return model.GetMaximumOrderQuantityForTargetBuyingPower(parameters);
79  }
80 
81  /// <summary>
82  /// Gets the buying power available for a trade
83  /// </summary>
84  /// <param name="model">The <see cref="IBuyingPowerModel"/></param>
85  /// <param name="portfolio">The algorithm's portfolio</param>
86  /// <param name="security">The security to be traded</param>
87  /// <param name="direction">The direction of the trade</param>
88  /// <returns>The buying power available for the trade</returns>
89  public static decimal GetBuyingPower(
90  this IBuyingPowerModel model,
91  SecurityPortfolioManager portfolio,
92  Security security,
93  OrderDirection direction
94  )
95  {
96  var context = new BuyingPowerParameters(portfolio, security, direction);
97  var buyingPower = model.GetBuyingPower(context);
98 
99  // existing implementations assume certain non-account currency units, so return raw value
100  return buyingPower.Value;
101  }
102 
103  /// <summary>
104  /// Gets the margin currently allocated to the specified holding
105  /// </summary>
106  /// <param name="model">The buying power model</param>
107  /// <param name="security">The security</param>
108  /// <returns>The maintenance margin required for the provided holdings quantity/cost/value</returns>
109  public static decimal GetMaintenanceMargin(this IBuyingPowerModel model, Security security)
110  {
112  }
113 
114  /// <summary>
115  /// Gets the margin currently allocated to the specified holding
116  /// </summary>
117  /// <param name="model">The buying power model</param>
118  /// <param name="security">The security</param>
119  /// <param name="quantity">The quantity of shares</param>
120  /// <returns>The initial margin required for the provided security and quantity</returns>
121  public static decimal GetInitialMarginRequirement(this IBuyingPowerModel model, Security security, decimal quantity)
122  {
123  return model.GetInitialMarginRequirement(new InitialMarginParameters(security, quantity));
124  }
125 
126  /// <summary>
127  /// Helper method to determine if the requested quantity is above the algorithm minimum order margin portfolio percentage
128  /// </summary>
129  /// <param name="model">The buying power model</param>
130  /// <param name="security">The security</param>
131  /// <param name="quantity">The quantity of shares</param>
132  /// <param name="portfolioManager">The algorithm's portfolio</param>
133  /// <param name="minimumOrderMarginPortfolioPercentage">Minimum order margin portfolio percentage to ignore bad orders, orders with unrealistic small sizes</param>
134  /// <remarks>If we are trading with negative margin remaining this method will return true always</remarks>
135  /// <returns>True if this order quantity is above the minimum requested</returns>
137  decimal quantity, SecurityPortfolioManager portfolioManager, decimal minimumOrderMarginPortfolioPercentage)
138  {
139  if (minimumOrderMarginPortfolioPercentage == 0)
140  {
141  return true;
142  }
143  var absFinalOrderMargin = Math.Abs(model.GetInitialMarginRequirement(new InitialMarginParameters(
144  security, quantity)).Value);
145 
146  return AboveMinimumOrderMarginPortfolioPercentage(portfolioManager, minimumOrderMarginPortfolioPercentage, absFinalOrderMargin);
147  }
148 
149  /// <summary>
150  /// Helper method to determine if the requested quantity is above the algorithm minimum order margin portfolio percentage
151  /// </summary>
152  /// <param name="portfolioManager">The algorithm's portfolio</param>
153  /// <param name="minimumOrderMarginPortfolioPercentage">Minimum order margin portfolio percentage to ignore bad orders, orders with unrealistic small sizes</param>
154  /// <param name="absFinalOrderMargin">The calculated order margin value</param>
155  /// <remarks>If we are trading with negative margin remaining this method will return true always</remarks>
156  /// <returns>True if this order quantity is above the minimum requested</returns>
158  decimal minimumOrderMarginPortfolioPercentage,
159  decimal absFinalOrderMargin)
160  {
161  var minimumValue = portfolioManager.TotalPortfolioValue * minimumOrderMarginPortfolioPercentage;
162 
163  if (minimumValue > absFinalOrderMargin
164  // if margin remaining is negative allow the order to pass so we can reduce the position
165  && portfolioManager.GetMarginRemaining(portfolioManager.TotalPortfolioValue) > 0)
166  {
167  return false;
168  }
169 
170  return true;
171  }
172  }
173 }