示例#1
0
        public static int GetNewOrderVolume(TradeSignalActionTrade action,
                                            TradeSharpConnection ctx, SUBSCRIPTION_SIGNAL tradeSets)
        {
            // получить ордера по счету, посчитать актуальный баланс (средства) счета
            try
            {
                var account = ctx.ACCOUNT.FirstOrDefault(a => a.ID == tradeSets.TargetAccount.Value);
                if (account == null)
                {
                    Logger.ErrorFormat("Ошибка при расчете объема по счету {0}, ордер {1}: счет не найден",
                                       tradeSets.TargetAccount, action.OrderId);
                    return(0);
                }

                var equity = (double)account.Balance;

                // ордера
                var orders = ctx.POSITION.Where(p => p.AccountID == tradeSets.TargetAccount &&
                                                p.State == (int)PositionState.Opened).ToList().Select(o => LinqToEntity.DecorateOrder(o)).ToList();

                // проверить - нет ли противоположного ордера?
                var quotes = Contract.Util.BL.QuoteStorage.Instance.ReceiveAllData();

                if (orders.Count > 0)
                {
                    if (!(tradeSets.HedgingOrdersEnabled ?? false))
                    {
                        var hasOrdersCounter = orders.Any(p => p.Symbol == action.Ticker && p.Side != action.Side);
                        if (hasOrdersCounter)
                        {
                            logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Info, LogMsgContraOrders,
                                                                  1000 * 60 * 90, "Ордер {0} {1}, счет {2} - есть встречные ордера",
                                                                  action.Side > 0 ? "BUY" : "SELL", action.Ticker, tradeSets.TargetAccount);
                            return(0);
                        }
                    }

                    // посчитать профит по позам
                    bool noQuoteError;
                    var  openResult = DalSpot.Instance.CalculateOpenedPositionsCurrentResult(
                        orders, quotes, account.Currency, out noQuoteError);
                    if (noQuoteError)
                    {
                        logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgVolmCalcNoQuote,
                                                              1000 * 60 * 90, "GetNewOrderVolume - нет котировки");
                        return(0);
                    }
                    equity += openResult;
                }

                if (equity <= 0)
                {
                    logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgEquityIsNil,
                                                          1000 * 60 * 90, "Баланс счета {0}: {1}", account.ID, equity);
                    return(0);
                }

                // посчитать объем
                var volumeDepo = (tradeSets.PercentLeverage ?? 100) / 100f * equity * (double)action.Leverage;
                // пересчитать объем в базовую валюту
                string errorStr;
                var    volumeBase = DalSpot.Instance.ConvertToTargetCurrency(action.Ticker, true, account.Currency, volumeDepo,
                                                                             quotes, out errorStr);
                if (!volumeBase.HasValue)
                {
                    logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgVolmToBase,
                                                          1000 * 60 * 90, "GetNewOrderVolume - невозможно посчитать объем по сделке {0}, валюта счета {1}: {2}",
                                                          action.Ticker, account.Currency, errorStr);
                    return(0);
                }

                // округлить объем
                var volume = MarketOrder.RoundDealVolume((int)volumeBase,
                                                         (VolumeRoundType)(tradeSets.VolumeRound ?? (int)VolumeRoundType.Ближайшее),
                                                         tradeSets.MinVolume ?? 10000, tradeSets.StepVolume ?? 10000);
                if (volume == 0)
                {
                    var msg = string.Format("Полученный объем входа ({0}) округлен до 0", (int)volumeBase);
                    logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error,
                                                          LogMsgVolmRoundToZero, 1000 * 60 * 90, msg);
                    return(0);
                }

                // проверить на превышение плеча
                if ((tradeSets.MaxLeverage ?? 0) > 0)
                {
                    var totalExposure     = 0M;
                    var ordersBySignaller = orders.Where(position =>
                    {
                        int orderSignalCatId, parentDealId;
                        if (MarketOrder.GetTradeSignalFromDeal(position, out orderSignalCatId, out parentDealId))
                        {
                            return(orderSignalCatId == action.ServiceId);
                        }
                        return(false);
                    }).GroupBy(o => o.Symbol).ToDictionary(o => o.Key, o => o.ToList());

                    foreach (var orderByTicker in ordersBySignaller)
                    {
                        // суммарная экспозиция
                        var exp = orderByTicker.Value.Sum(o => o.Side * o.Volume);
                        if (orderByTicker.Key == action.Ticker)
                        {
                            exp += action.Side * volume;
                        }
                        if (exp == 0)
                        {
                            continue;
                        }

                        // перевести экспозицию в валюту депозита
                        var expBase = DalSpot.Instance.ConvertToTargetCurrency(action.Ticker, true, account.Currency,
                                                                               volumeDepo,
                                                                               quotes, out errorStr);
                        if (!expBase.HasValue)
                        {
                            logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgExposureNoQuote,
                                                                  1000 * 60 * 90,
                                                                  "GetNewOrderVolume - невозможно посчитать экспозицию по сделке " +
                                                                  "{0}, тикер {1}: {2}",
                                                                  action.Ticker, orderByTicker.Key, errorStr);
                            return(0);
                        }

                        totalExposure += Math.Abs(expBase.Value);
                    }
                    var totalLeverage = (double)totalExposure / equity;
                    // ReSharper disable PossibleInvalidOperationException
                    if (totalLeverage > tradeSets.MaxLeverage.Value)
                    // ReSharper restore PossibleInvalidOperationException
                    {
                        logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgMaxLevExceeded,
                                                              1000 * 60 * 90,
                                                              "GetNewOrderVolume - макс плечо ({0}) превышено, " +
                                                              "тикер {1}: плечо составит {2}",
                                                              tradeSets.MaxLeverage.Value,
                                                              action.Ticker, totalLeverage);
                        return(0);
                    }
                }

                return(volume);
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("Ошибка при расчете объема по счету {0}, ордер {1}: {2}",
                                   tradeSets.TargetAccount, action.OrderId, ex);
            }

            return(0);
        }
        private static void GetClosedDealsResult(
            float balance, string depoCurx,
            Dictionary <string, QuoteData> quotes,
            Dictionary <int, TradeSignalProfit> signalResult)
        {
            List <MarketOrder> orders;

            try
            {
                var status = TradeSharpAccount.Instance.proxy.GetHistoryOrders(AccountStatus.Instance.accountID, null, out orders);
                if (status != RequestStatus.OK)
                {
                    Logger.ErrorFormat("SignalProfitReport - не удалось получить закрытые сделки ({0})", status);
                    return;
                }
            }
            catch (Exception ex)
            {
                Logger.Error("SignalProfitReport - не удалось получить закрытые сделки:", ex);
                return;
            }
            foreach (var order in orders)
            {
                int signalCatId, parentDealId;
                if (!MarketOrder.GetTradeSignalFromDeal(order, out signalCatId, out parentDealId))
                {
                    continue;
                }

                TradeSignalProfit result;
                signalResult.TryGetValue(signalCatId, out result);
                if (result == null)
                {
                    result = new TradeSignalProfit();
                    signalResult.Add(signalCatId, result);
                }
                result.closedDeals.Add(order);
            }

            // суммарные позы
            foreach (var result in signalResult.Values)
            {
                // список суммарных поз по каждому тикеру - EURUSD, ...
                if (result.closedDeals.Count == 0)
                {
                    continue;
                }
                var sumPos = PositionSummary.GetPositionSummary(quotes, result.closedDeals, depoCurx, balance);
                result.closedDeals.Clear();

                foreach (var pos in sumPos)
                {
                    pos.Command = MakeDealsCountString(pos.orders.Count);
                    if (string.IsNullOrEmpty(pos.Symbol))
                    {
                        continue;
                    }

                    result.closedDeals.Add(new MarketOrder
                    {
                        Side         = pos.Side,
                        Symbol       = pos.Symbol,
                        Volume       = pos.Volume,
                        Comment      = pos.Command,
                        ResultPoints = pos.ProfitInPoints,
                        ResultDepo   = pos.Profit,
                        ResultBase   = pos.ProfitInPercent
                    });
                }
                // суммарная поза
                var totalPos = sumPos.First(p => string.IsNullOrEmpty(p.Symbol));
                sumPos.Remove(totalPos);
                result.totalClosedDealsCount = sumPos.Sum(p => p.orders.Count);
                result.totalClosedResult     = sumPos.Sum(p => p.Profit);
                result.totalClosedVolume     = totalPos.Volume;
            }
        }
示例#3
0
        private void RenderAccountPositions(StringBuilder sb, int accountId)
        {
            List <MarketOrder> orders;
            var accountInfo = GetAccountInfoFromServer(accountId, out orders);

            if (accountInfo == null)
            {
                return;
            }

            var tradeSignalRequestScript = RenderAjaxSignalDetailQuery(sb);

            // краткая сводка по счету
            sb.AppendLine("      <h3>Счет " + accountId + "</h3>");
            sb.AppendLine("      <p>");
            var ptrVal = new Dictionary <string, string>
            {
                { "Баланс",
                  accountInfo.Equity.ToStringUniformMoneyFormat() + " " + accountInfo.Currency },
                { "Текущая прибыль/убыток",
                  (accountInfo.Equity - accountInfo.Balance).ToStringUniformMoneyFormat() + " " + accountInfo.Currency },
                { "Группа", accountInfo.Group }
            };

            foreach (var pair in ptrVal)
            {
                sb.AppendLine("        " + pair.Key + ": " + pair.Value + "<br/>");
            }
            sb.AppendLine("      </p>");

            // рендерить таблицу открытых позиций
            RenderTableOpenTag(sb);
            RenderTableRowTag(sb, true);
            sb.AppendLine("        <td>№</td><td>Тип</td><td>Объем</td><td>Инстр.</td>" +
                          "<td>Цена</td><td>Время</td><td>Выход</td><td>Результат</td><td>SL</td><td>TP</td><td>Сиг.</td></tr>");

            var evenRow         = false;
            var colorSchemeText = new Dictionary <Cortege2 <bool, bool>, string>
            {
                { new Cortege2 <bool, bool>(true, true), "Black" },   // even - profit
                { new Cortege2 <bool, bool>(false, true), "Black" },  // odd - profit
                { new Cortege2 <bool, bool>(false, false), "Black" }, // odd - loss
                { new Cortege2 <bool, bool>(true, false), "#860000" }  // even - loss
            };
            var colorSchemeBack = new Dictionary <Cortege2 <bool, bool>, string>
            {
                { new Cortege2 <bool, bool>(true, true), "White" },    // even - profit
                { new Cortege2 <bool, bool>(false, true), "#E0E0E0" }, // odd - profit
                { new Cortege2 <bool, bool>(false, false), "FFD6D6" }, // odd - loss
                { new Cortege2 <bool, bool>(true, false), "#White" }  // even - loss
            };

            foreach (var order in orders)
            {
                evenRow = !evenRow;
                var colorText = colorSchemeText[new Cortege2 <bool, bool>(evenRow, order.ResultDepo >= 0)];
                var colorBack = colorSchemeBack[new Cortege2 <bool, bool>(evenRow, order.ResultDepo >= 0)];

                sb.AppendLine(string.Format("        <tr style=\"color:{0}; background-color:{1}\">",
                                            colorText, colorBack));

                int signalCat, parentDeal;
                var signalString = "";
                if (MarketOrder.GetTradeSignalFromDeal(order, out signalCat, out parentDeal))
                {
                    signalString = string.Format("<a href=\"#\" onclick=\"{0}({1})\">[{1}]</a>",
                                                 tradeSignalRequestScript, signalCat);
                }

                sb.AppendLine(string.Format("        <td>{0}</td><td>{1}</td><td>{2}</td>" +
                                            "<td>{3}</td><td>{4}</td><td>{5:dd.MM.yyyy HH:mm:ss}</td><td>{6}</td><td>{7}</td><td>{8}</td><td>{9}</td><td>{10}</td></tr>",
                                            order.ID, order.Side > 0 ? "BUY" : "SELL", order.Volume.ToStringUniformMoneyFormat(),
                                            order.Symbol, order.PriceEnter.ToStringUniformMoneyFormat(),
                                            order.TimeEnter, (order.PriceExit ?? 0).ToStringUniformPriceFormat(),
                                            order.ResultDepo.ToStringUniformMoneyFormat(),
                                            order.StopLoss.HasValue ? order.StopLoss.Value.ToStringUniformPriceFormat() : " ",
                                            order.TakeProfit.HasValue ? order.TakeProfit.Value.ToStringUniformPriceFormat() : " ",
                                            signalString));
            }
        }
        private static Dictionary <int, TradeSignalProfit> GetOpenDealsResult(
            float balance, string depoCurx, Dictionary <string, QuoteData> quotes)
        {
            var signalResult = new Dictionary <int, TradeSignalProfit>();
            // получить открытые сделки
            var orders = MarketOrdersStorage.Instance.MarketOrders;

            foreach (var order in orders)
            {
                int signalCatId, parentDealId;
                if (!MarketOrder.GetTradeSignalFromDeal(order, out signalCatId, out parentDealId))
                {
                    continue;
                }

                TradeSignalProfit result;
                signalResult.TryGetValue(signalCatId, out result);
                if (result == null)
                {
                    result = new TradeSignalProfit();
                    signalResult.Add(signalCatId, result);
                }
                result.openDeals.Add(order);
            }
            if (signalResult.Count == 0)
            {
                return(signalResult);
            }

            // агрегировать открытые сделки - суммарные позы по ордерам
            foreach (var result in signalResult.Values)
            {
                // список суммарных поз по каждому тикеру - EURUSD, ...
                if (result.openDeals.Count == 0)
                {
                    continue;
                }
                var sumPos = PositionSummary.GetPositionSummary(quotes, result.openDeals, depoCurx, balance);
                result.openDeals.Clear();

                foreach (var pos in sumPos)
                {
                    pos.Command = MakeDealsCountString(pos.orders.Count);
                    if (string.IsNullOrEmpty(pos.Symbol))
                    {
                        continue;
                    }

                    result.openDeals.Add(new MarketOrder
                    {
                        Side         = pos.Side,
                        Symbol       = pos.Symbol,
                        Volume       = pos.Volume,
                        Comment      = pos.Command,
                        PriceEnter   = pos.AveragePrice,
                        ResultPoints = pos.ProfitInPoints,
                        ResultDepo   = pos.Profit,
                        ResultBase   = pos.ProfitInPercent
                    });
                }
                // суммарная поза
                var totalPos = sumPos.First(p => string.IsNullOrEmpty(p.Symbol));
                sumPos.Remove(totalPos);

                result.totalOpenPosCount      = sumPos.Sum(p => p.orders.Count);
                result.totalOpenResultDepo    = sumPos.Sum(p => p.Profit);
                result.totalOpenResultPercent = 100 * result.totalOpenResultDepo / balance;
                result.totalVolumeOpenDepo    = totalPos.Volume;
            }

            return(signalResult);
        }
        /// <summary>
        /// таки запросить ордера
        /// </summary>
        private void CheckOrders()
        {
            Dictionary <int, List <MarketOrder> > orderDic;

            // получить ордера
            try
            {
                if (!AccountStatus.Instance.isAuthorized)
                {
                    return;
                }
                var acId = AccountStatus.Instance.accountID;
                dealsRequestInProcess = true;
                try
                {
                    orderDic = TradeSharpAccount.Instance.proxy.GetSignallersOpenTrades(acId);
                }
                finally
                {
                    dealsRequestInProcess = false;
                }
                if (orderDic == null || orderDic.Count == 0)
                {
                    return;
                }
            }
            catch (Exception ex)
            {
                Logger.Error("TradeSignalMonitorStream.CheckOrders() - ошибка получения ордеров", ex);
                return;
            }

            if (isStopping)
            {
                return;
            }
            // сравнить ордера с открытыми ордерами по счету - найти "лишние" открытые
            var dealsToClose = new List <MarketOrder>();

            try
            {
                var orders = MarketOrdersStorage.Instance.MarketOrders;
                if (orders == null || orders.Count == 0)
                {
                    return;
                }
                // найти в списке "лишние" ордера
                foreach (var order in orders)
                {
                    int serviceId, parentDealId;
                    if (!MarketOrder.GetTradeSignalFromDeal(order, out serviceId, out parentDealId))
                    {
                        continue;
                    }

                    // найти для данного ордера "родительский" ордер
                    List <MarketOrder> parentOrders;
                    orderDic.TryGetValue(serviceId, out parentOrders);
                    if (parentOrders == null)
                    {
                        continue;                       // возможно, на данныю категорию более не подписаны
                    }
                    if (!parentOrders.Any(o => o.ID == parentDealId))
                    {
                        // у сигнальщика не найдена сделка - попытка закрыть ее
                        if (!spareDealIds.ContainsKey(order.ID))
                        {
                            // сообщить о левой сделке
                            showMessageInUI(DateTime.Now,
                                            string.Format("Сделка {0} ({1} {2} {3}) закрыта у управляющего (сигнал #{4}) - производится закрытие",
                                                          order.ID, order.Side > 0 ? "BUY" : "SELL", order.Volume, order.Symbol,
                                                          serviceId));
                            spareDealIds.Add(order.ID, order.ID);
                        }
                        dealsToClose.Add(order);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error("TradeSignalMonitorStream.CheckOrders() - ошибка сравнения ордеров", ex);
            }

            try
            {
                foreach (var deal in dealsToClose)
                {
                    TryCloseDeal(deal);
                }
            }
            catch (Exception ex)
            {
                Logger.Error("TradeSignalMonitorStream.CheckOrders() - ошибка закрытия сделки", ex);
            }
        }