public static List <Candle> GetCandles(string instrumentID, CandleType type, DateTime fromTradingDay) { List <Candle> minuteCandles = CandleDAL.Get(instrumentID, fromTradingDay); if (type == CandleType.Minute) { return(minuteCandles); } else { return(CandleHelper.ConvertCandleToCandle(minuteCandles, type)); } }
public void StartWork() { if (Working) { return; } if (Done) { return; } _thread = new Thread(() => { Working = true; Done = false; CandleHelper.RetrieveCandles(Symbol, Interval, Start, End); Working = false; Done = true; }); _thread.Start(); }
public string Backtest(string source, string market, KlineInterval kline, DateTime start, DateTime end, StrategyOptions actStrat) { //var source = ""; //var market = "BTCTUSDT"; //var kline = Binance.Net.Objects.KlineInterval.FifteenMinutes; //var start = new DateTime(2019, 11, 1); //var end = new DateTime(2019, 12, 30); //var actStrat = new StrategyOptions(); // get all candles CandleHelper.RetrieveCandles(market, kline, start, end); DateTime small = DateTime.MinValue; DateTime big = DateTime.MinValue; List <CandleInfo> allCandles = null; if (!CandleHelper.CandlesAvailable(market, kline, start, end, out small, out big, out allCandles)) { return("no candles available"); } var temp = new Context(allCandles); temp.ActiveStrategyOptions = Globals.ActiveStrategyOptions; if (!CryptoGlobals.RunScript(source, ref temp)) { return("error in script: " + temp.SCRIPT_ERROR); } var c = new Context(allCandles); c.ActiveStrategyOptions = actStrat; var startingBalance = c.ActiveStrategyOptions.BacktestStartingBalance; var originalBalance = startingBalance; var l = new List <CandleInfo>(); dynamic script = CSScript.RoslynEvaluator.LoadCode(source); foreach (var item in allCandles) { l.Add(item); if (l.Count < 20) { continue; } c.RawCandles = l; try { script.OnData(c); }catch (Exception ex) { return("error: " + ex.Message); } } foreach (var item in c.GetOpenOrders()) { c.CloseOrder(item); } var orders = c.GetAllOrders(); var candlesAndOrders = new SortedDictionary <DateTime, List <OrderInfo> >(); foreach (var item in orders) { var buyDate = item.BuyCandle.OpenTime; var sellDate = item.SellCandle.OpenTime; if (!candlesAndOrders.ContainsKey(buyDate)) { candlesAndOrders[buyDate] = new List <OrderInfo>(); } if (!candlesAndOrders.ContainsKey(sellDate)) { candlesAndOrders[sellDate] = new List <OrderInfo>(); } candlesAndOrders[buyDate].Add(item); candlesAndOrders[sellDate].Add(item); } candlesAndOrders.OrderBy(x => x.Key); var originalEquity = originalBalance; double finalEquity = 0f; var equityOrders = new Dictionary <string, OrderInfo>(); List <OrderResultInfo> finalOrders = new List <OrderResultInfo>(); double totalProfits = 0f; var tempCount = 0; var alreadyAddedIds = new List <string>(); foreach (var cao in candlesAndOrders) { var currDate = cao.Key; var orderList = cao.Value; foreach (var item in orderList) { tempCount++; var isSell = false; if (alreadyAddedIds.Contains(item.Id)) { isSell = true; } else { alreadyAddedIds.Add(item.Id); } var ord = item; var id = ord.Id; string type; DateTime time; double orderPrice = 0.0f;; double size = ord.BuyAmountInUSD; double profitLoss = 0f; double balance = 0f; if (isSell == false) // buy { originalBalance -= ord.BuyAmountInUSD; originalBalance = Math.Round(originalBalance, 2); time = ord.BuyCandle.OpenTime; type = "Buy"; orderPrice = Math.Round(ord.BuyPrice, 2); equityOrders[ord.Id] = ord; } else // sell { var tUsd = ord.TotalUSD(); tUsd = Math.Round(tUsd, 2); originalBalance += tUsd; originalBalance = Math.Round(originalBalance, 2); time = ord.SellCandle.OpenTime; type = "Sell"; var tmpPL = Math.Round(tUsd - ord.BuyAmountInUSD, 2); profitLoss = tmpPL; balance = originalBalance; balance = Math.Round(balance, 2); totalProfits += tmpPL; orderPrice = Math.Round(ord.GetSellPrice(), 2); equityOrders.Remove(ord.Id); } size = Math.Round(size, 8); var finalBalance = balance;// (isSell) ? "$ " + balance.ToString() : ""; finalEquity = 0f; CandleInfo tempCandle = (isSell) ? orderList[0].SellCandle : orderList[0].BuyCandle; double ttttemp = 0f; foreach (var eOrd in equityOrders.Values) { finalEquity += tempCandle.MidPrice * ord.CoinAmount; ttttemp += ord.BuyAmountInUSD; } ttttemp = Math.Round(ttttemp, 3); finalEquity = Math.Round(finalEquity, 3); var ori = new OrderResultInfo() { Id = id.ToString(), Time = time, Type = type, OrderPrice = orderPrice, OrderAmountUSD = size, ProfitLoss = profitLoss, FinalBalance = finalBalance, FinalEquity = finalEquity }; finalOrders.Add(ori); } } var finalPL = Math.Round(originalBalance - startingBalance, 2); finalOrders.Add(new OrderResultInfo() { Id = "", Time = DateTime.MinValue, Type = "blank", OrderPrice = 0f, OrderAmountUSD = 0f, ProfitLoss = 0f, FinalBalance = 0f }); finalOrders.Add(new OrderResultInfo() { Id = "", Time = DateTime.MinValue, Type = "blank2", OrderPrice = 0f, OrderAmountUSD = 0f, ProfitLoss = finalPL, FinalBalance = originalBalance }); var final = JsonConvert.SerializeObject(finalOrders); return(final); }
public ActionResult <string> Get(string Symbol) { var RequestData = new Dictionary <string, string>(); RequestData = CryptoGlobals.GetRequestData(Request); Symbol = Symbol.Replace("-", ""); var interval = KlineInterval.FifteenMinutes; var start = new DateTime(2019, 7, 1); var end = DateTime.Now; var symbol = Symbol.ToUpper(); var liteJson = false; var justOK = false; var jsonP = ""; if (RequestData.ContainsKey("interval")) { var tempInterval = RequestData["interval"].ToString(); interval = CryptoGlobals.GetKlineFromString(tempInterval); } else { return("interval missing"); } Response.Headers.Add("Access-Control-Allow-Origin", "*"); if (RequestData.ContainsKey("jsonp")) { jsonP = RequestData["jsonp"]; } if (RequestData.ContainsKey("justok")) { justOK = true; } if (RequestData.ContainsKey("lite") && RequestData["lite"] == "true") { liteJson = true; } if (RequestData.ContainsKey("start") && RequestData.ContainsKey("end")) { var startS = RequestData["start"].ToString(); var endS = RequestData["end"].ToString(); DateTime dt1; if (DateTime.TryParseExact(startS, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out dt1)) { start = dt1; } else { return("Invalid start date"); } DateTime dt2; if (DateTime.TryParseExact(endS, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out dt2)) { end = dt2.AddDays(1); // because we are NOT getting time. So we want to get UNTIL the next day if (end > DateTime.Now) { end = DateTime.Now; } } else { return("Invalid end date"); } } else { return(JsonConvert.SerializeObject(new KeyValuePair <string, string>("Error", "You have to use start & date query"))); } if (!CandleHelper.Jobs.ContainsKey(symbol) || (CandleHelper.Jobs.ContainsKey(symbol) && CandleHelper.Jobs[symbol].Done)) { if (CandleHelper.Jobs.ContainsKey(symbol)) { CandleHelper.Jobs.Remove(symbol); } DateTime small = DateTime.MinValue; DateTime big = DateTime.MinValue; List <CandleInfo> allCandles = null; if (CandleHelper.CandlesAvailable(symbol, interval, start, end, out small, out big, out allCandles)) { var finalS = ""; if (justOK) { finalS = "ok"; } else { if (liteJson) { var temp = new List <CandleInfo>(); foreach (var item in allCandles) { temp.Add(item); // timestamp, o,h,l,c // highchart requires timestamp*1000 or else dates are invalid } finalS = JsonConvert.SerializeObject(temp); } else { finalS = JsonConvert.SerializeObject(allCandles); } } //Response.ContentType = "application/javascript"; if (jsonP != "") { return(jsonP + "(" + finalS + ")"); } return(finalS); // let's retrieve em all?? return("Small: " + small.ToString() + Environment.NewLine + "Big: " + big.ToString()); } else { if (big == DateTime.MinValue) { big = start; } else { big = big.MinusKlineInterval(interval).MinusKlineInterval(interval); } CandleHelper.Jobs[symbol] = new CandleJob(symbol, start, end, interval); // we just started the job CandleHelper.Jobs[symbol].StartWork(); return("working"); } } else { return("working"); } }
public static void FillMarketsInDB(bool updatePrices = true) { bool shouldUpdate = false; var tempDt = DBHelper.GetDataTable("SELECT * FROM Markets"); if (tempDt.Rows.Count > 0) { // we already have markets. But maybe update the prices. if (!updatePrices) { return; } shouldUpdate = true; } var markets24 = CryptoGlobals.adminBinanceClient.Get24HPricesList(); if (markets24 != null && markets24.Data != null && markets24.Data.Count() > 0) { // all good } else { return; } var finalMarkets = new List <Binance24HPrice>(); foreach (var item in markets24.Data) { if (CryptoGlobals.GoodMarkets.Contains(item.Symbol)) { finalMarkets.Add(item); } } List <SQLiteCommand> list = new List <SQLiteCommand>(); foreach (var item in finalMarkets) { SQLiteCommand com = new SQLiteCommand(); if (!shouldUpdate) { com.CommandText = "INSERT OR IGNORE INTO Markets " + "(Symbol,Enabled,Volume,FirstCandleTime,LastPrice) " + "VALUES (@Symbol,@Enabled,@Volume,@FirstCandleTime,@LastPrice)"; } else { com.CommandText = "UPDATE Markets SET LastPrice=@LastPrice WHERE Symbol=@Symbol"; } com.Parameters.AddWithValue("@Volume", item.QuoteVolume); com.Parameters.AddWithValue("@FirstCandleTime", CandleHelper.GetFirstCandleDate(item.Symbol).ToSqlDateString()); com.Parameters.AddWithValue("@Enabled", 1); com.Parameters.AddWithValue("@Symbol", item.Symbol); com.Parameters.AddWithValue("@LastPrice", item.LastPrice); list.Add(com); } DBHelper.BulkExecuteNonQuery(list); }
private async Task RunAsync(CancellationToken token) { while (!token.IsCancellationRequested) { // get live orders if (AllMarkets == null) { RefreshMarkets(); } if (AllUsers == null) { RefreshUsers(); } if (AllContexts == null) { AllContexts = new Dictionary <int, Context>(); } foreach (DataRow row in DBHelper.dtJobs.Rows) { var job = new JobInfo(row); if (job.IsLive) { // grab the latest candles var kline = CryptoGlobals.GetKlineFromString(job.Interval); var c = CryptoGlobals.LastCandleInDB(AllMarkets[job.MarketId].Symbol, kline); var shouldGetCandles = false; var firstDate = DateTime.Today.AddDays(60); if (c == null) { // ouch never got any candles :( shouldGetCandles = true; } else { // we got, that's our start date if (c.OpenTime < CryptoGlobals.MinusKlineInterval(DateTime.UtcNow, kline)) { shouldGetCandles = true; firstDate = c.OpenTime; } } if (shouldGetCandles) { CandleHelper.RetrieveCandles(AllMarkets[job.MarketId].Symbol, kline, firstDate, DateTime.Now.AddDays(1)); // TAKE IT ALLLLL } if (!AllUsers.ContainsKey(job.UserId)) { AllUsers = null; RefreshUsers(); if (!AllUsers.ContainsKey(job.UserId)) { // invalid user continue; } } var user = AllUsers[job.UserId]; // get candles var crows = DBHelper.GetDataTable("SELECT * FROM Candles WHERE Symbol='" + AllMarkets[job.MarketId].Symbol + "' AND Interval='" + job.Interval + "'"); // haha crows List <CandleInfo> CurrentCandles = new List <CandleInfo>(); foreach (DataRow crow in crows.Rows) { var tempC = new CandleInfo(crow); CurrentCandles.Add(tempC); } StrategyOptions myStrat = null; var strat = DBHelper.GetDataTable("SELECT * from Strategies where Id=" + job.ScriptId); if (strat.Rows.Count > 0) { myStrat = (new StrategyInfo(strat.Rows[0])).Options; } else { continue; // cancel!?!? } Context cxt = null; if (!AllContexts.ContainsKey(job.Id)) { cxt = new Context(CurrentCandles); cxt.IsLive = true; cxt.User = user; cxt.ActiveStrategyOptions = new StrategyOptions() { BacktestStartingBalance = 1000000, Fees = 0, MaxOpenOrders = myStrat.MaxOpenOrders, MinutesInBetweenOrders = myStrat.MinutesInBetweenOrders }; } else { cxt = AllContexts[job.Id]; cxt.RawCandles = CurrentCandles; } var l = new List <CandleInfo>(); if (CurrentCandles.Count == 0) { continue; } cxt.RawCandles = CurrentCandles; if (cxt.IsLive && !cxt.IsPaper) { //var orders = CryptoGlobals.UserBinances[user.Username].GetOpenOrders(); // //foreach (var item in orders.Data) //{ // // if (item.Symbol != AllMarkets[job.MarketId].Symbol) continue; // // var t = new OrderInfo(cxt, (float)(item.Price * item.ExecutedQuantity)); // t.CoinAmount = (float)item.ExecutedQuantity; // t.IsOpen = true; // t.Id = item.ClientOrderId.ToString(); //} } else { } if (!Globals.RunScript(cxt.StrategyScript, ref cxt)) { continue; } // we now can run the script } } System.Diagnostics.Debug.WriteLine(DateTime.Now); await Task.Delay(1000); } }