public static void BuyCurrencyFromUsdt(string currencyPair, ref TradeSignalOrder tradeSignalOrder) { lock (_syncRoot) { decimal percentToTrade = GetPercentToTrade(); bool isMoving = false; int attemptCount = 0; Dictionary <string, decimal> balances = PoloniexExchangeService.Instance.ReturnBalances(); decimal usdtBalance = balances[CurrencyConstants.USDT] * percentToTrade; /* don't attempt to trade under $1 */ if (usdtBalance < 1M) { tradeSignalOrder.PlaceValueTradedAt = -1; tradeSignalOrder.MoveValueTradedAt = -1; tradeSignalOrder.LastValueAtProcessing = -1; Logger.Write($"Order: Insufficient funds", Logger.LogType.TransactionLog); } long orderNumber = 0; while (true) { attemptCount++; Dictionary <string, Dictionary <string, decimal> > res = PoloniexExchangeService.Instance.ReturnTicker(); var latestUsdtBtcTicker = res[currencyPair]; // weighted average decimal usdtCurrencyLastPrice = latestUsdtBtcTicker[TickerResultKeys.last]; // 3 decimal usdtCurrencyLowestAsk = latestUsdtBtcTicker[TickerResultKeys.lowestAsk]; // 2 decimal usdtCurrencyHighestBid = latestUsdtBtcTicker[TickerResultKeys.highestBid]; // 1 /* TESTING CODE : BEGIN */ //decimal buyRate = (0.75M) * usdtBtcLastPrice; // TODO: FIX!!! //if (isMoving) //{ // buyRate = buyRate * 0.75M; //} /* TESTING CODE : END */ /* PRODUCTION CODE : BEGIN */ decimal buyRate = ((3M * usdtCurrencyLastPrice) + (2M * usdtCurrencyLowestAsk) + (1M * usdtCurrencyHighestBid)) / 6M; /* PRODUCTION CODE : END */ decimal buyAmount = usdtBalance / buyRate; if (!isMoving) { tradeSignalOrder.PlaceValueTradedAt = buyRate; // BUY Thread.Sleep(1000); // guarantee nonce (unix timestamp) var buyResult = PoloniexExchangeService.Instance.Buy(currencyPair, buyRate, buyAmount); orderNumber = buyResult.orderNumber; Logger.Write($"Order: Purchasing {currencyPair} from USDT; buyRate: {buyRate}, buyAmount: {buyAmount}, _numberOfTraders: {_numberOfTraders}, _numberOfHoldings: {_numberOfHoldings}", Logger.LogType.TransactionLog); isMoving = true; } else { tradeSignalOrder.MoveValueTradedAt = buyRate; // MOVE Thread.Sleep(1000); // guarantee nonce (unix timestamp) var moveResult = PoloniexExchangeService.Instance.MoveOrder(orderNumber, buyRate, buyAmount); orderNumber = moveResult.orderNumber; Logger.Write($"Order: Moving (attemptCount:{attemptCount}) {currencyPair} from USDT; buyRate: {buyRate}, buyAmount: {buyAmount}, _numberOfTraders: {_numberOfTraders}, _numberOfHoldings: {_numberOfHoldings}", Logger.LogType.TransactionLog); } Thread.Sleep(10 * 1000); // allow exchange to resolve order // Get open orders var openOrders = PoloniexExchangeService.Instance.ReturnOpenOrders(currencyPair); var originalBuyOrder = openOrders.SingleOrDefault(x => x[OpenOrderKeys.orderNumber] == orderNumber.ToString()); Logger.Write($"openOrders: {JsonConvert.SerializeObject(openOrders)}", Logger.LogType.TransactionLog); bool isTradeComplete = originalBuyOrder == null; if (isTradeComplete) { tradeSignalOrder.LastValueAtProcessing = buyRate; _numberOfHoldings++; break; } } } }
public static void ProcessEmaCrossOverSignal(Guid eventActionId) { using (var db = new PoloniexContext()) { var tradeSignalEventAction = db.TradeSignalEventActions .Single(x => x.EventActionId == eventActionId); var currencyPair = tradeSignalEventAction.CurrencyPair; var latestShorterMovingAverage = db.MovingAverages .Where(x => x.CurrencyPair == tradeSignalEventAction.CurrencyPair && x.Interval == tradeSignalEventAction.ShorterMovingAverageInterval) .OrderByDescending(x => x.ClosingDateTime) .First(); var latestLongerMovingAverage = db.MovingAverages .Where(x => x.CurrencyPair == tradeSignalEventAction.CurrencyPair && x.Interval == tradeSignalEventAction.LongerMovingAverageInterval) .OrderByDescending(x => x.ClosingDateTime) .First(); var lastClosingValue = db.CurrencyDataPoints .Where(x => x.CurrencyPair == tradeSignalEventAction.CurrencyPair) .OrderByDescending(x => x.ClosingDateTime) .First().ClosingValue; Signals[currencyPair].IsBullish = latestShorterMovingAverage.MovingAverageValue - latestLongerMovingAverage.MovingAverageValue >= 0; if (!Signals[currencyPair].Init) { if (!Signals[currencyPair].WasBullish && Signals[currencyPair].IsBullish && !Signals[currencyPair].HasHoldings) { // BUY Signals[currencyPair].ShouldBuy = true; Signals[currencyPair].BuyValue = lastClosingValue; } if (Signals[currencyPair].HasHoldings) { decimal high; decimal low; high = Signals[currencyPair].BuyValue * (1M + Configurations[currencyPair].StopLossPercentageUpper); low = Signals[currencyPair].BuyValue * (1M - Configurations[currencyPair].StopLossPercentageLower); if (Configurations[currencyPair].IsStopLossTailing) { if (lastClosingValue >= high) { Signals[currencyPair].BuyValue = high * (1M + Configurations[currencyPair].StopLossPercentageUpper); } if (lastClosingValue <= low) { Signals[currencyPair].ShouldSell = true; } } else { if (lastClosingValue >= high || lastClosingValue <= low) { Signals[currencyPair].ShouldSell = true; } } } if (Signals[currencyPair].ShouldBuy) { var buyTradeSignalOrder = new TradeSignalOrder() { CurrencyPair = currencyPair, TradeOrderType = TradeOrderType.Buy, LastValueAtRequest = latestShorterMovingAverage.LastClosingValue, IsProcessed = false, InProgress = false, OrderRequestedDateTime = DateTime.UtcNow, CreatedByEventActionId = eventActionId }; db.TradeSignalOrders.Add(buyTradeSignalOrder); db.SaveChanges(); Signals[currencyPair].HasHoldings = true; } if (Signals[currencyPair].ShouldSell) { var sellTradeSignalOrder = new TradeSignalOrder() { CurrencyPair = currencyPair, TradeOrderType = TradeOrderType.Sell, LastValueAtRequest = latestShorterMovingAverage.LastClosingValue, IsProcessed = false, InProgress = false, OrderRequestedDateTime = DateTime.UtcNow, CreatedByEventActionId = eventActionId }; db.TradeSignalOrders.Add(sellTradeSignalOrder); db.SaveChanges(); Signals[currencyPair].HasHoldings = false; } Logger.Write($"currencyPair: {currencyPair}, wasBullish: {Signals[currencyPair].WasBullish}, isBullish: {Signals[currencyPair].IsBullish}, hasHolding: {Signals[currencyPair].HasHoldings}, shouldBuy: {Signals[currencyPair].ShouldBuy}, shouldSell: {Signals[currencyPair].ShouldSell}", Logger.LogType.TransactionLog); Signals[currencyPair].ShouldBuy = false; Signals[currencyPair].ShouldSell = false; } else { Logger.Write($"TradeTask init for {currencyPair}, evenActionId: {eventActionId} (see TransactionLog)", Logger.LogType.ServiceLog); Signals[currencyPair].Init = false; } Signals[currencyPair].WasBullish = Signals[currencyPair].IsBullish; } }
public static void SellCurrencyToUsdt(string currencyPair, ref TradeSignalOrder tradeSignalOrder) { lock (_syncRoot) { decimal percentToTrade = 1.00M; // always sell 100% bool isMoving = false; int attemptCount = 0; Dictionary <string, decimal> balances = PoloniexExchangeService.Instance.ReturnBalances(); decimal currencyBalance = balances[CurrencyUtility.GetCurrencyFromUsdtCurrencyPair(currencyPair)] * percentToTrade; long orderNumber = 0; while (true) { attemptCount++; Dictionary <string, Dictionary <string, decimal> > res = PoloniexExchangeService.Instance.ReturnTicker(); var latestUsdtBtcTicker = res[currencyPair]; // weighted average decimal usdtCurrencyLastPrice = latestUsdtBtcTicker[TickerResultKeys.last]; // 3 decimal usdtCurrencyHighestBid = latestUsdtBtcTicker[TickerResultKeys.highestBid]; // 2 decimal usdtCurrencyLowestAsk = latestUsdtBtcTicker[TickerResultKeys.lowestAsk]; // 1 /* TESTING CODE : BEGIN */ //decimal sellRate = (1.25M) * usdtBtcLastPrice; // TODO: FIX!!! //if (isMoving) //{ // sellRate = sellRate * 1.25M; //} /* TESTING CODE : END */ /* PRODUCTION CODE : BEGIN */ decimal sellRate = ((3M * usdtCurrencyLastPrice) + (2M * usdtCurrencyHighestBid) + (1M * usdtCurrencyLowestAsk)) / 6M;; /* PRODUCTION CODE : END */ decimal sellAmount = currencyBalance; if (!isMoving) { tradeSignalOrder.PlaceValueTradedAt = sellRate; // SELL Thread.Sleep(1000); // guarantee nonce (unix timestamp) var sellResult = PoloniexExchangeService.Instance.Sell(currencyPair, sellRate, sellAmount); orderNumber = sellResult.orderNumber; Logger.Write($"Order: Selling {currencyPair} to USDT; sellRate: {sellRate}, sellAmount: {sellAmount}, _numberOfTraders: {_numberOfTraders}, _numberOfHoldings: {_numberOfHoldings}", Logger.LogType.TransactionLog); isMoving = true; } else { tradeSignalOrder.MoveValueTradedAt = sellRate; // MOVE Thread.Sleep(1000); // guarantee nonce (unix timestamp) var moveResult = PoloniexExchangeService.Instance.MoveOrder(orderNumber, sellRate, sellAmount); orderNumber = moveResult.orderNumber; Logger.Write($"Order: Moving (attemptCount:{attemptCount}) {currencyPair} to USDT; sellRate: {sellRate}, sellAmount: {sellAmount}, _numberOfTraders: {_numberOfTraders}, _numberOfHoldings: {_numberOfHoldings}", Logger.LogType.TransactionLog); } Thread.Sleep(10 * 1000); // allow exchange to resolve order // Get open orders var openOrders = PoloniexExchangeService.Instance.ReturnOpenOrders(currencyPair); var originalBuyOrder = openOrders.SingleOrDefault(x => x[OpenOrderKeys.orderNumber] == orderNumber.ToString()); Logger.Write($"openOrders: {JsonConvert.SerializeObject(openOrders)}", Logger.LogType.TransactionLog); bool isTradeComplete = originalBuyOrder == null; if (isTradeComplete) { tradeSignalOrder.LastValueAtProcessing = sellRate; _numberOfHoldings--; break; } } } }