public void TestLoad() { // очистить локальный кеш NewsLocalStorage.ReInstantiate(); var fakeNewsServer = MakeFakeNewsServer(); // подготовить тестовые новости NewsStorageProxy.fakeChannel = fakeNewsServer; // "залогиниться" var firstAccountId = fakeNewsServer.channelsByAccount.Keys.First(); Account account; fakeTradeAccount.GetAccountInfo(firstAccountId, true, out account); AccountStatus.Instance.AccountData = account; // запустить актуализацию NewsCache.Instance.ActualizeAsync(); // дождаться завершения... NewsCache.Instance.syncCompletedEvent.Wait(); // содержимое кеша должно соответствовать исходному наполнению CompareStoredAndServerNews(fakeNewsServer, firstAccountId, "NewsStorageProxy first load: all news are loaded"); // дополнить сервер несколькими новостями fakeNewsServer.AddNews(1, new List <News> { NewsMaker.MakeSingleNews(1, DateTime.Now.AddMinutes(-30)), NewsMaker.MakeSingleNews(1, DateTime.Now.AddMinutes(-28)), }); fakeNewsServer.AddNews(3, new List <News> { NewsMaker.MakeSingleNews(3, DateTime.Now.AddMinutes(-21)) }); // запустить актуализацию NewsCache.Instance.ActualizeAsync(); // дождаться завершения... NewsCache.Instance.syncCompletedEvent.Wait(); // содержимое кеша снова должно соответствовать исходному наполнению CompareStoredAndServerNews(fakeNewsServer, firstAccountId, "NewsStorageProxy second load: all news are loaded"); }
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); }
public Dictionary <string, decimal> CalculateAccountExposure(int accountId, out decimal equity, out decimal reservedMargin, out decimal exposure, Dictionary <string, QuoteData> curPrices, ITradeSharpAccount proxyAccount, Func <int, AccountGroup> getAccountGroup) { if (curPrices == null) { Logger.Error("Ошибка в CalculateAccountExposure - curPrices == null"); throw new Exception("Ошибка в CalculateAccountExposure - curPrices == null"); } equity = 0; exposure = 0; reservedMargin = 0; var exps = new Dictionary <string, decimal>(); Account account; proxyAccount.GetAccountInfo(accountId, true, out account); if (account == null) { return(exps); } equity = account.Equity; List <MarketOrder> marketOrders; try { var result = proxyAccount.GetMarketOrders(accountId, out marketOrders); if (result != RequestStatus.OK) { return(exps); } } catch (Exception ex) { Logger.Error("Ошибка в CalculateAccountExposure - GetMarketOrders", ex); throw; } if (marketOrders == null) { Logger.Error("Ошибка в CalculateAccountExposure - posInf == null"); throw new Exception("Ошибка в CalculateAccountExposure - posInf == null"); } foreach (var position in marketOrders) { var volume = position.Volume * position.Side; if (exps.ContainsKey(position.Symbol)) { exps[position.Symbol] += volume; } else { exps.Add(position.Symbol, volume); } } // перевести экспозицию по каждой валюте в валюту депо foreach (var pair in exps) { var deltaExp = pair.Value; try { string errorStr; var deltaExpDepo = DalSpot.Instance.ConvertToTargetCurrency(pair.Key, true, account.Currency, (double)deltaExp, curPrices, out errorStr, true); if (deltaExpDepo.HasValue) { exposure += Math.Abs(deltaExpDepo.Value); } } catch (Exception ex) { Logger.Error("Ошибка в CalculateAccountExposure - ConvertBase2Depo", ex); throw; } } // марж. требования try { var accountGroup = getAccountGroup(accountId); reservedMargin = exposure / (decimal)accountGroup.BrokerLeverage; } catch (Exception ex) { Logger.Error("Ошибка в CalculateAccountExposure - getAccountGroup", ex); throw; } return(exps); }
public Dictionary<string, decimal> CalculateAccountExposure(int accountId, out decimal equity, out decimal reservedMargin, out decimal exposure, Dictionary<string, QuoteData> curPrices, ITradeSharpAccount proxyAccount, Func<int, AccountGroup> getAccountGroup) { if (curPrices == null) { Logger.Error("Ошибка в CalculateAccountExposure - curPrices == null"); throw new Exception("Ошибка в CalculateAccountExposure - curPrices == null"); } equity = 0; exposure = 0; reservedMargin = 0; var exps = new Dictionary<string, decimal>(); Account account; proxyAccount.GetAccountInfo(accountId, true, out account); if (account == null) return exps; equity = account.Equity; List<MarketOrder> marketOrders; try { var result = proxyAccount.GetMarketOrders(accountId, out marketOrders); if (result != RequestStatus.OK) return exps; } catch (Exception ex) { Logger.Error("Ошибка в CalculateAccountExposure - GetMarketOrders", ex); throw; } if (marketOrders == null) { Logger.Error("Ошибка в CalculateAccountExposure - posInf == null"); throw new Exception("Ошибка в CalculateAccountExposure - posInf == null"); } foreach (var position in marketOrders) { var volume = position.Volume * position.Side; if (exps.ContainsKey(position.Symbol)) exps[position.Symbol] += volume; else exps.Add(position.Symbol, volume); } // перевести экспозицию по каждой валюте в валюту депо foreach (var pair in exps) { var deltaExp = pair.Value; try { string errorStr; var deltaExpDepo = DalSpot.Instance.ConvertToTargetCurrency(pair.Key, true, account.Currency, (double)deltaExp, curPrices, out errorStr, true); if (deltaExpDepo.HasValue) exposure += Math.Abs(deltaExpDepo.Value); } catch (Exception ex) { Logger.Error("Ошибка в CalculateAccountExposure - ConvertBase2Depo", ex); throw; } } // марж. требования try { var accountGroup = getAccountGroup(accountId); reservedMargin = exposure / (decimal)accountGroup.BrokerLeverage; } catch (Exception ex) { Logger.Error("Ошибка в CalculateAccountExposure - getAccountGroup", ex); throw; } return exps; }