private bool GetAccountEquityAndUsedMargin(ACCOUNT account, out decimal equity, out decimal usedMargin) { try { decimal exposure; profitCalculator.CalculateAccountExposure(account.ID, out equity, out usedMargin, out exposure, QuoteStorage.Instance.ReceiveAllData(), ManagerAccount.Instance, accountRepository.GetAccountGroup); return(true); } catch (Exception ex) { equity = 0; usedMargin = 0; Logger.ErrorFormat("GetAccountEquityAndUsedMargin({0}) error: {1}", account.ID, ex); return(false); } }
public bool IsEnterEnabled(int accountId, string symbol, int side, int volume, out decimal equity) { Account account; equity = 0; var status = proxyAccount.GetAccountInfo(accountId, false, out account); if (status != RequestStatus.OK || account == null) { Logger.ErrorFormat("IsEnterEnabled - не удалось получить счет ({0})", accountId); return(false); } var curPrices = quoteStorage.ReceiveAllData(); decimal reservedMargin, exposure; var accountExposure = profitCalculator.CalculateAccountExposure( accountId, out equity, out reservedMargin, out exposure, curPrices, proxyAccount, getAccountGroup); account.Equity = equity; // посчитать маржу с учетом новой позы var smbExp = accountExposure.ContainsKey(symbol) ? accountExposure[symbol] : 0; var smbExpNew = Math.Abs(smbExp + side * volume); smbExp = Math.Abs(smbExp); if (smbExpNew <= smbExp) // новая поза не увеличивает экспозицию { return(true); } // посчитать новую экспозицию var deltaExp = (smbExpNew - smbExp); // перевести в валюту депо string errorStr; var deltaExpDepo = DalSpot.Instance.ConvertToTargetCurrency(symbol, true, account.Currency, (double)deltaExp, curPrices, out errorStr, false); if (!deltaExpDepo.HasValue) { Logger.ErrorFormat("IsEnterEnabled - не удалось конвертировать базовую {0} в депо {1}", symbol, account.Currency); return(false); } var newExp = deltaExpDepo.Value + exposure; // проверить маржинальные требования var group = getAccountGroup(account.ID); var deltaMargin = deltaExp / (decimal)group.BrokerLeverage; var newMargin = deltaMargin + reservedMargin; var margPercent = equity == 0 ? 100 : 100 * newMargin / equity; if (margPercent >= (decimal)group.MarginCallPercentLevel) { Logger.InfoFormat("Счет {0}: запрос на {1} {2} {3} превышает марж. требования ({4:f2} из {5:f2})", accountId, side > 0 ? "BUY" : "SELL", volume, symbol, margPercent, group.MarginCallPercentLevel); Logger.InfoFormat("{0:f1} {1:f1} {2:f1} {3:f1} {4:f1} {5} {6:f1} {7:f1}", smbExp, smbExpNew, deltaExp, exposure, equity, accountExposure.Count, deltaMargin, account.Balance); return(false); } // окончательно - проверить макс. плечо if (equity == 0 || account.MaxLeverage == 0) { return(true); } var newLeverage = newExp / equity; if (newLeverage < (decimal)account.MaxLeverage) { return(true); } Logger.InfoFormat("Превышение плеча ({0} при допустимом {1})", newLeverage, account.MaxLeverage); return(false); }
/// <summary> /// проверить маржин колл - стопаут /// </summary> private void CheckMargin() { if (!WorkingDay.Instance.IsWorkingDay(DateTime.Now)) { return; } var curPrices = QuoteStorage.Instance.ReceiveAllData(); try { using (var ctx = DatabaseContext.Instance.Make()) { foreach (var group in ctx.ACCOUNT_GROUP) { // проверка каждого счета foreach (var account in group.ACCOUNT) { decimal reservedMargin, equity; try { decimal exposure; profitCalculator.CalculateAccountExposure(account.ID, out equity, out reservedMargin, out exposure, curPrices, ManagerAccount.Instance, accountRepository.GetAccountGroup); } catch (Exception ex) { loggerNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMagicExposureCheck, 60 * 1000, "Ошибка при расчете маржи/средств счета {0}: {1}", account.ID, ex); break; } // посчитать отношение reservedMargin / equity, % var expLevel = equity == 0 ? 0 : (equity < 0 && reservedMargin != 0) ? 100 : 100 * reservedMargin / equity; var isMc = expLevel >= group.MarginCallPercentLevel; var isSo = expLevel >= group.StopoutPercentLevel; // стопаут! if (isSo) { if (ShouldLogStopout(account.ID)) { Logger.InfoFormat("Стопаут для счета {0}: нач. маржа={1:f0}, средства={2:f0}, предел={3:f1}%", account.ID, reservedMargin, equity, group.StopoutPercentLevel); } PerformStopout(account, curPrices, ctx); continue; } if (!isMc) { continue; } loggerNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMagicMarginCall, 30 * 60 * 1000, "МК для счета {0}: нач. маржа={1:f0}, средства={2:f0}, предел={3:f1}%", account.ID, reservedMargin, equity, group.MarginCallPercentLevel); PerformMarginCall(account); //continue; } } } } catch (Exception ex) { Logger.Error("Ошибка в CheckMargin", ex); } }