{"action":"created","issue":{"url":"https://api.github.com/repos/lppkarl/Trady/issues/46","repository_url":"https://api.github.com/repos/lppkarl/Trady","labels_url":"https://api.github.com/repos/lppkarl/Trady/issues/46/labels{/name}","comments_url":"https://api.github.com/repos/lppkarl/Trady/issues/46/comments","events_url":"https://api.github.com/repos/lppkarl/Trady/issues/46/events","html_url":"https://github.com/lppkarl/Trady/issues/46","id":306161025,"number":46,"title":"Problem with TransformingCandles, InvalidTimeframeException","user":{"login":"hidden1994","id":35395198,"avatar_url":"https://avatars3.githubusercontent.com/u/35395198?v=4","gravatar_id":"","url":"https://api.github.com/users/hidden1994","html_url":"https://github.com/hidden1994","followers_url":"https://api.github.com/users/hidden1994/followers","following_url":"https://api.github.com/users/hidden1994/following{/other_user}","gists_url":"https://api.github.com/users/hidden1994/gists{/gist_id}","starred_url":"https://api.github.com/users/hidden1994/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hidden1994/subscriptions","organizations_url":"https://api.github.com/users/hidden1994/orgs","repos_url":"https://api.github.com/users/hidden1994/repos","events_url":"https://api.github.com/users/hidden1994/events{/privacy}","received_events_url":"https://api.github.com/users/hidden1994/received_events","type":"User","site_admin":false},"labels":[{"id":491702121,"url":"https://api.github.com/repos/lppkarl/Trady/labels/help%20wanted","name":"help wanted","color":"128A0C","default":true}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2018-03-17T14:33:17Z","updated_at":"2018-03-26T09:24:36Z","closed_at":null,"author_association":"NONE","body":"Today faced problem with converting candles from lower interval(i.e. 15min) to higher interval(i.e. 30m or 1h)\r\n\r\nApplication perfectly works on my home pc, but refuses to work on another pc.\r\nI am in russia, moscow (+3 UTC), he is in somewhere in canada(-5 UTC).\r\n\r\nSo i looked into Transform extension function and sibling methods and heres what i found:\r\n\r\nTrady/CandleExtension.cs\r\nIn method **IsTimeframesValid**\r\nthis method works with 2 candles as i understood and for me \r\n\r\nvar candleEndTime = periodInstance.NextTimestamp(candles.ElementAt(i).DateTime);\r\n\r\nproduces right time and in next if condition it doesnt fall through and doesnt produce false result.\r\n\r\nhowever **periodInstance.NextTimestamp** from his pc changes last numbers in timestamps\r\nAs i understood in just rounds timestamp\r\n\r\non my pc:\r\n23:29:59 00:00 -> 23:30:00 00:00\r\nand then compared with\r\n23:44:59 00:00\r\n\r\non his pc\r\n23:29:59 00:00 -> 23:30:00 -04:00\r\nand then compared with\r\n23:44:59 00:00\r\n\r\nThis somehow produces error, i dont know why, but for now i just made my own transform methods where i doesnt use **periodInstance.NextTimestamp** and just do straight compare\r\n"},"comment":{"url":"https://api.github.com/repos/lppkarl/Trady/issues/comments/376102429","html_url":"https://github.com/lppkarl/Trady/issues/46#issuecomment-376102429","issue_url":"https://api.github.com/repos/lppkarl/Trady/issues/46","id":376102429,"user":{"login":"neonVoice","id":21147332,"avatar_url":"https://avatars3.githubusercontent.com/u/21147332?v=4","gravatar_id":"","url":"https://api.github.com/users/neonVoice","html_url":"https://github.com/neonVoice","followers_url":"https://api.github.com/users/neonVoice/followers","following_url":"https://api.github.com/users/neonVoice/following{/other_user}","gists_url":"https://api.github.com/users/neonVoice/gists{/gist_id}","starred_url":"https://api.github.com/users/neonVoice/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/neonVoice/subscriptions","organizations_url":"https://api.github.com/users/neonVoice/orgs","repos_url":"https://api.github.com/users/neonVoice/repos","events_url":"https://api.github.com/users/neonVoice/events{/privacy}","received_events_url":"https://api.github.com/users/neonVoice/received_events","type":"User","site_admin":false},"created_at":"2018-03-26T09:24:36Z","updated_at":"2018-03-26T09:24:36Z","author_association":"NONE","body":"Importer from binance:\r\n```C#\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Threading;\r\nusing System.Threading.Tasks;\r\nusing Binance.Net;\r\nusing Binance.Net.Objects;\r\nusing Trady.Core;\r\nusing Trady.Core.Infrastructure;\r\nusing Trady.Core.Period;\r\n\r\nnamespace BTPIndicatorsWin.General.Trading\r\n{\r\n  internal class BinanceImporter : IImporter\r\n  {\r\n    public async Task<IReadOnlyList<IOhlcv>> ImportAsync(string symbol, DateTime? startTime = null,\r\n      DateTime? endTime = null, PeriodOption period = PeriodOption.Daily,\r\n      CancellationToken token = default(CancellationToken))\r\n    {\r\n      IReadOnlyList<IOhlcv> candlesList;\r\n\r\n      if (startTime == null)\r\n        startTime = DateTime.UtcNow.AddHours(-10);\r\n\r\n      if (endTime == null)\r\n        endTime = DateTime.UtcNow;\r\n\r\n      var interval = ConvertPeriodToKline(period);\r\n\r\n      using (var client = new BinanceClient())\r\n      {\r\n        candlesList = await GetCandlesForSymbol(client, symbol, interval,\r\n          startTime.Value, endTime.Value);\r\n      }\r\n\r\n      return candlesList;\r\n    }\r\n\r\n    private async Task<IReadOnlyList<IOhlcv>> GetCandlesForSymbol(BinanceClient client, string symbol,\r\n      KlineInterval interval, DateTime startTime, DateTime endTime)\r\n    {\r\n      var binanceKlinesTask = await client.GetKlinesAsync(symbol, interval, startTime, endTime);\r\n\r\n      var binanceKlines = binanceKlinesTask.Data;\r\n\r\n      var candles = new List<IOhlcv>();\r\n\r\n      foreach (var binanceKline in binanceKlines)\r\n      {\r\n        var candle = new Candle(binanceKline.CloseTime, binanceKline.Open, binanceKline.High,\r\n          binanceKline.Low, binanceKline.Close, binanceKline.Volume);\r\n\r\n        candles.Add(candle);\r\n      }\r\n\r\n      return candles;\r\n    }\r\n\r\n    private KlineInterval ConvertPeriodToKline(PeriodOption period)\r\n    {\r\n      KlineInterval interval;\r\n\r\n      switch (period)\r\n      {\r\n        case PeriodOption.PerSecond:\r\n          interval = KlineInterval.OneMinute; // wrong\r\n          break;\r\n        case PeriodOption.PerMinute:\r\n          interval = KlineInterval.OneMinute;\r\n          break;\r\n        case PeriodOption.Per5Minute:\r\n          interval = KlineInterval.FiveMinutes;\r\n          break;\r\n        case PeriodOption.Per10Minute:\r\n          interval = KlineInterval.FiveteenMinutes; // wrong\r\n          break;\r\n        case PeriodOption.Per15Minute:\r\n          interval = KlineInterval.FiveteenMinutes;\r\n          break;\r\n        case PeriodOption.Per30Minute:\r\n          interval = KlineInterval.ThirtyMinutes;\r\n          break;\r\n        case PeriodOption.Hourly:\r\n          interval = KlineInterval.OneHour;\r\n          break;\r\n        case PeriodOption.BiHourly:\r\n          interval = KlineInterval.TwoHour;\r\n          break;\r\n        case PeriodOption.Daily:\r\n          interval = KlineInterval.OneDay;\r\n          break;\r\n        case PeriodOption.Weekly:\r\n          interval = KlineInterval.OneWeek;\r\n          break;\r\n        case PeriodOption.Monthly:\r\n          interval = KlineInterval.OneMonth;\r\n          break;\r\n        default:\r\n          throw new ArgumentOutOfRangeException(nameof(period), period, null);\r\n      }\r\n\r\n      return interval;\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nGetting candles history for pair and storing in in \"associate array\":\r\n```C#\r\n    private static async Task<PairCandles> GetPairCandles(string pairName) {\r\n      var pairCandles = await Importer.ImportAsync(pairName, DateTime.UtcNow.AddHours(-15),\r\n        DateTime.UtcNow, PeriodOption.Per15Minute);\r\n\r\n      return new PairCandles(pairCandles, pairName);\r\n    }\r\n```\r\nAfter returning PairCandles, im immideately start async processing job for it:\r\n```C#\r\n    private static async Task ProcessFilteredPairs() {\r\n      Console.WriteLine(\"ProcessFilteredPairs -\");\r\n      var cnt = 0;\r\n\r\n      foreach (var pairName in _filteredPairsList) {\r\n        if (GetOnlyOne) {\r\n          if (cnt++ == 1) {\r\n            break;\r\n          }\r\n        }\r\n\r\n        // gets PAIR candles\r\n        var pairCandles = await GetPairCandles(pairName);\r\n        // start analysis on candles asynchronously\r\n        AnalysisTasks.Add(Task.Run(() => FillTradingEnabledLines(pairCandles)));\r\n      }\r\n      // wait for all analysis tasks to end\r\n      await Task.WhenAll(AnalysisTasks);\r\n      Console.WriteLine(\"ProcessFilteredPairs +\");\r\n    }\r\n```\r\n\r\nFillTradingenabledLines -> ProcessPairCandles:\r\n```C#\r\n    private static void FillTradingEnabledLines(PairCandles pairCandles) {\r\n      Console.WriteLine(\"FillTradingEnabledLines - \" + pairCandles.Pair);\r\n      var buyProbability = ProcessPairCandles(pairCandles);\r\n      var tradingEnabledString = pairCandles.Pair + Config.LineGeneration.SuffixTradingEnabled;\r\n      tradingEnabledString += buyProbability > Config.Threshold ? \"true\" : \"false\";\r\n      TradingEnabledLines.Add(tradingEnabledString);\r\n\r\n      ProcessedCandles.Add(pairCandles.Pair, (\"BUY\", buyProbability));\r\n      Console.WriteLine(\"FillTradingEnabledLines + \" + pairCandles.Pair);\r\n    }\r\n```\r\nProcessPairCandles -> AnalyzePair:\r\n```C#\r\n    private static double ProcessPairCandles(PairCandles pairCandles) {\r\n      //Console.WriteLine(\"ProcessPairCandles -\");\r\n      double totalBuyProbability = 0;\r\n\r\n      foreach (var period in Config.Periods) {\r\n        var buyProbability = AnalyzePair(pairCandles, period);\r\n\r\n        if (double.IsNaN(buyProbability)) {\r\n          buyProbability = 0.5;\r\n        }\r\n\r\n        var coefficient = PeriodCoefficients[period.Time];\r\n        var multiplied = buyProbability * coefficient;\r\n\r\n        //Console.WriteLine($\"{pairCandles.Pair} BUY - {buyProbability:0.00} * {coefficient:0.00} = {multiplied:0.00}\");\r\n        totalBuyProbability += multiplied;\r\n      }\r\n\r\n      // Gets Mean BuyProbability from N Periods (Fast + Slow)\r\n      var newTotal = totalBuyProbability / Config.Periods.Count;\r\n\r\n      //Console.WriteLine($\"{pairCandles.Pair} BUY - {totalBuyProbability:0.00} / {Config.Periods.Count} = {newTotal:0.00} <- TOTAL\");\r\n\r\n      //Console.WriteLine(\"ProcessPairCandles +\");\r\n      return newTotal;\r\n    }\r\n```\r\nAnalyzePair -> Extension methods\r\n\r\n```C#\r\n    private static double AnalyzePair(PairCandles pairCandles, Config.Period period) {\r\n      //Console.WriteLine(\"AnalyzePair -\");\r\n      var candles = TradyExtensions.ConvertCandlesToTime(pairCandles.Candles, period.Time);\r\n/*\r\n...\r\n*/\r\n      }\r\n```\r\n\r\nExtension ConvertCandlesToTime:\r\n```C#\r\n    public static IReadOnlyList<IOhlcv> ConvertCandlesToTime(IReadOnlyList<IOhlcv> inputCandles, string periodTime)\r\n    {\r\n      //Console.WriteLine(\"ConvertCandlesToTime -\");\r\n\r\n      var periodOption = GetPeriodFromConfig(periodTime);\r\n\r\n      //Console.WriteLine($\"periodTime - {periodTime}\\tperiodOption - {periodOption}\");\r\n      // Supported period: PerSecond, PerMinute, Per15Minutes, Per30Minutes, Hourly, BiHourly, Daily, Weekly, Monthly\r\n\r\n      IReadOnlyList<IOhlcv> outputCandles;\r\n      try\r\n      {\r\n        switch (periodOption)\r\n        {\r\n          case PeriodOption.PerSecond:\r\n            outputCandles = Transform<Per15Minute, PerSecond>(inputCandles);\r\n            break;\r\n          case PeriodOption.PerMinute:\r\n            outputCandles = Transform<Per15Minute, PerMinute>(inputCandles);\r\n            break;\r\n          case PeriodOption.Per5Minute:\r\n            outputCandles = Transform<Per15Minute, Per5Minute>(inputCandles);\r\n            break;\r\n          case PeriodOption.Per10Minute:\r\n            outputCandles = Transform<Per15Minute, Per10Minute>(inputCandles);\r\n            break;\r\n          case PeriodOption.Per15Minute:\r\n            outputCandles = Transform<Per15Minute, Per15Minute>(inputCandles);\r\n            break;\r\n          case PeriodOption.Per30Minute:\r\n            outputCandles = Transform<Per15Minute, Per30Minute>(inputCandles);\r\n            break;\r\n          case PeriodOption.Hourly:\r\n            outputCandles = Transform<Per15Minute, Hourly>(inputCandles);\r\n            break;\r\n          case PeriodOption.BiHourly:\r\n            outputCandles = Transform<Per15Minute, BiHourly>(inputCandles);\r\n            break;\r\n          case PeriodOption.Daily:\r\n            outputCandles = Transform<Per15Minute, Daily>(inputCandles);\r\n            break;\r\n          case PeriodOption.Weekly:\r\n            outputCandles = Transform<Per15Minute, Weekly>(inputCandles);\r\n            break;\r\n          case PeriodOption.Monthly:\r\n            outputCandles = Transform<Per15Minute, Monthly>(inputCandles);\r\n            break;\r\n          default:\r\n            outputCandles = inputCandles;\r\n            break;\r\n        }\r\n      }\r\n      catch (Exception e)\r\n      {\r\n        outputCandles = inputCandles;\r\n      }\r\n\r\n      //Console.WriteLine(\"ConvertCandlesToTime +\");\r\n      return outputCandles;\r\n    }\r\n```\r\n\r\nHere Transform operation is mine with changed code from your library."}}
{"actor":{"display_login":"neonVoice"}}