Exemplo n.º 1
0
        private bool TryOpenMoreDeals(double bottomAsk, double topBid, double spreadToOpen)
        {
            int zoneIndex = OrderGrid.GetZoneIndex(spreadToOpen);

            if (zoneIndex == -1)
            {
                return(false);
            }
            double baseAmount = GetRemainAmountForZoneInBaseCurrency(zoneIndex);

            if (baseAmount == 0)
            {
                return(false);
            }

            double buyAmount                = CalculateLongBuyAmountByBaseAmount(baseAmount);
            double actualBuyAmount          = GetActualBottomAskAmount(bottomAsk);
            double finalBuyAmount           = Math.Min(buyAmount, actualBuyAmount);
            double requiredShortSellAmount  = CalculateRequiredShortAmount(finalBuyAmount, spreadToOpen);
            double availableShortSellAmount = GetActualShortBidAmount(topBid);
            double finalSellAmount          = Math.Min(requiredShortSellAmount, availableShortSellAmount);

            if (finalSellAmount < requiredShortSellAmount)
            {
                finalSellAmount = availableShortSellAmount;
                finalBuyAmount  = CalculateRequiredLongAmount(finalSellAmount, spreadToOpen);
            }

            MarketBuy(Long, bottomAsk, finalBuyAmount);
            MarketSell(Short, topBid, finalSellAmount);

            var order = new StatisticalArbitrageOrderInfo()
            {
                LongAmount       = finalBuyAmount,
                LongValue        = bottomAsk,
                ShortAmount      = finalSellAmount,
                ShortTotalAmount = finalSellAmount,
                ShortValue       = topBid,
                ZoneIndex        = zoneIndex,
                SpentDeposit     = Long.HighestBidInBaseCurrency() * finalBuyAmount,
                Spread           = spreadToOpen
            };

            LastItem             = new StatisticalArbitrageHistoryItem();
            LastItem.Time        = DateTime.UtcNow;
            LastItem.Earned      = Earned;
            LastItem.LongPrice   = bottomAsk;
            LastItem.ShortPrice  = topBid;
            LastItem.LongAmount  = finalBuyAmount;
            LastItem.ShortAmount = finalSellAmount;
            LastItem.Open        = true;
            StrategyData.Add(LastItem);

            //OpenedOrders.Add(order);
            OnOrderOpened(LastItem);

            return(true);
        }
Exemplo n.º 2
0
        private void OnOrderOpened(StatisticalArbitrageHistoryItem lastItem)
        {
            string text = string.Empty;

            text += "<b>" + Name + "</b> open order:";
            text += "<pre> buy:       " + lastItem.LongPrice.ToString("0.########") + " am = " + lastItem.LongAmount.ToString("0.########") + "</pre>";
            text += "<pre> sell:      " + lastItem.ShortPrice.ToString("0.########") + " am = " + lastItem.ShortAmount.ToString("0.########") + "</pre>";

            TelegramBot.Default.SendNotification(text, ChatId);
            LogManager.Default.Add(LogType.Success, this, null, "open order",
                                   "buy " + lastItem.LongPrice.ToString("0.########") + " am = " + lastItem.LongAmount.ToString("0.########") +
                                   "    sell" + lastItem.ShortPrice.ToString("0.########") + " am = " + lastItem.ShortAmount.ToString("0.########"));
        }
Exemplo n.º 3
0
        private bool TryCloseDeals(double bottomBid, double topAsk, double spreadToClose)
        {
            if (spreadToClose > CloseSpread)
            {
                return(false);
            }
            if (OpenedOrders.Count == 0)
            {
                return(false);
            }

            StatisticalArbitrageOrderInfo order = GetOpenedOrderWithMaxSpread();
            double actualSellAmount             = GetActualBottomBidAmount(bottomBid);
            double finalSellAmount = Math.Min(actualSellAmount, order.LongAmount);
            double koeffSell       = finalSellAmount / order.LongAmount;

            double actualBuyAmount = GetActualShortAskAmount(topAsk);
            double finalBuyAmount  = Math.Min(actualBuyAmount, order.ShortAmount);
            double koeffBuy        = finalBuyAmount / order.ShortAmount;
            double koeff           = Math.Min(koeffBuy, koeffSell);

            finalSellAmount *= koeff;
            finalBuyAmount  *= koeff;


            MarketSell(Long, bottomBid, finalSellAmount);
            MarketBuy(Short, topAsk, finalBuyAmount);

            order.LongAmount  -= finalSellAmount;
            order.ShortAmount -= finalBuyAmount;
            double eInc = (1 / order.LongValue - 1 / order.ShortValue) * finalBuyAmount;

            Earned += eInc;

            LastItem             = new StatisticalArbitrageHistoryItem();
            LastItem.Time        = DateTime.UtcNow;
            LastItem.Earned      = Earned;
            LastItem.LongAmount  = finalSellAmount;
            LastItem.LongPrice   = bottomBid;
            LastItem.ShortPrice  = topAsk;
            LastItem.ShortAmount = finalBuyAmount;
            LastItem.Close       = true;
            StrategyData.Add(LastItem);

            //if(order.LongAmount <= 0 && order.ShortAmount <= 0)
            //    OpenedOrders.Remove(order);
            OnOrderClosed(LastItem);

            return(true);
        }
        protected override void OnTickCore()
        {
            base.OnTickCore();

            double bottomAsk = 0;
            double topBid    = 0;
            double bottomBid = 0;
            double topAsk    = 0;

            if (Long.OrderBookStatus != TickerDataStatus.Actual || Short.OrderBookStatus != TickerDataStatus.Actual)
            {
                string longOb  = Long.OrderBookStatus == TickerDataStatus.Actual ? "green" : "red";
                string shortOb = Short.OrderBookStatus == TickerDataStatus.Actual ? "green" : "red";
                StateTextCore = "<b><color=" + longOb + ">long order book status = " + Long.OrderBookStatus + "</color>    <color=" + shortOb + ">short order book status = " + Short.OrderBookStatus + "</b>";
                return;
            }

            bottomAsk = Long.OrderBook.LowestAsk;
            topBid    = Short.OrderBook.HighestBid;
            bottomBid = Long.OrderBook.HighestBid;
            topAsk    = Short.OrderBook.LowestAsk;

            double spreadToOpen  = topBid - bottomAsk;
            double spreadToClose = topAsk - bottomBid;

            if (LastItem == null || LastItem.LongAsk != bottomAsk || LastItem.ShortBid != topBid)
            {
                LastItem          = new StatisticalArbitrageHistoryItem();
                LastItem.Time     = DataProvider.CurrentTime;
                LastItem.LongAsk  = bottomAsk;
                LastItem.LongBid  = bottomBid;
                LastItem.ShortBid = topBid;
                LastItem.ShortAsk = topAsk;
                LastItem.Earned   = Earned;
                LastItem.Index    = StrategyData.Count;
                StrategyData.Add(LastItem);
                StateTextCore = "<b><color=green>long=" + LastItem.LongAsk.ToString("0.########") + "</color> <color=red> short=" + LastItem.ShortBid.ToString("0.########") + "</color>  spread = " + LastItem.OpenSpread.ToString("0.00000000") + "  order count = " + OpenedOrders.Count + "</b>";
            }

            if (TryOpenMoreDeals(bottomAsk, topBid, spreadToOpen))
            {
            }
            else if (TryCloseDeals(bottomBid, topAsk, spreadToClose))
            {
            }
        }
        private bool TryOpenMoreDeals(double bottomAsk, double topBid, double spreadToOpen)
        {
            if (spreadToOpen < SpreadOpenPosition)
            {
                return(false);
            }

            //int zoneIndex = OrderGrid.GetZoneIndex(spreadToOpen);
            //if(zoneIndex == -1)
            //    return false;
            //double baseAmount = GetRemainAmountForZoneInBaseCurrency(zoneIndex);
            //if(baseAmount == 0)
            //    return false;

            double baseAmount               = MaxAllowedDeposit * 0.9;
            double buyAmount                = CalculateLongBuyAmountByBaseAmount(baseAmount);
            double actualBuyAmount          = GetActualBottomAskAmount(bottomAsk);
            double finalBuyAmount           = Math.Min(buyAmount, actualBuyAmount);
            double requiredShortSellAmount  = CalculateRequiredShortAmount(finalBuyAmount, spreadToOpen);
            double availableShortSellAmount = GetActualShortBidAmount(topBid);
            double finalSellAmount          = Math.Min(requiredShortSellAmount, availableShortSellAmount);

            if (finalSellAmount < requiredShortSellAmount)
            {
                finalSellAmount = availableShortSellAmount;
                finalBuyAmount  = CalculateRequiredLongAmount(finalSellAmount, spreadToOpen);
            }

            if (finalBuyAmount == 0 || finalSellAmount == 0 || finalBuyAmount * bottomAsk < MinDepositForOpenPosition)
            {
                return(false);
            }

            var order = new StatisticalArbitrageOrderInfo()
            {
                ShortValue   = topBid,
                SpentDeposit = Long.HighestBidInBaseCurrency() * finalBuyAmount,
                Spread       = spreadToOpen
            };

            if (Long.SpentInBaseCurrency(bottomAsk, finalBuyAmount) * 1.05 > MaxAllowedDeposit)
            {
                LogManager.Default.Add(LogType.Error, this, Name, "not enough deposit for open long position", "spent = " + Long.SpentInBaseCurrency(bottomAsk, finalBuyAmount) + " in " + Long.BaseCurrency + "; deposit = " + MaxAllowedDeposit);
                return(false);
            }

            if (Short.SpentInBaseCurrency(topBid, finalSellAmount) * 1.05 > GetMaxAllowedShortDeposit())
            {
                LogManager.Default.Add(LogType.Error, this, Name, "not enough deposit for open long position", "spent = " + Short.SpentInBaseCurrency(topBid, finalSellAmount) + " in " + Short.BaseCurrency + "; deposit = " + GetMaxAllowedShortDeposit());
                return(false);
            }

            OpenedPairs.Add(order);
            OpenPositionInfo lp = OpenLongPosition(Long, "OL", bottomAsk, finalBuyAmount, 1000);

            if (lp == null)
            {
                OpenedPairs.Remove(order);
                LogManager.Default.Add(LogType.Error, this, Name, "failed open long position", "price = " + bottomAsk + "; amount = " + finalBuyAmount + "; spent = " + Long.SpentInBaseCurrency(bottomAsk, finalBuyAmount) + " in " + Long.BaseCurrency);
                return(false);
            }

            OpenPositionInfo sp = OpenShortPosition(Short, "OS", topBid, finalSellAmount, 1000);

            if (sp == null)
            {
                OpenedPairs.Remove(order);
                LogManager.Default.Add(LogType.Error, this, Name, "failed open short position", "price = " + topBid + "; amount = " + finalSellAmount + "; spent = " + Short.SpentInBaseCurrency(topBid, finalSellAmount));
                return(false);
            }

            order.LongPosition     = lp;
            order.ShortPosition    = sp;
            order.LongAmount       = lp.OpenAmount;
            order.LongValue        = lp.OpenValue;
            order.ShortAmount      = sp.OpenAmount;
            order.ShortTotalAmount = sp.OpenValue;

            LastItem = new StatisticalArbitrageHistoryItem();
            LastItem.OpenedPositions.Add(order.LongPosition);
            LastItem.OpenedPositions.Add(order.ShortPosition);
            LastItem.Time        = DataProvider.CurrentTime;
            LastItem.Earned      = Earned;
            LastItem.LongBid     = Long.OrderBook.HighestBid;
            LastItem.LongAsk     = bottomAsk;
            LastItem.ShortBid    = topBid;
            LastItem.ShortAsk    = Short.OrderBook.LowestAsk;
            LastItem.LongAmount  = finalBuyAmount;
            LastItem.ShortAmount = finalSellAmount;
            LastItem.Open        = true;
            LastItem.Index       = StrategyData.Count;
            LastItem.Mark        = "OPEN";
            StrategyData.Add(LastItem);

            //OpenedOrders.Add(order);
            OnOrderOpened(LastItem);

            return(true);
        }
        private bool TryCloseDeals(double bottomBid, double topAsk, double spreadToClose)
        {
            if (spreadToClose > SpreadClosePosition)
            {
                return(false);
            }
            if (OpenedOrders.Count == 0)
            {
                return(false);
            }

            //StatisticalArbitrageOrderInfo order = GetOpenedOrderWithMaxSpread();
            foreach (StatisticalArbitrageOrderInfo order in OpenedPairs)
            {
                if (order.Spread < SpreadClosePosition)
                {
                    continue;
                }

                double actualLongCloseBid  = Long.GetActualBidByAmount(order.LongAmount);
                double actualShortCloseAsk = Short.GetActualAskByAmount(order.ShortAmount);

                double spread = actualShortCloseAsk - actualLongCloseBid;
                if (spread > SpreadClosePosition)
                {
                    continue;
                }

                double actualSellAmount = GetActualBottomBidAmount(actualLongCloseBid);
                double actualBuyAmount  = GetActualShortAskAmount(actualShortCloseAsk);

                double finalSellAmount = Math.Min(actualSellAmount, order.LongAmount);
                double koeffSell       = finalSellAmount / order.LongAmount;

                double finalBuyAmount = Math.Min(actualBuyAmount, order.ShortAmount);
                double koeffBuy       = finalBuyAmount / order.ShortAmount;
                double koeff          = Math.Min(koeffBuy, koeffSell);
                finalSellAmount *= koeff;
                finalBuyAmount  *= koeff;

                TradingResult closeLong  = MarketSell(Long, bottomBid, finalSellAmount);
                TradingResult closeShort = MarketBuy(Short, topAsk, finalBuyAmount);


                order.LongAmount  -= closeLong.Amount;
                order.ShortAmount -= closeShort.Amount;

                //double eInc = (1 / order.LongValue - 1 / order.ShortValue) * finalBuyAmount;
                //Earned += eInc;

                LastItem             = new StatisticalArbitrageHistoryItem();
                LastItem.Time        = DataProvider.CurrentTime;
                LastItem.Earned      = Earned;
                LastItem.LongAmount  = finalSellAmount;
                LastItem.LongAsk     = Long.OrderBook.LowestAsk;
                LastItem.LongBid     = bottomBid;
                LastItem.ShortAsk    = topAsk;
                LastItem.ShortBid    = Short.OrderBook.HighestBid;
                LastItem.ShortAmount = finalBuyAmount;
                LastItem.Close       = true;
                LastItem.Index       = StrategyData.Count;
                LastItem.Mark        = "CLOSE";
                LastItem.ClosedPositions.Add(order.LongPosition);
                LastItem.ClosedPositions.Add(order.ShortPosition);
                StrategyData.Add(LastItem);

                CloseLongPosition(order.LongPosition, closeLong);
                CloseShortPosition(order.ShortPosition, closeShort);

                if (order.LongAmount <= 0 && order.ShortAmount <= 0)
                {
                    OpenedPairs.Remove(order);
                    OnOrderClosed(LastItem);
                }
                else
                {
                    throw new Exception("Partial Close Not Implemented");
                }
            }

            return(true);
        }