21 using System.Threading.Tasks;
25 using System.Collections.Generic;
35 private static readonly
object _locker =
new();
36 private static Dictionary<string, MarginRequirementsEntry[]> _marginRequirementsCache =
new();
39 private int _marginCurrentIndex;
102 throw new InvalidOperationException(
"Futures are leveraged products and different leverage cannot be set by user");
116 throw new InvalidOperationException(
117 "Futures do not allow specifying a leveraged target, since they are traded using margin which already is leveraged. " +
118 $
"Possible target buying power goes from -1 to 1, target provided is: {parameters.TargetBuyingPower}");
120 return base.GetMaximumOrderQuantityForTargetBuyingPower(parameters);
139 ConvertToAccountCurrency(fees).Amount;
143 return new InitialMargin(orderMargin + Math.Sign(orderMargin) * feesInAccountCurrency);
159 var marginReq = GetCurrentMarginRequirements(security);
160 if (marginReq ==
null)
166 && security.Exchange.ExchangeOpen
167 && !security.Exchange.ClosingSoon)
169 return marginReq.MaintenanceIntraday * parameters.
AbsoluteQuantity * security.QuoteCurrency.ConversionRate;
173 return marginReq.MaintenanceOvernight * parameters.
AbsoluteQuantity * security.QuoteCurrency.ConversionRate;
188 var marginReq = GetCurrentMarginRequirements(security);
189 if (marginReq ==
null)
195 && security.Exchange.ExchangeOpen
196 && !security.Exchange.ClosingSoon)
198 return new InitialMargin(marginReq.InitialIntraday * quantity * security.QuoteCurrency.ConversionRate);
202 return new InitialMargin(marginReq.InitialOvernight * quantity * security.QuoteCurrency.ConversionRate);
208 if (lastData ==
null)
213 var marginRequirementsHistory = LoadMarginRequirementsHistory(security.
Symbol);
214 var date = lastData.Time.Date;
216 while (_marginCurrentIndex + 1 < marginRequirementsHistory.Length &&
217 marginRequirementsHistory[_marginCurrentIndex + 1].Date <= date)
219 _marginCurrentIndex++;
222 return marginRequirementsHistory[_marginCurrentIndex];
230 private static MarginRequirementsEntry[] LoadMarginRequirementsHistory(Symbol symbol)
232 if (!_marginRequirementsCache.TryGetValue(symbol.ID.Symbol, out var marginRequirementsEntries))
236 if (!_marginRequirementsCache.TryGetValue(symbol.ID.Symbol, out marginRequirementsEntries))
238 Dictionary<string, MarginRequirementsEntry[]> marginRequirementsCache =
new(_marginRequirementsCache)
240 [symbol.ID.Symbol] = marginRequirementsEntries = FromCsvFile(symbol)
243 _marginRequirementsCache = marginRequirementsCache;
247 return marginRequirementsEntries;
255 private static MarginRequirementsEntry[] FromCsvFile(Symbol symbol)
257 var file = Path.Combine(Globals.DataFolder,
258 symbol.SecurityType.ToLower(),
259 symbol.ID.Market.ToLowerInvariant(),
260 "margins", symbol.ID.Symbol +
".csv");
262 if(_dataProvider ==
null)
269 var marginRequirementsEntries = _dataProvider.ReadLines(file)
270 .Where(x => !x.StartsWith(
"#") && !
string.IsNullOrWhiteSpace(x))
272 .Select(MarginRequirementsEntry.Create)
273 .OrderBy(x => x.Date)
276 if (marginRequirementsEntries.Length == 0)
278 Log.
Error($
"FutureMarginModel.FromCsvFile(): Unable to locate future margin requirements file. Defaulting to zero margin for this symbol. File: {file}");
280 marginRequirementsEntries =
new[] {
281 new MarginRequirementsEntry
283 Date = DateTime.MinValue
287 return marginRequirementsEntries;
293 private static void ClearMarginCache()
295 Task.Delay(Time.OneDay).ContinueWith((_) =>
299 _marginRequirementsCache =
new();