Lean  $LEAN_TAG$
OandaBrokerageModel.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 System.Collections.Generic;
19 using QuantConnect.Orders;
23 using QuantConnect.Util;
24 
26 {
27  /// <summary>
28  /// Oanda Brokerage Model Implementation for Back Testing.
29  /// </summary>
31  {
32  /// <summary>
33  /// The default markets for the fxcm brokerage
34  /// </summary>
35  public new static readonly IReadOnlyDictionary<SecurityType, string> DefaultMarketMap = new Dictionary<SecurityType, string>
36  {
37  {SecurityType.Base, Market.USA},
38  {SecurityType.Equity, Market.USA},
39  {SecurityType.Option, Market.USA},
40  {SecurityType.Forex, Market.Oanda},
42  }.ToReadOnlyDictionary();
43 
44  private readonly HashSet<OrderType> _supportedOrderTypes = new()
45  {
46  OrderType.Limit,
47  OrderType.Market,
48  OrderType.StopMarket
49  };
50 
51  /// <summary>
52  /// Gets a map of the default markets to be used for each security type
53  /// </summary>
54  public override IReadOnlyDictionary<SecurityType, string> DefaultMarkets => DefaultMarketMap;
55 
56  /// <summary>
57  /// Initializes a new instance of the <see cref="DefaultBrokerageModel"/> class
58  /// </summary>
59  /// <param name="accountType">The type of account to be modelled, defaults to
60  /// <see cref="AccountType.Margin"/></param>
61  public OandaBrokerageModel(AccountType accountType = AccountType.Margin)
62  : base(accountType)
63  {
64  if (accountType == AccountType.Cash)
65  {
66  throw new InvalidOperationException($"Oanda brokerage can only be used with a {AccountType.Margin} account type");
67  }
68  }
69 
70  /// <summary>
71  /// Returns true if the brokerage could accept this order. This takes into account
72  /// order type, security type, and order size limits.
73  /// </summary>
74  /// <remarks>
75  /// For example, a brokerage may have no connectivity at certain times, or an order rate/size limit
76  /// </remarks>
77  /// <param name="security"></param>
78  /// <param name="order">The order to be processed</param>
79  /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be submitted</param>
80  /// <returns>True if the brokerage could process the order, false otherwise</returns>
81  public override bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message)
82  {
83  message = null;
84 
85  // validate security type
86  if (security.Type != SecurityType.Forex && security.Type != SecurityType.Cfd)
87  {
88  message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
89  Messages.DefaultBrokerageModel.UnsupportedSecurityType(this, security));
90 
91  return false;
92  }
93 
94  // validate order type
95  if (!_supportedOrderTypes.Contains(order.Type))
96  {
97  message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
98  Messages.DefaultBrokerageModel.UnsupportedOrderType(this, order, _supportedOrderTypes));
99 
100  return false;
101  }
102 
103  // validate time in force
105  {
106  message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
107  Messages.DefaultBrokerageModel.UnsupportedTimeInForce(this, order));
108 
109  return false;
110  }
111 
112  return true;
113  }
114 
115  /// <summary>
116  /// Get the benchmark for this model
117  /// </summary>
118  /// <param name="securities">SecurityService to create the security with if needed</param>
119  /// <returns>The benchmark for this brokerage</returns>
120  public override IBenchmark GetBenchmark(SecurityManager securities)
121  {
122  var symbol = Symbol.Create("EURUSD", SecurityType.Forex, Market.Oanda);
123  return SecurityBenchmark.CreateInstance(securities, symbol);
124  }
125 
126  /// <summary>
127  /// Gets a new fee model that represents this brokerage's fee structure
128  /// </summary>
129  /// <param name="security">The security to get a fee model for</param>
130  /// <returns>The new fee model for this brokerage</returns>
131  public override IFeeModel GetFeeModel(Security security)
132  {
133  return new ConstantFeeModel(0m);
134  }
135 
136  /// <summary>
137  /// Gets a new settlement model for the security
138  /// </summary>
139  /// <param name="security">The security to get a settlement model for</param>
140  /// <returns>The settlement model for this brokerage</returns>
141  public override ISettlementModel GetSettlementModel(Security security)
142  {
143  return security.Type == SecurityType.Cfd
146  }
147  }
148 }