We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Exception: volume is not double
## Step 1: Have you search for this issue before posting it?

Yes and talked about it on slack.

## Step 2: Describe your environment

  * Operating system: Ubuntu 19.10
  * Python Version: Python 3.7.5
  * CCXT version: ccxt==1.22.61
  * Branch: Develop
  * Last Commit ID: 43add0b1594f03379e61ef014b80a0a2723914de
  
## Step 3: Describe the problem:

When running hyperopt using downloaded data an exception will be thown.
**Exception: volume is not double**

When doing some troubleshooting it only affects some of the downloaded data (not all pairs)
XRP/BTC
```
date      datetime64[ns, UTC]
open                  float64
high                  float64
low                   float64
close                 float64
volume                  int64
dtype: object
```
### Steps to reproduce:

  1. Not sure :-/
  2. The main indicator that throws error is MFI (dataframe['mfi'] = ta.MFI(dataframe))
  
### Observed Results:

Unable to run hyperopt

### Relevant code exceptions or logs:

  ```
2020-02-20 22:47:28,025 - freqtrade - ERROR - Fatal exception!
Traceback (most recent call last):
  File "/opt/tradebot/freqtrade/.env/lib/python3.7/site-packages/talib/__init__.py", line 20, in wrapper
    for arg in chain(args, kwargs.values())
StopIteration

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/freqtrade/freqtrade/main.py", line 36, in main
    return_code = args['func'](args)
  File "/freqtrade/freqtrade/commands/optimize_commands.py", line 76, in start_hyperopt
    hyperopt.start()
  File "/freqtrade/freqtrade/optimize/hyperopt.py", line 488, in start
    preprocessed = self.backtesting.strategy.tickerdata_to_dataframe(data)
  File "/freqtrade/freqtrade/strategy/interface.py", line 448, in tickerdata_to_dataframe
    for pair, pair_data in tickerdata.items()}
  File "/freqtrade/freqtrade/strategy/interface.py", line 448, in <dictcomp>
    for pair, pair_data in tickerdata.items()}
  File "/freqtrade/freqtrade/strategy/interface.py", line 464, in advise_indicators
    return self.populate_indicators(dataframe, metadata)
  File "/freqtrade/user_data/strategies/MyDev.py", line 205, in populate_indicators
    dataframe['mfi'] = ta.MFI(dataframe)
  File "talib/_abstract.pxi", line 352, in talib._ta_lib.Function.__call__
  File "talib/_abstract.pxi", line 383, in talib._ta_lib.Function.__call_function
  File "/opt/tradebot/freqtrade/.env/lib/python3.7/site-packages/talib/__init__.py", line 24, in wrapper
    return func(*args, **kwargs)
  File "talib/_func.pxi", line 8454, in talib._ta_lib.MFI
Exception: volume is not double

  ```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `freqtrade/data/history/jsondatahandler.py`
Content:
```
1 import re
2 from pathlib import Path
3 from typing import Dict, List, Optional
4 
5 import numpy as np
6 from pandas import DataFrame, read_json, to_datetime
7 
8 from freqtrade import misc
9 from freqtrade.configuration import TimeRange
10 from freqtrade.constants import DEFAULT_DATAFRAME_COLUMNS
11 
12 from .idatahandler import IDataHandler
13 
14 
15 class JsonDataHandler(IDataHandler):
16 
17     _use_zip = False
18     _columns = DEFAULT_DATAFRAME_COLUMNS
19 
20     @classmethod
21     def ohlcv_get_pairs(cls, datadir: Path, timeframe: str) -> List[str]:
22         """
23         Returns a list of all pairs with ohlcv data available in this datadir
24         for the specified timeframe
25         :param datadir: Directory to search for ohlcv files
26         :param timeframe: Timeframe to search pairs for
27         :return: List of Pairs
28         """
29 
30         _tmp = [re.search(r'^(\S+)(?=\-' + timeframe + '.json)', p.name)
31                 for p in datadir.glob(f"*{timeframe}.{cls._get_file_extension()}")]
32         # Check if regex found something and only return these results
33         return [match[0].replace('_', '/') for match in _tmp if match]
34 
35     def ohlcv_store(self, pair: str, timeframe: str, data: DataFrame) -> None:
36         """
37         Store data in json format "values".
38             format looks as follows:
39             [[<date>,<open>,<high>,<low>,<close>]]
40         :param pair: Pair - used to generate filename
41         :timeframe: Timeframe - used to generate filename
42         :data: Dataframe containing OHLCV data
43         :return: None
44         """
45         filename = self._pair_data_filename(self._datadir, pair, timeframe)
46         _data = data.copy()
47         # Convert date to int
48         _data['date'] = _data['date'].astype(np.int64) // 1000 // 1000
49 
50         # Reset index, select only appropriate columns and save as json
51         _data.reset_index(drop=True).loc[:, self._columns].to_json(
52             filename, orient="values",
53             compression='gzip' if self._use_zip else None)
54 
55     def _ohlcv_load(self, pair: str, timeframe: str,
56                     timerange: Optional[TimeRange] = None,
57                     ) -> DataFrame:
58         """
59         Internal method used to load data for one pair from disk.
60         Implements the loading and conversion to a Pandas dataframe.
61         Timerange trimming and dataframe validation happens outside of this method.
62         :param pair: Pair to load data
63         :param timeframe: Ticker timeframe (e.g. "5m")
64         :param timerange: Limit data to be loaded to this timerange.
65                         Optionally implemented by subclasses to avoid loading
66                         all data where possible.
67         :return: DataFrame with ohlcv data, or empty DataFrame
68         """
69         filename = self._pair_data_filename(self._datadir, pair, timeframe)
70         if not filename.exists():
71             return DataFrame(columns=self._columns)
72         pairdata = read_json(filename, orient='values')
73         pairdata.columns = self._columns
74         pairdata['date'] = to_datetime(pairdata['date'],
75                                        unit='ms',
76                                        utc=True,
77                                        infer_datetime_format=True)
78         return pairdata
79 
80     def ohlcv_purge(self, pair: str, timeframe: str) -> bool:
81         """
82         Remove data for this pair
83         :param pair: Delete data for this pair.
84         :param timeframe: Ticker timeframe (e.g. "5m")
85         :return: True when deleted, false if file did not exist.
86         """
87         filename = self._pair_data_filename(self._datadir, pair, timeframe)
88         if filename.exists():
89             filename.unlink()
90             return True
91         return False
92 
93     def ohlcv_append(self, pair: str, timeframe: str, data: DataFrame) -> None:
94         """
95         Append data to existing data structures
96         :param pair: Pair
97         :param timeframe: Timeframe this ohlcv data is for
98         :param data: Data to append.
99         """
100         raise NotImplementedError()
101 
102     @classmethod
103     def trades_get_pairs(cls, datadir: Path) -> List[str]:
104         """
105         Returns a list of all pairs for which trade data is available in this
106         :param datadir: Directory to search for ohlcv files
107         :return: List of Pairs
108         """
109         _tmp = [re.search(r'^(\S+)(?=\-trades.json)', p.name)
110                 for p in datadir.glob(f"*trades.{cls._get_file_extension()}")]
111         # Check if regex found something and only return these results to avoid exceptions.
112         return [match[0].replace('_', '/') for match in _tmp if match]
113 
114     def trades_store(self, pair: str, data: List[Dict]) -> None:
115         """
116         Store trades data (list of Dicts) to file
117         :param pair: Pair - used for filename
118         :param data: List of Dicts containing trade data
119         """
120         filename = self._pair_trades_filename(self._datadir, pair)
121         misc.file_dump_json(filename, data, is_zip=self._use_zip)
122 
123     def trades_append(self, pair: str, data: List[Dict]):
124         """
125         Append data to existing files
126         :param pair: Pair - used for filename
127         :param data: List of Dicts containing trade data
128         """
129         raise NotImplementedError()
130 
131     def trades_load(self, pair: str, timerange: Optional[TimeRange] = None) -> List[Dict]:
132         """
133         Load a pair from file, either .json.gz or .json
134         # TODO: respect timerange ...
135         :param pair: Load trades for this pair
136         :param timerange: Timerange to load trades for - currently not implemented
137         :return: List of trades
138         """
139         filename = self._pair_trades_filename(self._datadir, pair)
140         tradesdata = misc.file_load_json(filename)
141         if not tradesdata:
142             return []
143 
144         return tradesdata
145 
146     def trades_purge(self, pair: str) -> bool:
147         """
148         Remove data for this pair
149         :param pair: Delete data for this pair.
150         :return: True when deleted, false if file did not exist.
151         """
152         filename = self._pair_trades_filename(self._datadir, pair)
153         if filename.exists():
154             filename.unlink()
155             return True
156         return False
157 
158     @classmethod
159     def _pair_data_filename(cls, datadir: Path, pair: str, timeframe: str) -> Path:
160         pair_s = misc.pair_to_filename(pair)
161         filename = datadir.joinpath(f'{pair_s}-{timeframe}.{cls._get_file_extension()}')
162         return filename
163 
164     @classmethod
165     def _get_file_extension(cls):
166         return "json.gz" if cls._use_zip else "json"
167 
168     @classmethod
169     def _pair_trades_filename(cls, datadir: Path, pair: str) -> Path:
170         pair_s = misc.pair_to_filename(pair)
171         filename = datadir.joinpath(f'{pair_s}-trades.{cls._get_file_extension()}')
172         return filename
173 
174 
175 class JsonGzDataHandler(JsonDataHandler):
176 
177     _use_zip = True
178
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/freqtrade/data/history/jsondatahandler.py b/freqtrade/data/history/jsondatahandler.py
--- a/freqtrade/data/history/jsondatahandler.py
+++ b/freqtrade/data/history/jsondatahandler.py
@@ -69,7 +69,9 @@
         filename = self._pair_data_filename(self._datadir, pair, timeframe)
         if not filename.exists():
             return DataFrame(columns=self._columns)
-        pairdata = read_json(filename, orient='values')
+        pairdata = read_json(filename, orient='values',
+                             dtype={'open': 'float', 'high': 'float',
+                                    'low': 'float', 'close': 'float', 'volume': 'float'})
         pairdata.columns = self._columns
         pairdata['date'] = to_datetime(pairdata['date'],
                                        unit='ms',

{"golden_diff": "diff --git a/freqtrade/data/history/jsondatahandler.py b/freqtrade/data/history/jsondatahandler.py\n--- a/freqtrade/data/history/jsondatahandler.py\n+++ b/freqtrade/data/history/jsondatahandler.py\n@@ -69,7 +69,9 @@\n         filename = self._pair_data_filename(self._datadir, pair, timeframe)\n         if not filename.exists():\n             return DataFrame(columns=self._columns)\n-        pairdata = read_json(filename, orient='values')\n+        pairdata = read_json(filename, orient='values',\n+                             dtype={'open': 'float', 'high': 'float',\n+                                    'low': 'float', 'close': 'float', 'volume': 'float'})\n         pairdata.columns = self._columns\n         pairdata['date'] = to_datetime(pairdata['date'],\n                                        unit='ms',\n", "issue": "Exception: volume is not double\n## Step 1: Have you search for this issue before posting it?\r\n\r\nYes and talked about it on slack.\r\n\r\n## Step 2: Describe your environment\r\n\r\n  * Operating system: Ubuntu 19.10\r\n  * Python Version: Python 3.7.5\r\n  * CCXT version: ccxt==1.22.61\r\n  * Branch: Develop\r\n  * Last Commit ID: 43add0b1594f03379e61ef014b80a0a2723914de\r\n  \r\n## Step 3: Describe the problem:\r\n\r\nWhen running hyperopt using downloaded data an exception will be thown.\r\n**Exception: volume is not double**\r\n\r\nWhen doing some troubleshooting it only affects some of the downloaded data (not all pairs)\r\nXRP/BTC\r\n```\r\ndate      datetime64[ns, UTC]\r\nopen                  float64\r\nhigh                  float64\r\nlow                   float64\r\nclose                 float64\r\nvolume                  int64\r\ndtype: object\r\n```\r\n### Steps to reproduce:\r\n\r\n  1. Not sure :-/\r\n  2. The main indicator that throws error is MFI (dataframe['mfi'] = ta.MFI(dataframe))\r\n  \r\n### Observed Results:\r\n\r\nUnable to run hyperopt\r\n\r\n### Relevant code exceptions or logs:\r\n\r\n  ```\r\n2020-02-20 22:47:28,025 - freqtrade - ERROR - Fatal exception!\r\nTraceback (most recent call last):\r\n  File \"/opt/tradebot/freqtrade/.env/lib/python3.7/site-packages/talib/__init__.py\", line 20, in wrapper\r\n    for arg in chain(args, kwargs.values())\r\nStopIteration\r\n\r\nDuring handling of the above exception, another exception occurred:\r\n\r\nTraceback (most recent call last):\r\n  File \"/freqtrade/freqtrade/main.py\", line 36, in main\r\n    return_code = args['func'](args)\r\n  File \"/freqtrade/freqtrade/commands/optimize_commands.py\", line 76, in start_hyperopt\r\n    hyperopt.start()\r\n  File \"/freqtrade/freqtrade/optimize/hyperopt.py\", line 488, in start\r\n    preprocessed = self.backtesting.strategy.tickerdata_to_dataframe(data)\r\n  File \"/freqtrade/freqtrade/strategy/interface.py\", line 448, in tickerdata_to_dataframe\r\n    for pair, pair_data in tickerdata.items()}\r\n  File \"/freqtrade/freqtrade/strategy/interface.py\", line 448, in <dictcomp>\r\n    for pair, pair_data in tickerdata.items()}\r\n  File \"/freqtrade/freqtrade/strategy/interface.py\", line 464, in advise_indicators\r\n    return self.populate_indicators(dataframe, metadata)\r\n  File \"/freqtrade/user_data/strategies/MyDev.py\", line 205, in populate_indicators\r\n    dataframe['mfi'] = ta.MFI(dataframe)\r\n  File \"talib/_abstract.pxi\", line 352, in talib._ta_lib.Function.__call__\r\n  File \"talib/_abstract.pxi\", line 383, in talib._ta_lib.Function.__call_function\r\n  File \"/opt/tradebot/freqtrade/.env/lib/python3.7/site-packages/talib/__init__.py\", line 24, in wrapper\r\n    return func(*args, **kwargs)\r\n  File \"talib/_func.pxi\", line 8454, in talib._ta_lib.MFI\r\nException: volume is not double\r\n\r\n  ```\r\n\n", "before_files": [{"content": "import re\nfrom pathlib import Path\nfrom typing import Dict, List, Optional\n\nimport numpy as np\nfrom pandas import DataFrame, read_json, to_datetime\n\nfrom freqtrade import misc\nfrom freqtrade.configuration import TimeRange\nfrom freqtrade.constants import DEFAULT_DATAFRAME_COLUMNS\n\nfrom .idatahandler import IDataHandler\n\n\nclass JsonDataHandler(IDataHandler):\n\n    _use_zip = False\n    _columns = DEFAULT_DATAFRAME_COLUMNS\n\n    @classmethod\n    def ohlcv_get_pairs(cls, datadir: Path, timeframe: str) -> List[str]:\n        \"\"\"\n        Returns a list of all pairs with ohlcv data available in this datadir\n        for the specified timeframe\n        :param datadir: Directory to search for ohlcv files\n        :param timeframe: Timeframe to search pairs for\n        :return: List of Pairs\n        \"\"\"\n\n        _tmp = [re.search(r'^(\\S+)(?=\\-' + timeframe + '.json)', p.name)\n                for p in datadir.glob(f\"*{timeframe}.{cls._get_file_extension()}\")]\n        # Check if regex found something and only return these results\n        return [match[0].replace('_', '/') for match in _tmp if match]\n\n    def ohlcv_store(self, pair: str, timeframe: str, data: DataFrame) -> None:\n        \"\"\"\n        Store data in json format \"values\".\n            format looks as follows:\n            [[<date>,<open>,<high>,<low>,<close>]]\n        :param pair: Pair - used to generate filename\n        :timeframe: Timeframe - used to generate filename\n        :data: Dataframe containing OHLCV data\n        :return: None\n        \"\"\"\n        filename = self._pair_data_filename(self._datadir, pair, timeframe)\n        _data = data.copy()\n        # Convert date to int\n        _data['date'] = _data['date'].astype(np.int64) // 1000 // 1000\n\n        # Reset index, select only appropriate columns and save as json\n        _data.reset_index(drop=True).loc[:, self._columns].to_json(\n            filename, orient=\"values\",\n            compression='gzip' if self._use_zip else None)\n\n    def _ohlcv_load(self, pair: str, timeframe: str,\n                    timerange: Optional[TimeRange] = None,\n                    ) -> DataFrame:\n        \"\"\"\n        Internal method used to load data for one pair from disk.\n        Implements the loading and conversion to a Pandas dataframe.\n        Timerange trimming and dataframe validation happens outside of this method.\n        :param pair: Pair to load data\n        :param timeframe: Ticker timeframe (e.g. \"5m\")\n        :param timerange: Limit data to be loaded to this timerange.\n                        Optionally implemented by subclasses to avoid loading\n                        all data where possible.\n        :return: DataFrame with ohlcv data, or empty DataFrame\n        \"\"\"\n        filename = self._pair_data_filename(self._datadir, pair, timeframe)\n        if not filename.exists():\n            return DataFrame(columns=self._columns)\n        pairdata = read_json(filename, orient='values')\n        pairdata.columns = self._columns\n        pairdata['date'] = to_datetime(pairdata['date'],\n                                       unit='ms',\n                                       utc=True,\n                                       infer_datetime_format=True)\n        return pairdata\n\n    def ohlcv_purge(self, pair: str, timeframe: str) -> bool:\n        \"\"\"\n        Remove data for this pair\n        :param pair: Delete data for this pair.\n        :param timeframe: Ticker timeframe (e.g. \"5m\")\n        :return: True when deleted, false if file did not exist.\n        \"\"\"\n        filename = self._pair_data_filename(self._datadir, pair, timeframe)\n        if filename.exists():\n            filename.unlink()\n            return True\n        return False\n\n    def ohlcv_append(self, pair: str, timeframe: str, data: DataFrame) -> None:\n        \"\"\"\n        Append data to existing data structures\n        :param pair: Pair\n        :param timeframe: Timeframe this ohlcv data is for\n        :param data: Data to append.\n        \"\"\"\n        raise NotImplementedError()\n\n    @classmethod\n    def trades_get_pairs(cls, datadir: Path) -> List[str]:\n        \"\"\"\n        Returns a list of all pairs for which trade data is available in this\n        :param datadir: Directory to search for ohlcv files\n        :return: List of Pairs\n        \"\"\"\n        _tmp = [re.search(r'^(\\S+)(?=\\-trades.json)', p.name)\n                for p in datadir.glob(f\"*trades.{cls._get_file_extension()}\")]\n        # Check if regex found something and only return these results to avoid exceptions.\n        return [match[0].replace('_', '/') for match in _tmp if match]\n\n    def trades_store(self, pair: str, data: List[Dict]) -> None:\n        \"\"\"\n        Store trades data (list of Dicts) to file\n        :param pair: Pair - used for filename\n        :param data: List of Dicts containing trade data\n        \"\"\"\n        filename = self._pair_trades_filename(self._datadir, pair)\n        misc.file_dump_json(filename, data, is_zip=self._use_zip)\n\n    def trades_append(self, pair: str, data: List[Dict]):\n        \"\"\"\n        Append data to existing files\n        :param pair: Pair - used for filename\n        :param data: List of Dicts containing trade data\n        \"\"\"\n        raise NotImplementedError()\n\n    def trades_load(self, pair: str, timerange: Optional[TimeRange] = None) -> List[Dict]:\n        \"\"\"\n        Load a pair from file, either .json.gz or .json\n        # TODO: respect timerange ...\n        :param pair: Load trades for this pair\n        :param timerange: Timerange to load trades for - currently not implemented\n        :return: List of trades\n        \"\"\"\n        filename = self._pair_trades_filename(self._datadir, pair)\n        tradesdata = misc.file_load_json(filename)\n        if not tradesdata:\n            return []\n\n        return tradesdata\n\n    def trades_purge(self, pair: str) -> bool:\n        \"\"\"\n        Remove data for this pair\n        :param pair: Delete data for this pair.\n        :return: True when deleted, false if file did not exist.\n        \"\"\"\n        filename = self._pair_trades_filename(self._datadir, pair)\n        if filename.exists():\n            filename.unlink()\n            return True\n        return False\n\n    @classmethod\n    def _pair_data_filename(cls, datadir: Path, pair: str, timeframe: str) -> Path:\n        pair_s = misc.pair_to_filename(pair)\n        filename = datadir.joinpath(f'{pair_s}-{timeframe}.{cls._get_file_extension()}')\n        return filename\n\n    @classmethod\n    def _get_file_extension(cls):\n        return \"json.gz\" if cls._use_zip else \"json\"\n\n    @classmethod\n    def _pair_trades_filename(cls, datadir: Path, pair: str) -> Path:\n        pair_s = misc.pair_to_filename(pair)\n        filename = datadir.joinpath(f'{pair_s}-trades.{cls._get_file_extension()}')\n        return filename\n\n\nclass JsonGzDataHandler(JsonDataHandler):\n\n    _use_zip = True\n", "path": "freqtrade/data/history/jsondatahandler.py"}], "after_files": [{"content": "import re\nfrom pathlib import Path\nfrom typing import Dict, List, Optional\n\nimport numpy as np\nfrom pandas import DataFrame, read_json, to_datetime\n\nfrom freqtrade import misc\nfrom freqtrade.configuration import TimeRange\nfrom freqtrade.constants import DEFAULT_DATAFRAME_COLUMNS\n\nfrom .idatahandler import IDataHandler\n\n\nclass JsonDataHandler(IDataHandler):\n\n    _use_zip = False\n    _columns = DEFAULT_DATAFRAME_COLUMNS\n\n    @classmethod\n    def ohlcv_get_pairs(cls, datadir: Path, timeframe: str) -> List[str]:\n        \"\"\"\n        Returns a list of all pairs with ohlcv data available in this datadir\n        for the specified timeframe\n        :param datadir: Directory to search for ohlcv files\n        :param timeframe: Timeframe to search pairs for\n        :return: List of Pairs\n        \"\"\"\n\n        _tmp = [re.search(r'^(\\S+)(?=\\-' + timeframe + '.json)', p.name)\n                for p in datadir.glob(f\"*{timeframe}.{cls._get_file_extension()}\")]\n        # Check if regex found something and only return these results\n        return [match[0].replace('_', '/') for match in _tmp if match]\n\n    def ohlcv_store(self, pair: str, timeframe: str, data: DataFrame) -> None:\n        \"\"\"\n        Store data in json format \"values\".\n            format looks as follows:\n            [[<date>,<open>,<high>,<low>,<close>]]\n        :param pair: Pair - used to generate filename\n        :timeframe: Timeframe - used to generate filename\n        :data: Dataframe containing OHLCV data\n        :return: None\n        \"\"\"\n        filename = self._pair_data_filename(self._datadir, pair, timeframe)\n        _data = data.copy()\n        # Convert date to int\n        _data['date'] = _data['date'].astype(np.int64) // 1000 // 1000\n\n        # Reset index, select only appropriate columns and save as json\n        _data.reset_index(drop=True).loc[:, self._columns].to_json(\n            filename, orient=\"values\",\n            compression='gzip' if self._use_zip else None)\n\n    def _ohlcv_load(self, pair: str, timeframe: str,\n                    timerange: Optional[TimeRange] = None,\n                    ) -> DataFrame:\n        \"\"\"\n        Internal method used to load data for one pair from disk.\n        Implements the loading and conversion to a Pandas dataframe.\n        Timerange trimming and dataframe validation happens outside of this method.\n        :param pair: Pair to load data\n        :param timeframe: Ticker timeframe (e.g. \"5m\")\n        :param timerange: Limit data to be loaded to this timerange.\n                        Optionally implemented by subclasses to avoid loading\n                        all data where possible.\n        :return: DataFrame with ohlcv data, or empty DataFrame\n        \"\"\"\n        filename = self._pair_data_filename(self._datadir, pair, timeframe)\n        if not filename.exists():\n            return DataFrame(columns=self._columns)\n        pairdata = read_json(filename, orient='values',\n                             dtype={'open': 'float', 'high': 'float',\n                                    'low': 'float', 'close': 'float', 'volume': 'float'})\n        pairdata.columns = self._columns\n        pairdata['date'] = to_datetime(pairdata['date'],\n                                       unit='ms',\n                                       utc=True,\n                                       infer_datetime_format=True)\n        return pairdata\n\n    def ohlcv_purge(self, pair: str, timeframe: str) -> bool:\n        \"\"\"\n        Remove data for this pair\n        :param pair: Delete data for this pair.\n        :param timeframe: Ticker timeframe (e.g. \"5m\")\n        :return: True when deleted, false if file did not exist.\n        \"\"\"\n        filename = self._pair_data_filename(self._datadir, pair, timeframe)\n        if filename.exists():\n            filename.unlink()\n            return True\n        return False\n\n    def ohlcv_append(self, pair: str, timeframe: str, data: DataFrame) -> None:\n        \"\"\"\n        Append data to existing data structures\n        :param pair: Pair\n        :param timeframe: Timeframe this ohlcv data is for\n        :param data: Data to append.\n        \"\"\"\n        raise NotImplementedError()\n\n    @classmethod\n    def trades_get_pairs(cls, datadir: Path) -> List[str]:\n        \"\"\"\n        Returns a list of all pairs for which trade data is available in this\n        :param datadir: Directory to search for ohlcv files\n        :return: List of Pairs\n        \"\"\"\n        _tmp = [re.search(r'^(\\S+)(?=\\-trades.json)', p.name)\n                for p in datadir.glob(f\"*trades.{cls._get_file_extension()}\")]\n        # Check if regex found something and only return these results to avoid exceptions.\n        return [match[0].replace('_', '/') for match in _tmp if match]\n\n    def trades_store(self, pair: str, data: List[Dict]) -> None:\n        \"\"\"\n        Store trades data (list of Dicts) to file\n        :param pair: Pair - used for filename\n        :param data: List of Dicts containing trade data\n        \"\"\"\n        filename = self._pair_trades_filename(self._datadir, pair)\n        misc.file_dump_json(filename, data, is_zip=self._use_zip)\n\n    def trades_append(self, pair: str, data: List[Dict]):\n        \"\"\"\n        Append data to existing files\n        :param pair: Pair - used for filename\n        :param data: List of Dicts containing trade data\n        \"\"\"\n        raise NotImplementedError()\n\n    def trades_load(self, pair: str, timerange: Optional[TimeRange] = None) -> List[Dict]:\n        \"\"\"\n        Load a pair from file, either .json.gz or .json\n        # TODO: respect timerange ...\n        :param pair: Load trades for this pair\n        :param timerange: Timerange to load trades for - currently not implemented\n        :return: List of trades\n        \"\"\"\n        filename = self._pair_trades_filename(self._datadir, pair)\n        tradesdata = misc.file_load_json(filename)\n        if not tradesdata:\n            return []\n\n        return tradesdata\n\n    def trades_purge(self, pair: str) -> bool:\n        \"\"\"\n        Remove data for this pair\n        :param pair: Delete data for this pair.\n        :return: True when deleted, false if file did not exist.\n        \"\"\"\n        filename = self._pair_trades_filename(self._datadir, pair)\n        if filename.exists():\n            filename.unlink()\n            return True\n        return False\n\n    @classmethod\n    def _pair_data_filename(cls, datadir: Path, pair: str, timeframe: str) -> Path:\n        pair_s = misc.pair_to_filename(pair)\n        filename = datadir.joinpath(f'{pair_s}-{timeframe}.{cls._get_file_extension()}')\n        return filename\n\n    @classmethod\n    def _get_file_extension(cls):\n        return \"json.gz\" if cls._use_zip else \"json\"\n\n    @classmethod\n    def _pair_trades_filename(cls, datadir: Path, pair: str) -> Path:\n        pair_s = misc.pair_to_filename(pair)\n        filename = datadir.joinpath(f'{pair_s}-trades.{cls._get_file_extension()}')\n        return filename\n\n\nclass JsonGzDataHandler(JsonDataHandler):\n\n    _use_zip = True\n", "path": "freqtrade/data/history/jsondatahandler.py"}]}