예제 #1
0
        public void Start()
        {
            if (!isStarted)
            {
                EofR1ExeThread = new Thread(() => WatchMarkets());
                EofR1ExeThread.IsBackground = true;
                EofR1ExeThread.Name         = "EMAofRSI1-ExecutionLoop-Thread";
                EofR1ExeThread.Start();
                isStarted = true;
            }

            StopLossController.StartWatching();
        }
예제 #2
0
        private void LoadHoldings()
        {
            //Load held assets, stoploss amts, from SQLite for each period:
            AddHoldingsTable("period5m");
            AddHoldingsTable("period20m");
            AddHoldingsTable("period1h");
            AddHoldingsTable("period4h");
            AddHoldingsTable("period12h");
            AddHoldingsTable("OpenOrders");


            //REGISTER EXISTING STOPLOSS RATES FOR EACH HOLDING
            foreach (DataTable dt in Holdings.Tables)
            {
                if (dt.TableName == "OpenOrders")
                {
                    continue;
                }

                foreach (DataRow row in dt.Rows)
                {
                    var stopLoss = new StopLoss((string)row["MarketDelta"], Convert.ToDecimal(row["StopLossRate"]), Convert.ToDecimal(row["Qty"]), (a, b, c) => ReCalcStoploss(a, b, c), (a, b) => StopLossExecutedCallback(a, b), dt.TableName, OPTIONS.VITRUAL_MODE);

                    if (OPTIONS.SAFE_MODE)
                    {
                        if (Convert.ToDecimal(row["BoughtRate"]) > stopLoss.StopRate)
                        {
                            stopLoss.StopRate = Convert.ToDecimal(row["BoughtRate"]) * 0.68M;
                        }
                    }
                    //Trace.WriteLine(string.Format("{0}_{1} ... {2} ... {3} ... {4}", stopLoss.CandlePeriod, stopLoss.MarketDelta, stopLoss.Quantity, stopLoss.StopRate, stopLoss.virtualSL));

                    StopLossController.RegisterStoploss(stopLoss, string.Format("{0}_{1}", stopLoss.CandlePeriod, stopLoss.MarketDelta));
                }
            }


            //Load Total From SQLite data:
            LoadTradingTotal();
        }
예제 #3
0
        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
                                                  ));
                }
            }
        }
예제 #4
0
        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;
            }
        }
예제 #5
0
        private void WatchMarkets()
        {
            using (var cmd = new SQLiteCommand(conn))
            {
                while (true) //!(Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Backspace))
                {
                    //WRITE/SAVE SQL DATA CHANGES:
                    SaveSQLOrderData(cmd);
                    SaveSQLData(cmd);

                    //BEGIN CANDLES ASSESSMENTS:
                    foreach (Market m in BtrexData.Markets.Values)
                    {
                        //CHECK FOR NEW CANDLES:
                        if (m.TradeHistory.LastStoredCandle > StratData.Candles5m[m.MarketDelta].Last().DateTime)
                        {
                            //Get new 5m candles:
                            var Importer   = new TradyCandleImporter();
                            var newCandles = Importer.ImportAsync(m.MarketDelta, StratData.Candles5m[m.MarketDelta].Last().DateTime.AddMinutes(5)).Result;
                            StratData.Candles5m[m.MarketDelta].AddRange(newCandles);
                            CheckStrategy(StratData.Candles5m[m.MarketDelta].Skip(Math.Max(0, StratData.Candles5m[m.MarketDelta].Count - 42)).ToList(), m.MarketDelta, "period5m");

                            //Build new 20m candles + Check strategy for buy/sell signals:
                            var CandleCurrentTime = m.TradeHistory.LastStoredCandle.AddMinutes(5);
                            if (CandleCurrentTime > StratData.Candles20m[m.MarketDelta].Last().DateTime.AddMinutes(40))
                            {
                                if (StratData.BuildNew20mCndls(m.MarketDelta))
                                {
                                    CheckStrategy(StratData.Candles20m[m.MarketDelta].Skip(Math.Max(0, StratData.Candles20m[m.MarketDelta].Count - 42)).ToList(), m.MarketDelta, "period20m");
                                }

                                //Build new 1h candles + Check strategy for buy/sell signals:
                                if (CandleCurrentTime > StratData.Candles1h[m.MarketDelta].Last().DateTime.AddHours(2))
                                {
                                    if (StratData.BuildNew1hCndls(m.MarketDelta))
                                    {
                                        CheckStrategy(StratData.Candles1h[m.MarketDelta].Skip(Math.Max(0, StratData.Candles1h[m.MarketDelta].Count - 42)).ToList(), m.MarketDelta, "period1h");
                                    }

                                    //Build new 4h candles + Check strategy for buy/sell signals:
                                    if (CandleCurrentTime > StratData.Candles4h[m.MarketDelta].Last().DateTime.AddHours(8) && StratData.BuildNew4hCndls(m.MarketDelta))
                                    {
                                        CheckStrategy(StratData.Candles4h[m.MarketDelta].Skip(Math.Max(0, StratData.Candles4h[m.MarketDelta].Count - 42)).ToList(), m.MarketDelta, "period4h");
                                    }

                                    //Build new 12h candles + Check strategy for buy/sell signals:
                                    if (CandleCurrentTime > StratData.Candles12h[m.MarketDelta].Last().DateTime.AddHours(24) && StratData.BuildNew12hCndls(m.MarketDelta))
                                    {
                                        CheckStrategy(StratData.Candles12h[m.MarketDelta].Skip(Math.Max(0, StratData.Candles12h[m.MarketDelta].Count - 42)).ToList(), m.MarketDelta, "period12h");
                                    }
                                }
                            }
                        }
                    }


                    //EXECUTE ALL List<NewOrders>:
                    if (NewOrders.Count > 0)
                    {
                        //PendingOrders.AddRange(NewOrders);
                        var ords = new List <NewOrder>(NewOrders);
                        NewOrders = new List <NewOrder>();

                        //This is not awaited because NewOrder objects reference their own callback
                        BtrexREST.TradeController.ExecuteNewOrderList(ords, OPTIONS.VITRUAL_MODE);
                    }


                    Thread.Sleep(TimeSpan.FromSeconds(3));
                }

                //CONTROL-LOOP ENDED:
                StopLossController.Stop();
            }

            conn.Close();
            isStarted = false;
            Trace.WriteLine("\r\n\r\n    @@@ EMAofRSI1 Strategy STOPPED @@@\r\n\r\n");
        }