public async Task <Unit> UpdateOrder(CryptoOrder cryptoOrder) { try { Console.WriteLine($"Closed order {cryptoOrder.Uuid} as {cryptoOrder.OrderType} at {cryptoOrder.Limit}"); switch (cryptoOrder.OrderType) { case CryptoOrderType.LimitSell: Budget.Available += cryptoOrder.Price; var tradeForSellOrder = Trades.FirstOrDefault(t => t.SellOrder.Uuid == cryptoOrder.Uuid); if (tradeForSellOrder != null) { if (cryptoOrder.Canceled) { tradeForSellOrder.Status = TradeStatus.Bought; tradeForSellOrder.SellOrder.IsOpened = false; return(await Task.FromResult(Unit.Default)); } var tradeProfit = tradeForSellOrder.BuyOrder.Price.GetReadablePercentageChange(tradeForSellOrder.SellOrder.Price); Budget.Profit += tradeProfit; Budget.Earned += tradeForSellOrder.SellOrder.Price - tradeForSellOrder.BuyOrder.Price; Console.WriteLine($"{cryptoOrder.Uuid}: SELL - {tradeProfit}"); await _pushManager.TriggerPush(PushMessage.FromMessage($"Sold {Market} for profit {tradeProfit}%")); tradeForSellOrder.Profit = tradeProfit; tradeForSellOrder.Status = TradeStatus.Completed; tradeForSellOrder.SellOrder = cryptoOrder; } break; case CryptoOrderType.LimitBuy: var tradeForBuyOrder = Trades.FirstOrDefault(t => t.BuyOrder.Uuid == cryptoOrder.Uuid); if (tradeForBuyOrder != null) { await _pushManager.TriggerPush(PushMessage.FromMessage($"Bought {Market} at {cryptoOrder.Limit} BTC")); if (cryptoOrder.Canceled) { tradeForBuyOrder.Status = TradeStatus.Empty; tradeForBuyOrder.BuyOrder = new CryptoOrder(); return(await Task.FromResult(Unit.Default)); } tradeForBuyOrder.Status = TradeStatus.Bought; tradeForBuyOrder.BuyOrder = cryptoOrder; } break; } } finally { if (!IsInTestMode) { var traderData = await _traderGrain.GetTraderData(); traderData.CurrentTicker = Ticker; await _hubNotifier.UpdateTrader(traderData); } } return(await Task.FromResult(Unit.Default)); }
private void HandleOrderUpdated(CryptoOrder order) { if (IsFilteredOut(order)) { // order for different pair, etc. Ignore. return; } _idToOrder[order.Id] = order; if (order.OrderStatus == CryptoOrderStatus.Executed || order.OrderStatus == CryptoOrderStatus.PartiallyFilled) { if (order.Side == CryptoOrderSide.Ask) { LastExecutedSellOrder = order; } else { LastExecutedBuyOrder = order; } } _orderChanged.OnNext(order); if (IsOurOrder(order)) { _ourOrderChanged.OnNext(order); } }
public override Task <CryptoResponse <CryptoOrder> > BuyCoinAsync(CryptoOrder cryptoOrder) { //cryptoOrder.Uuid = "BUYORDER-" + BuyOrdersCount++; cryptoOrder.IsOpened = true; _pendingBuyOrders.Add(cryptoOrder); return(Task.FromResult(new CryptoResponse <CryptoOrder>(cryptoOrder)));; }
public override Task <CryptoResponse <CryptoOrder> > SellCoinAsync(CryptoOrder sellOrder) { //sellOrder.Uuid = "SELLORDER-" + SellOrdersCount++; sellOrder.IsOpened = true; _pendingSellOrders.Add(sellOrder); return(Task.FromResult(new CryptoResponse <CryptoOrder>(sellOrder)));; }
public static BittrexStreamOrderData ToBittrexStreamOrder(this CryptoOrder orderData) { try { var bittrexStreamOrderData = new BittrexStreamOrderData { Order = new BittrexStreamOrder { Market = orderData.Market, OrderType = orderData.OrderType == CryptoOrderType.LimitBuy ? OrderSideExtended.LimitBuy : OrderSideExtended.LimitSell, Price = orderData.Price.RoundSatoshi(), Quantity = orderData.Quantity.RoundSatoshi(), PricePerUnit = orderData.PricePerUnit.RoundSatoshi(), CommissionPaid = orderData.CommissionPaid.RoundSatoshi(), CancelInitiated = orderData.Canceled, Uuid = new Guid(orderData.Uuid), Opened = orderData.Opened, Closed = orderData.Closed, Limit = orderData.PricePerUnit.RoundSatoshi(), QuantityRemaining = orderData.QuantityRemaining.RoundSatoshi() } }; return(bittrexStreamOrderData); } catch (Exception e) { Console.WriteLine(e); return(null); } }
public ActionResult DeleteConfirmed(int id) { CryptoOrder cryptoOrder = db.CryptoOrders.Find(id); db.CryptoOrders.Remove(cryptoOrder); db.SaveChanges(); return(RedirectToAction("Index")); }
private static void HandleOrderChanged(CryptoOrder order) { Log.Information($"Order '{order.ClientId}' [{order.Pair} {order.Side} {order.Type}] changed. " + $"Price: {order.PriceGrouped}, Amount: {order.AmountOrig:#.#####}/{order.AmountOrigQuote}, " + $"cumulative: {order.AmountFilledCumulative:#.#####}/{order.AmountFilledCumulativeQuote}, " + $"filled: {order.AmountFilled:#.#####}/{order.AmountFilledQuote}, " + $"Status: {order.OrderStatus}"); }
private void OnOrderCreated(CryptoOrder order) { if (order == null) { return; } HandleOrderUpdated(order); }
public async Task <Unit> UpdateOrder(CryptoOrder cryptoOrder) { if (!IsInTestMode) { var traderData = await _traderGrain.GetTraderData(); traderData.CurrentTicker = Ticker; await _hubNotifier.UpdateTrader(traderData); } return(await Task.FromResult(Unit.Default)); }
public ActionResult Edit([Bind(Include = "ID,Value,UserID,CryptoID")] CryptoOrder cryptoOrder) { if (ModelState.IsValid) { db.Entry(cryptoOrder).State = EntityState.Modified; db.SaveChanges(); return(RedirectToAction("Index")); } ViewBag.CryptoID = new SelectList(db.Cryptoes, "ID", "Name", cryptoOrder.CryptoID); return(View(cryptoOrder)); }
public virtual async Task <CryptoResponse <CryptoOrder> > BuyCoinAsync(CryptoOrder cryptoOrder) { var buyResult = await _bittrexClient.PlaceOrderAsync(OrderSide.Buy, cryptoOrder.Market, cryptoOrder.Quantity, cryptoOrder.Limit); if (buyResult.Success) { cryptoOrder.Uuid = buyResult.Data.Uuid.ToString(); return(new CryptoResponse <CryptoOrder>(cryptoOrder)); } return(new CryptoResponse <CryptoOrder>(buyResult.Error.Message)); }
private CryptoOrder GetOrderMock(string clientId, string pair, CryptoOrderSide side) { return(CryptoOrder.Mock( clientId, pair, side, _random.Next(10, 10000), _random.Next(1, 1000), CryptoOrderType.Market, DateTime.UtcNow )); }
public ActionResult Create([Bind(Include = "ID,Value,CryptoID")] CryptoOrder cryptoOrder) { if (ModelState.IsValid) { cryptoOrder.UserID = User.Identity.GetUserId(); db.CryptoOrders.Add(cryptoOrder); db.SaveChanges(); return(RedirectToAction("Index")); } ViewBag.CryptoID = new SelectList(db.Cryptoes, "ID", "Name", cryptoOrder.CryptoID); return(View(cryptoOrder)); }
// GET: CryptoOrders/Details/5 public ActionResult Details(int?id) { if (id == null) { return(new HttpStatusCodeResult(HttpStatusCode.BadRequest)); } CryptoOrder cryptoOrder = db.CryptoOrders.Find(id); if (cryptoOrder == null) { return(HttpNotFound()); } return(View(cryptoOrder)); }
private void OnOrderUpdated(CryptoOrder order) { if (order == null) { return; } if (order.OrderStatus == CryptoOrderStatus.Undefined) { Log.Debug($"[ORDERS] Received order with weird status ({order.ClientId} - {order.PriceGrouped}/{order.AmountGrouped})"); } HandleOrderUpdated(order); }
public virtual async Task <CryptoResponse <CryptoOrder> > SellCoinAsync(CryptoOrder sellOrder) { var sellResult = await _bittrexClient.PlaceOrderAsync(OrderSide.Sell, sellOrder.Market, sellOrder.Quantity, sellOrder.Limit); if (sellResult.Success) { sellOrder.Uuid = sellResult.Data.Uuid.ToString(); return(new CryptoResponse <CryptoOrder>(sellOrder)); } else { return(new CryptoResponse <CryptoOrder>(sellResult.Error.Message)); } }
public async Task <Unit> UpdateOrder(CryptoOrder cryptoOrder) { try { Log($"Closed order {cryptoOrder.Uuid} as {cryptoOrder.OrderType} at {cryptoOrder.Limit}"); switch (cryptoOrder.OrderType) { case CryptoOrderType.LimitSell: TraderState.Budget.Available += cryptoOrder.Price; var tradeForSellOrder = TraderState.Trades.FirstOrDefault(t => t.SellOrder.Uuid == cryptoOrder.Uuid); if (tradeForSellOrder != null) { if (cryptoOrder.Canceled) { tradeForSellOrder.Status = TradeStatus.Bought; tradeForSellOrder.SellOrder.IsOpened = false; return(await Task.FromResult(Unit.Default)); } var tradeProfit = tradeForSellOrder.BuyOrder.Price.GetReadablePercentageChange(tradeForSellOrder.SellOrder.Price); TraderState.Budget.Profit += tradeProfit; TraderState.Budget.Earned += tradeForSellOrder.SellOrder.Price - tradeForSellOrder.BuyOrder.Price; Log($"{cryptoOrder.Uuid}: SELL - {tradeProfit}"); tradeForSellOrder.Profit = tradeProfit; tradeForSellOrder.Status = TradeStatus.Completed; tradeForSellOrder.SellOrder = cryptoOrder; } break; case CryptoOrderType.LimitBuy: var tradeForBuyOrder = TraderState.Trades.FirstOrDefault(t => t.BuyOrder.Uuid == cryptoOrder.Uuid); if (tradeForBuyOrder != null) { if (cryptoOrder.Canceled) { TraderState.Trades.Remove(tradeForBuyOrder); return(await Task.FromResult(Unit.Default)); } tradeForBuyOrder.Status = TradeStatus.Bought; tradeForBuyOrder.BuyOrder = cryptoOrder; } break; } } finally { OrderUpdated.OnNext(cryptoOrder); } return(await Task.FromResult(Unit.Default)); }
// GET: CryptoOrders/Edit/5 public ActionResult Edit(int?id) { if (id == null) { return(new HttpStatusCodeResult(HttpStatusCode.BadRequest)); } CryptoOrder cryptoOrder = db.CryptoOrders.Find(id); if (cryptoOrder == null) { return(HttpNotFound()); } ViewBag.CryptoID = new SelectList(db.Cryptoes, "ID", "Name", cryptoOrder.CryptoID); return(View(cryptoOrder)); }
private async Task TriggerBuy(decimal pricePerUnit, decimal price, decimal budget) { var cryptoOrder = new CryptoOrder { PricePerUnit = pricePerUnit, Price = price }; CryptoApiMock.MockBuyingTrade(cryptoOrder); CryptoApiMock.MockCancelTrade(cryptoOrder); await InitializeTrader(new TradeAction { TradeAdvice = TradeAdvice.Buy, OrderPricePerUnit = pricePerUnit }); Strategy.SetupGet(strategy => strategy.Settings).Returns(new TraderSettings { TradingBudget = budget }); await CoinTrader.UpdatePrice(new Ticker()); }
private bool IsFilteredOut(CryptoOrder order) { if (order == null) { return(true); } // filter out by selected pair if (!string.IsNullOrWhiteSpace(TargetPair) && !TargetPair.Equals(order.PairClean)) { return(true); } return(false); }
public async Task SellingCoin_Should_UpdateOrderForTrade() { await InitializeTrader(new TradeAction { TradeAdvice = TradeAdvice.Sell, OrderPricePerUnit = 98 }); var sellOrder = new CryptoOrder { OrderType = CryptoOrderType.LimitSell, Price = 1100, Uuid = "S" }; CryptoApiMock.MockSellingTrade(sellOrder); CoinTrader.Trades[0].SellOrder.Uuid = "S"; await CoinTrader.UpdatePrice(_newPriceTicker); CoinTrader.Trades[0].SellOrder.Uuid.Should().Be("S"); CoinTrader.Trades[0].SellOrder.Price.Should().Be(1100); }
public async Task SoldCoin_Should_UpdateTradeStatus() { var sellOrder = new CryptoOrder { OrderType = CryptoOrderType.LimitSell, Price = 1100, Uuid = "S" }; var trade = new Trade { SellOrder = sellOrder }; await InitializeTrader(new TradeAction { TradeAdvice = TradeAdvice.Sell }); CoinTrader.Trades.Add(trade); await CoinTrader.UpdateOrder(sellOrder); trade.Status.Should().Be(TradeStatus.Completed); }
private CryptoOrder ConvertOrder(OrderResponse order) { var id = order.Data.Id.ToString(); var clientId = order.Data.Id; var existingCurrent = ExistingOrders.ContainsKey(id) ? ExistingOrders[id] : null; var existingPartial = _partiallyFilledOrders.ContainsKey(id) ? _partiallyFilledOrders[id] : null; var existing = existingPartial ?? existingCurrent; var price = Math.Abs(FirstNonZero(order.Data.Price, existing?.Price) ?? 0); var amount = Math.Abs(FirstNonZero(order.Data.Amount, existing?.AmountOrig) ?? 0); var amountOrig = Math.Abs(order.Data.Amount); var currentStatus = existing != null && existing.OrderStatus != CryptoOrderStatus.Undefined && existing.OrderStatus != CryptoOrderStatus.New //&& //order.OrderStatus == OrderStatus.Undefined ? existing.OrderStatus : ConvertOrderStatus(order); var newOrder = new CryptoOrder { Id = id, Pair = CryptoPairsHelper.Clean(order.Symbol), Price = price, //Amount = amount, AmountOrig = amountOrig, Side = ConvertSide(order.Data.Amount), OrderStatus = ConvertOrderStatus(order), Type = (CryptoOrderType)order.Data.OrderType, //TODO //Created = ConvertToDatetime(DateTimeOffset.Parse(order.Data.MicroTimeStamp, out dt)) }; if (currentStatus == CryptoOrderStatus.PartiallyFilled) { // save partially filled orders _partiallyFilledOrders[newOrder.Id] = newOrder; } return(newOrder); }
private CryptoOrder ConvertOrder(OrderResponse order) { var id = order?.Id.ToString() ?? "00000"; var clientId = order?.ProfileId; var existingCurrent = ExistingOrders.ContainsKey(id) ? ExistingOrders[id] : null; var existingPartial = _partiallyFilledOrders.ContainsKey(id) ? _partiallyFilledOrders[id] : null; var existing = existingPartial ?? existingCurrent; var price = Math.Abs(FirstNonZero(order?.Price, existing?.Price) ?? 0); var amount = Math.Abs(FirstNonZero(order?.Amount, existing?.AmountOrig) ?? 0); var amountOrig = Math.Abs(order?.Size ?? 0); var currentStatus = existing != null && existing.OrderStatus != CryptoOrderStatus.Undefined && existing.OrderStatus != CryptoOrderStatus.New && order?.OrderStatus == OrderStatus.Undefined ? existing.OrderStatus : ConvertOrderStatus(order); var newOrder = new CryptoOrder { Id = id, Pair = CryptoPairsHelper.Clean(order?.Pair), Price = price, //Amount = amount, AmountOrig = amountOrig, Side = ConvertSide(order.Side), OrderStatus = ConvertOrderStatus(order), Type = (CryptoOrderType)order.OrderType, Created = ConvertToDatetime(order.MtsCreate), ClientId = clientId //Created = Convert.ToDateTime(order.MtsCreate) }; if (currentStatus == CryptoOrderStatus.PartiallyFilled) { // save partially filled orders _partiallyFilledOrders[newOrder.Id] = newOrder; } return(newOrder); }
private CryptoOrder ConvertOrder(Order order) { var id = order.Id.ToString(); var existingCurrent = ExistingOrders.ContainsKey(id) ? ExistingOrders[id] : null; var existingPartial = _partiallyFilledOrders.ContainsKey(id) ? _partiallyFilledOrders[id] : null; var existing = existingPartial ?? existingCurrent; var price = Math.Abs(FirstNonZero(order.Price, existing?.Price) ?? 0); var amount = Math.Abs(FirstNonZero(order.Amount, existing?.AmountOrig) ?? 0); var amountOrig = Math.Abs(order.AmountOrig ?? 0); var currentStatus = existing != null && existing.OrderStatus != CryptoOrderStatus.Undefined && existing.OrderStatus != CryptoOrderStatus.New && order.OrderStatus == OrderStatus.Undefined ? existing.OrderStatus : ConvertOrderStatus(order); var newOrder = new CryptoOrder { //ExchangeName = ExchangeName, Pair = order.Symbol ?? existing?.Pair, Price = price, //Amount = amount, AmountOrig = amountOrig, Side = ConvertSide(Convert.ToDouble(order.Amount)), Id = id, ClientId = order.Cid.ToString(), OrderStatus = ConvertOrderStatus(order.OrderStatus), Type = ConvertOrderType(order.Type.ToString()), Created = order.MtsCreate, Updated = order.MtsUpdate }; if (currentStatus == CryptoOrderStatus.PartiallyFilled) { // save partially filled orders _partiallyFilledOrders[newOrder.Id] = newOrder; } return(newOrder); }
public async Task BoughtOrder_Should_UpdateTraderStatus() { var trade = new Trade(); CryptoBroker.TraderState.Trades = new List <Trade> { trade }; trade.BuyOrder.Uuid = "B"; var buyOrder = new CryptoOrder { Uuid = "B", OrderType = CryptoOrderType.LimitBuy }; await CryptoBroker.UpdateOrder(buyOrder); CryptoBroker.TraderState.Trades[0].Status.Should().Be(TradeStatus.Bought); }
public CryptoOrder GetNew() { var rand = new Random(); CryptoOrder RandOrder = new CryptoOrder { InstrumentId = rand.Next(1, 100), ChildOrderId = rand.Next(1, 1000), CreationTimestamp = new DateTimeOffset(rand.Next(2015, 2019), rand.Next(1, 12), rand.Next(1, 28), rand.Next(0, 23), rand.Next(0, 59), rand.Next(0, 59), TimeSpan.Zero), LastUpdateTimestamp = new DateTimeOffset(rand.Next(2015, 2019), rand.Next(1, 12), rand.Next(1, 28), rand.Next(0, 23), rand.Next(0, 59), rand.Next(0, 59), TimeSpan.Zero), OrderType = rand.Next(0, 3) == 0 ? CryptoOrderType.Unknown:(rand.Next(0, 2) == 0 ? CryptoOrderType.Limit: rand.Next(0, 1) == 0 ? CryptoOrderType.Market: CryptoOrderType.StopLimit), ParentOrderId = rand.Next(0, 1000), Price = Convert.ToDecimal(0.01 + (rand.NextDouble() * (10000 - 0.01))), RemainingVolume = Convert.ToDecimal(0.01 + (rand.NextDouble() * (10000 - 0.01))), Settings = new JsonElement(), Status = 0, }; return(RandOrder); }
public SellCoinTests() { _cryptoApiMock = new Mock <ICryptoApi>(); _clusterClientMock = new Mock <IClusterClient>(); _hubNotifier = new Mock <IHubNotifier>(); _cryptoTrader = new CryptoTrader(_cryptoApiMock.Object, _clusterClientMock.Object, _hubNotifier.Object); _cryptoApiMock.Setup(c => c.BuyCoinAsync(It.IsAny <CryptoOrder>())).ReturnsAsync(new CryptoResponse <CryptoOrder>("hello")); _updatedOrder = new CryptoOrder(); _cryptoApiMock.Setup(c => c.SellCoinAsync(It.IsAny <CryptoOrder>())).ReturnsAsync(new CryptoResponse <CryptoOrder>(_updatedOrder)); _currentTrade = new Trade { BuyOrder = new CryptoOrder { PricePerUnit = 100M }, IsActive = true }; _cryptoApiMock.Setup(c => c.GetTickerAsync(It.IsAny <string>())) .ReturnsAsync(new CryptoResponse <Ticker>(new Ticker { Ask = 15, Bid = 100 })); _traderGrainMock = new Mock <ITraderGrain>(); _clusterClientMock.Setup(c => c.GetGrain <ITraderGrain>(It.IsAny <string>(), It.IsAny <string>())).Returns(_traderGrainMock.Object); _traderGrainMock.Setup(t => t.UpdatePriceAsync(It.IsAny <Ticker>())).Returns(Task.CompletedTask); _traderGrainMock.Setup(t => t.UpdatePriceAsync(It.IsAny <Ticker>())).Returns(Task.CompletedTask); _traderGrainMock.Setup(t => t.GetSettings()).ReturnsAsync(new TraderSettings { HighStopLossPercentage = -10, StopLoss = -2, BuyTrigger = -1, MinimumTakeProfit = 2 }); _traderGrainMock.Setup(t => t.GetActiveTrades()).ReturnsAsync(new List <Trade> { _currentTrade }); }
private async Task CreateSellOrder(Trade trade, decimal pricePerUnit) { var sellOrder = new CryptoOrder { PricePerUnit = pricePerUnit, Limit = pricePerUnit, OrderType = CryptoOrderType.LimitSell, Market = Market, Price = pricePerUnit * trade.BuyOrder.Quantity, Quantity = trade.BuyOrder.Quantity, Uuid = $"{trade.BuyOrder.Uuid}-{Ticker.Id}" }; var sellResponse = await _cryptoApi.SellCoinAsync(sellOrder); if (sellResponse.IsSuccessful) { trade.Status = TradeStatus.Selling; trade.SellOrder = sellResponse.Content; } }
private async Task <CryptoOrder> CreateBuyOrder(decimal pricePerUnit) { if (TraderState.Budget.Available < Strategy.Settings.TradingBudget) { TraderState.Budget.Available += Strategy.Settings.TradingBudget; if (Ticker.Market == "BTC-BCH") { Console.WriteLine(TraderState.Budget.Invested); } TraderState.Budget.Invested += Strategy.Settings.TradingBudget; } var priceWithoutCommission = Strategy.Settings.TradingBudget * Consts.BittrexCommission; var quantity = priceWithoutCommission / pricePerUnit; quantity = quantity.RoundSatoshi(); var buyOrder = new CryptoOrder { PricePerUnit = pricePerUnit, Price = Strategy.Settings.TradingBudget, Quantity = quantity, IsClosed = false, Market = Market, Limit = pricePerUnit, Opened = Ticker.Timestamp, OrderType = CryptoOrderType.LimitBuy, Uuid = $"{Ticker.Id}-{Guid.NewGuid().ToString().Split('-')[0]}" }; var buyResponse = await _cryptoApi.BuyCoinAsync(buyOrder); if (buyResponse.IsSuccessful) { TraderState.Budget.Available -= buyResponse.Content.Price; } else { throw new Exception(buyResponse.ErrorMessage); } return(buyResponse.Content); }