//CALLBACK FUNCTIONS FOR STOPLOSS EXE AND CALC-MOVE: public void StopLossExecutedCallback(GetOrderResult OrderResponse, string period) { var TimeExecuted = OrderResponse.Closed; //FIND + REMOVE FROM HOLDINGS: var holdingRows = Holdings.Tables[period].Select(string.Format("MarketDelta = '{0}'", OrderResponse.Exchange)); //CALC PROFIT WITH BOUGHT RATE AND FEES INCLUDED, OUTPUT: var profit = ((OrderResponse.PricePerUnit / Convert.ToDecimal(holdingRows[0]["BoughtRate"])) - 1M); var compoundMultiple = (Convert.ToDecimal(holdingRows[0]["BoughtRate"]) * Convert.ToDecimal(holdingRows[0]["Qty"])) / OPTIONS.BTCwagerAmt; var timeHeld = TimeExecuted - Convert.ToDateTime(holdingRows[0]["DateTimeBUY"]); TradingTotal += (profit * compoundMultiple); var netWorth = GetNetPercentage(); //REMOVE foreach (var row in holdingRows) { Holdings.Tables[period].Rows.Remove(row); } //OUTPUT STOPLOSS EXECUTED: Trace.Write(string.Format("{0}{1} STOPLOSS-Sold {2} at {3:0.00000000}\r\n =TradeProfit: ", OPTIONS.VITRUAL_MODE ? "[VIRTUAL|" + TimeExecuted + "] ::: " : "[" + TimeExecuted + "] ::: ", period.Remove(0, 6), OrderResponse.Exchange.Split('-')[1], OrderResponse.PricePerUnit)); //OUTPUT PROFIT ON TRADE: if (profit < 0) { Console.ForegroundColor = ConsoleColor.Red; } else if (profit > 0) { Console.ForegroundColor = ConsoleColor.Green; } else { Console.ForegroundColor = ConsoleColor.DarkCyan; } Trace.Write(string.Format("{0:+0.###%;-0.###%;0}", profit)); //OUTPUT TIME HELD Console.ForegroundColor = ConsoleColor.DarkCyan; Trace.Write(string.Format(".....=Time-Held: {0:hh\\:mm\\:ss}.....", timeHeld)); //OUTPUT GROSS TOTAL PROFIT PERCENTAGE: if (TradingTotal < 0) { Console.ForegroundColor = ConsoleColor.Red; } else if (TradingTotal > 0) { Console.ForegroundColor = ConsoleColor.Green; } else { Console.ForegroundColor = ConsoleColor.DarkCyan; } Trace.Write(string.Format("=GrossProfit: {0:+0.###%;-0.###%;0}", TradingTotal / OPTIONS.MAXTOTALENTRANCES)); Console.ForegroundColor = ConsoleColor.DarkCyan; Trace.Write("....."); //OUTPUT CURRENT NET WORTH PERCENTAGE INCLUDING HOLDINGS: if (netWorth > 0) { Console.ForegroundColor = ConsoleColor.DarkGreen; } else if (netWorth < 0) { Console.ForegroundColor = ConsoleColor.DarkRed; } else { Console.ForegroundColor = ConsoleColor.DarkCyan; } Trace.WriteLine(string.Format("=CurrentNetWorth: {0:+0.###%;-0.###%;0}", netWorth)); Console.ForegroundColor = ConsoleColor.DarkCyan; //CREATE & ENQUEUE SQLDatawrite obj: var update = new SaveDataUpdate(period, OrderResponse.Exchange, "SELL", (DateTime)TimeExecuted, OrderResponse.Quantity, OrderResponse.PricePerUnit, null, true, TradingTotal); SQLDataUpdateWrites.Enqueue(update); }
public void ReCalcStoploss(string market, decimal oldRate, string period) { //RECALC NEW STOPLOSSRATE, THEN RAISE REGISTERED RATE IF HIGHER NOW: decimal boughtRate = 0; decimal ATR = 0; try { ATR = CalcStoplossMargin(market, period); boughtRate = Convert.ToDecimal(Holdings.Tables[period].Select(string.Format("MarketDelta = '{0}'", market))[0]["BoughtRate"]); } catch (Exception e) { Trace.WriteLine(" ****ERR RECALC-STOPLOSS>>> " + market + " | " + period + "... BOUGHT: " + boughtRate + " ... RATE: " + ATR); return; } //TIERED TRAILING STOPLOSS: //Teir 2 (calculate): var stoplossRate = BtrexData.Markets[market].TradeHistory.RecentFills.Last().Rate - (ATR * OPTIONS.ATRmultipleT2); var tier = "**"; //Use Teir 1, if T2 is below profit line: if (stoplossRate < boughtRate * 1.0025M) { stoplossRate = BtrexData.Markets[market].TradeHistory.RecentFills.Last().Rate - (ATR * OPTIONS.ATRmultipleT1); if (OPTIONS.SAFE_MODE) { stoplossRate = 0.0M; } tier = "*"; } //Use Teir 3, if current rate is above 8% profit: if (BtrexData.Markets[market].TradeHistory.RecentFills.Last().Rate > boughtRate * 1.1M) { stoplossRate = BtrexData.Markets[market].TradeHistory.RecentFills.Last().Rate - (ATR * OPTIONS.ATRmultipleT3); tier = "***"; } if (Math.Round(stoplossRate, 8) > Math.Round(oldRate, 8)) { var SLmovedTime = DateTime.UtcNow; //RAISE SL: StopLossController.RaiseStoploss(string.Format("{0}_{1}", period, market), stoplossRate); //CHANGE IN HOLDINGS: var row = Holdings.Tables[period].Select(string.Format("MarketDelta = '{0}'", market)); row[0]["StopLossRate"] = stoplossRate; //CREATE & ENQUEUE SQLDataWrite: var update = new SaveDataUpdate(period, market, "SL_MOVE", SLmovedTime, 0, 0, stoplossRate); SQLDataUpdateWrites.Enqueue(update); //OUTPUT STOPLOSS MOVED: if (OPTIONS.LogStoplossRaised) { Trace.WriteLine(string.Format("{0}{1}_{2} STOPLOSS-RAISED from {3:0.00000000} to {4:0.00000000}{5}", "[" + SLmovedTime + "] ::: ", period.Remove(0, 6), market, oldRate, stoplossRate, tier )); } } }
public void OrderExecutedCallback(OpenOrder OrderData) { //Find + REMOVE FROM OpenOrders TABLE, var OpenOrderRows = Holdings.Tables["OpenOrders"].Select(string.Format("UniqueID = '{0}_{1}'", OrderData.CandlePeriod, OrderData.Exchange)); foreach (var row in OpenOrderRows) { Holdings.Tables["OpenOrders"].Rows.Remove(row); } OrderData.PricePerUnit = Math.Round((OrderData.TotalReserved / OrderData.TotalQuantity), 8); if (OrderData.Type == "LIMIT_BUY") { //Calculate stoploss, within acceptable range per PeriodLength: decimal stoplossRate = OrderData.PricePerUnit - (CalcStoplossMargin(OrderData.Exchange, OrderData.CandlePeriod) * OPTIONS.ATRmultipleT1); switch (OrderData.CandlePeriod) { case "period5m": if (stoplossRate / OrderData.PricePerUnit < 0.98M) { stoplossRate = OrderData.PricePerUnit * 0.98M; } break; case "period20m": if (stoplossRate / OrderData.PricePerUnit < 0.95M) { stoplossRate = OrderData.PricePerUnit * 0.95M; } break; case "period1h": if (stoplossRate / OrderData.PricePerUnit < 0.93M) { stoplossRate = OrderData.PricePerUnit * 0.93M; } break; case "period4h": if (stoplossRate / OrderData.PricePerUnit < 0.90M) { stoplossRate = OrderData.PricePerUnit * 0.90M; } break; case "period12h": if (stoplossRate / OrderData.PricePerUnit < 0.88M) { stoplossRate = OrderData.PricePerUnit * 0.88M; } break; } //If 'SAFEMMODE' then Stoploss will be set to sell at minimum satoshis until profitable: if (OPTIONS.SAFE_MODE) { stoplossRate = 0.00105M / OrderData.TotalQuantity; } //Register new StopLoss in controller: StopLossController.RegisterStoploss(new StopLoss(OrderData.Exchange, stoplossRate, OrderData.TotalQuantity, (a, b, c) => ReCalcStoploss(a, b, c), (a, b) => StopLossExecutedCallback(a, b), OrderData.CandlePeriod, OPTIONS.VITRUAL_MODE), string.Format("{0}_{1}", OrderData.CandlePeriod, OrderData.Exchange)); //Enter into Holdings Table: var newHoldingsRow = Holdings.Tables[OrderData.CandlePeriod].NewRow(); newHoldingsRow["MarketDelta"] = OrderData.Exchange; newHoldingsRow["DateTimeBUY"] = OrderData.Closed; newHoldingsRow["Qty"] = OrderData.TotalQuantity; newHoldingsRow["BoughtRate"] = OrderData.PricePerUnit; newHoldingsRow["DateTimeSELL"] = "OWNED"; newHoldingsRow["SoldRate"] = "OWNED"; newHoldingsRow["StopLossRate"] = stoplossRate; newHoldingsRow["SL_Executed"] = 0; Holdings.Tables[OrderData.CandlePeriod].Rows.Add(newHoldingsRow); //Create + Enqueue SaveDataUpdate + OrderUpdate var update = new SaveDataUpdate(OrderData.CandlePeriod, OrderData.Exchange, "BUY", (DateTime)OrderData.Closed, OrderData.TotalQuantity, OrderData.PricePerUnit, stoplossRate); SQLDataUpdateWrites.Enqueue(update); SQLOrderUpdateWrites.Enqueue(OrderData); //OUTPUT BUY Trace.WriteLine(string.Format("{0}{1} Bought {2} at {3:0.00000000}, SL_Rate: {4:0.00000000}", OPTIONS.VITRUAL_MODE ? "[VIRTUAL|" + OrderData.Closed + "] ::: " : "[" + OrderData.Closed + "] ::: ", OrderData.CandlePeriod.Remove(0, 6), OrderData.Exchange.Split('-')[1], OrderData.PricePerUnit, stoplossRate)); } else if (OrderData.Type == "LIMIT_SELL") { StopLossController.CancelStoploss(string.Format("{0}_{1}", OrderData.CandlePeriod, OrderData.Exchange)); //Find row in Holdings: var holdingRows = Holdings.Tables[OrderData.CandlePeriod].Select(string.Format("MarketDelta = '{0}'", OrderData.Exchange)); //Calc profit with BoughtRate and include fees: var profit = ((OrderData.PricePerUnit / Convert.ToDecimal(holdingRows[0]["BoughtRate"])) - 1M); //Calc compound multiple var compoundMultiple = ((Convert.ToDecimal(holdingRows[0]["BoughtRate"]) * Convert.ToDecimal(holdingRows[0]["Qty"])) / OPTIONS.BTCwagerAmt); //Calc TradingTotal and NetWorth TradingTotal += (profit * compoundMultiple); var netWorth = GetNetPercentage(); var timeHeld = OrderData.Closed - Convert.ToDateTime(holdingRows[0]["DateTimeBUY"]); //Remove from Holdings: foreach (var row in holdingRows) { Holdings.Tables[OrderData.CandlePeriod].Rows.Remove(row); } //Create and add the SQL SaveDataUpdate + OrderUpdate var update = new SaveDataUpdate(OrderData.CandlePeriod, OrderData.Exchange, "SELL", (DateTime)OrderData.Closed, OrderData.TotalQuantity, OrderData.PricePerUnit, null, false, TradingTotal); SQLDataUpdateWrites.Enqueue(update); SQLOrderUpdateWrites.Enqueue(OrderData); //OUTPUT SELL-ON-SIGNAL Trace.Write(string.Format("{0}{1} Sold {2} at {3}\r\n =TradeProfit: ", OPTIONS.VITRUAL_MODE ? "[VIRTUAL|" + OrderData.Closed + "] ::: " : "[" + OrderData.Closed + "] ::: ", OrderData.CandlePeriod.Remove(0, 6), OrderData.Exchange.Split('-')[1], OrderData.PricePerUnit)); //OUTPUT PROFIT ON TRADE: if (profit < 0) { Console.ForegroundColor = ConsoleColor.Red; } else if (profit > 0) { Console.ForegroundColor = ConsoleColor.Green; } Trace.Write(string.Format("{0:+0.###%;-0.###%;0}", profit)); //OUTPUT TIME HELD Console.ForegroundColor = ConsoleColor.DarkCyan; Trace.Write(string.Format(".....=Time-Held: {0:hh\\:mm\\:ss}.....", timeHeld)); //OUTPUT GROSS TOTAL PROFIT PERCENTAGE: if (TradingTotal < 0) { Console.ForegroundColor = ConsoleColor.Red; } else if (TradingTotal > 0) { Console.ForegroundColor = ConsoleColor.Green; } else { Console.ForegroundColor = ConsoleColor.DarkCyan; } Trace.Write(string.Format("=GrossProfit: {0:+0.###%;-0.###%;0}", TradingTotal / OPTIONS.MAXTOTALENTRANCES)); Console.ForegroundColor = ConsoleColor.DarkCyan; Trace.Write("....."); //OUTPUT CURRENT NET WORTH PERCENTAGE INCLUDING HOLDINGS: if (netWorth > 0) { Console.ForegroundColor = ConsoleColor.DarkGreen; } else if (netWorth < 0) { Console.ForegroundColor = ConsoleColor.DarkRed; } else { Console.ForegroundColor = ConsoleColor.DarkCyan; } Trace.WriteLine(string.Format("=CurrentNetWorth: {0:+0.###%;-0.###%;0}", netWorth)); Console.ForegroundColor = ConsoleColor.DarkCyan; } }