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); }
private double CalculateRequiredShortAmount(double buyAmount, double spread) { return((buyAmount * Long.HighestBidInBaseCurrency() + spread * buyAmount) / Short.LowestAskInBaseCurrency()); }
private double CalculateRequiredLongAmount(double sellAmount, double spread) { return(sellAmount * Short.LowestAskInBaseCurrency() / (Long.HighestBidInBaseCurrency() + spread)); }
private double CalculateLongBuyAmountByBaseAmount(double baseAmount) { return(baseAmount / Long.HighestBidInBaseCurrency()); }
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); }