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); }
protected virtual StatisticalArbitrageOrderInfo GetOpenedOrderWithMaxSpread() { StatisticalArbitrageOrderInfo maxItem = null; //foreach(StatisticalArbitrageOrderInfo item in OpenedOrders) { // if(maxItem == null || maxItem.Spread < item.Spread) // maxItem = item; //} return(maxItem); }
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); }
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); }