├── test
├── __init__.py
└── test_test.py
├── src
├── helper_functions.py
├── io_helper.py
├── example_helper.py
├── datetime_helper.py
├── data_model.py
├── data_loader_helper.py
├── load_augmento_data_helper.py
└── analysis_helper.py
├── requirements.txt
├── documentation
├── simple_strategy_backtest_example.png
└── simple_strategy_backtest_example_incorrect.png
├── setup.py
├── augmento_client
├── __init__.py
├── logging.ini
└── rest_api.py
├── LICENSE
├── README.md
├── .gitignore
├── examples
├── 3_plot_augmento_example_data.py
├── 1_load_augmento_example_info.py
├── 0_load_augmento_example_data.py
├── 5_write_strategy_to_csv.py
├── 4_basic_strategy_example.py
└── 2_load_bitmex_example_data.py
└── notebooks
└── 2_moving_windows.ipynb
/test/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/helper_functions.py:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | requests
2 | msgpack
3 | numpy
4 | matplotlib
5 | pprint
6 | numba
--------------------------------------------------------------------------------
/documentation/simple_strategy_backtest_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/augmento-ai/quant-reseach/HEAD/documentation/simple_strategy_backtest_example.png
--------------------------------------------------------------------------------
/documentation/simple_strategy_backtest_example_incorrect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/augmento-ai/quant-reseach/HEAD/documentation/simple_strategy_backtest_example_incorrect.png
--------------------------------------------------------------------------------
/test/test_test.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | class TestBasicFunction(unittest.TestCase):
4 |
5 | def setUp(self):
6 | pass
7 |
8 | def test_0(self):
9 | self.assertTrue(1 == 1)
10 |
11 | if __name__ == '__main__':
12 | unittest.main()
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # coding: utf-8
3 | # @Author: ArthurBernard
4 | # @Email: arthur.bernard.92@gmail.com
5 | # @Date: 2019-07-22 15:50:05
6 | # @Last modified by: ArthurBernard
7 | # @Last modified time: 2019-07-23 15:19:50
8 |
9 | # Built-in packages
10 | from setuptools import setup, find_packages
11 |
12 | # External packages
13 |
14 | # Local packages
15 |
16 | # TODO : add info parameters
17 | setup(
18 | name='augmento_client',
19 | packages=find_packages(),
20 | )
21 |
--------------------------------------------------------------------------------
/augmento_client/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # coding: utf-8
3 | # @Author: ArthurBernard
4 | # @Email: arthur.bernard.92@gmail.com
5 | # @Date: 2019-07-22 15:12:28
6 | # @Last modified by: ArthurBernard
7 | # @Last modified time: 2019-07-23 15:51:05
8 |
9 | """ Client connector to Augmento API.
10 |
11 | TODO : - websocket api.
12 |
13 | """
14 |
15 | # Built-in packages
16 |
17 | # External packages
18 |
19 | # Local packages
20 | from augmento_client import rest_api
21 | from augmento_client.rest_api import *
22 |
23 | __all__ = rest_api.__all__
24 |
--------------------------------------------------------------------------------
/src/io_helper.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | def check_path(path, create_if_not_exist=True):
4 | if not os.path.exists(path) and create_if_not_exist == True:
5 | os.makedirs(path)
6 | return True
7 | elif not os.path.exists(path) and create_if_not_exist == False:
8 | return False
9 |
10 | def list_files_in_path_os(path, filename_prefix="", filename_suffix="", recursive=True):
11 | while path[-1] == "/":
12 | path = path[:-1]
13 | all_files = []
14 | for (dirpath, dirnames, fname) in os.walk(path):
15 | all_files.extend([dirpath + "/" + el for el in fname if filename_prefix in el and filename_suffix in el])
16 | if recursive == False:
17 | break
18 | all_files = sorted(all_files)
19 | return all_files
--------------------------------------------------------------------------------
/augmento_client/logging.ini:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | formatters:
4 | simple:
5 | format: '%(asctime)s | %(levelname)s | %(name)s | %(message)s'
6 |
7 | handlers:
8 | console:
9 | class: logging.StreamHandler
10 | level: DEBUG
11 | formatter: simple
12 | stream: ext://sys.stdout
13 | error_file:
14 | class : logging.handlers.RotatingFileHandler
15 | level: ERROR
16 | formatter: simple
17 | filename: augmento_client/errors.log
18 | maxBytes: 1048576
19 | backupCount: 3
20 | encoding: utf8
21 |
22 | loggers:
23 | get_augmento_data:
24 | level: DEBUG
25 | handlers: [console, error_file]
26 | propagate: no
27 |
28 | root:
29 | level: DEBUG
30 | handlers: [console, error_file]
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 augmento-ai
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # Quant Reseach
6 |
7 | This repo serves as a quickstart guide for using using Augmento sentiment data, as well as a working repo for analysing the data and developing example strategies.
8 |
9 | Augmento API docs: http://api-dev.augmento.ai/v0.1/documentation
10 |
11 | Bitmex API docs: https://www.bitmex.com/api/explorer/
12 |
13 | ## Getting started
14 |
15 | Prerequisites
16 |
17 | python 2.7 or later
18 |
19 | Install requirements
20 |
21 | pip install -r requirements.txt --user
22 | zlib (already included with MacOS)
23 |
24 | Run tests
25 |
26 | python -m unittest discover -v
27 |
28 | ## Examples
29 |
30 | ### Quickstart
31 |
32 | The quickstart examples are the quickest way to download some data, plot the data, and run a simple strategy.
33 |
34 | Cache two years of Augmento data from the Augmento ReST API to a local folder
35 |
36 | python examples/0_load_augmento_example_data.py
37 |
38 | Cache a list of sources, coins, bin sizes, and topics from the Augmento ReST API to a local folder
39 |
40 | python examples/1_load_augmento_example_info.py
41 |
42 | Cache two years of XBt candle data from the Bitmex ReST API to a local folder (this may take a few minutes)
43 |
44 | python examples/2_load_bitmex_example_data.py
45 |
46 | Plot some of the cached raw Augmento data against the cached Bitmex XBt price data
47 |
48 | python examples/3_plot_augmento_example_data.py
49 |
50 | Backtest a very simple strategy using Augmento data against the Bitmex XBt price, and plot the results
51 |
52 | python examples/4_basic_strategy_example.py
53 |
54 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | data/
3 |
4 | # Byte-compiled / optimized / DLL files
5 | __pycache__/
6 | *.py[cod]
7 | *$py.class
8 |
9 | # C extensions
10 | *.so
11 |
12 | # Distribution / packaging
13 | .Python
14 | build/
15 | develop-eggs/
16 | dist/
17 | downloads/
18 | eggs/
19 | .eggs/
20 | lib/
21 | lib64/
22 | parts/
23 | sdist/
24 | var/
25 | wheels/
26 | *.egg-info/
27 | .installed.cfg
28 | *.egg
29 | MANIFEST
30 |
31 | # PyInstaller
32 | # Usually these files are written by a python script from a template
33 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
34 | *.manifest
35 | *.spec
36 |
37 | # Installer logs
38 | pip-log.txt
39 | pip-delete-this-directory.txt
40 |
41 | # Unit test / coverage reports
42 | htmlcov/
43 | .tox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | .hypothesis/
51 | .pytest_cache/
52 |
53 | # Translations
54 | *.mo
55 | *.pot
56 |
57 | # Django stuff:
58 | *.log
59 | local_settings.py
60 | db.sqlite3
61 |
62 | # Flask stuff:
63 | instance/
64 | .webassets-cache
65 |
66 | # Scrapy stuff:
67 | .scrapy
68 |
69 | # Sphinx documentation
70 | docs/_build/
71 |
72 | # PyBuilder
73 | target/
74 |
75 | # Jupyter Notebook
76 | .ipynb_checkpoints
77 |
78 | # pyenv
79 | .python-version
80 |
81 | # celery beat schedule file
82 | celerybeat-schedule
83 |
84 | # SageMath parsed files
85 | *.sage.py
86 |
87 | # Environments
88 | .env
89 | .venv
90 | env/
91 | venv/
92 | ENV/
93 | env.bak/
94 | venv.bak/
95 |
96 | # Spyder project settings
97 | .spyderproject
98 | .spyproject
99 |
100 | # Rope project settings
101 | .ropeproject
102 |
103 | # mkdocs documentation
104 | /site
105 |
106 | # mypy
107 | .mypy_cache/
108 |
--------------------------------------------------------------------------------
/examples/3_plot_augmento_example_data.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import msgpack
3 | import zlib
4 | import numpy as np
5 | import datetime
6 | import matplotlib.pyplot as plt
7 | import matplotlib.dates as md
8 |
9 | # import files from src
10 | sys.path.insert(0, "src")
11 | import example_helper as eh
12 |
13 | # define the location of the input file
14 | filename_augmento_topics = "data/example_data/augmento_topics.msgpack.zlib"
15 | filename_augmento_data = "data/example_data/augmento_data.msgpack.zlib"
16 | filename_bitmex_data = "data/example_data/bitmex_data.msgpack.zlib"
17 |
18 | # load the example data
19 | all_data = eh.load_example_data(filename_augmento_topics,
20 | filename_augmento_data,
21 | filename_bitmex_data)
22 | aug_topics, aug_topics_inv, t_aug_data, aug_data, t_price_data, price_data = all_data
23 |
24 | # get the signals we're interested in
25 | aug_signal_a = aug_data[:, aug_topics_inv["Bullish"]]
26 | aug_signal_b = aug_data[:, aug_topics_inv["Bearish"]]
27 |
28 | # set up the figure
29 | fig, ax = plt.subplots(2, 1, sharex=True, sharey=False)
30 |
31 | # initialise some labels for the plot
32 | datenum_aug_data = [md.date2num(datetime.datetime.fromtimestamp(el)) for el in t_aug_data]
33 | datenum_price_data = [md.date2num(datetime.datetime.fromtimestamp(el)) for el in t_price_data]
34 |
35 | # plot stuff
36 | ax[0].grid(linewidth=0.4)
37 | ax[1].grid(linewidth=0.4)
38 | ax[0].plot(datenum_price_data, price_data, linewidth=0.5)
39 | ax[1].plot(datenum_aug_data, aug_signal_a, color="g", linewidth=0.5)
40 | ax[1].plot(datenum_aug_data, aug_signal_b, color="r", linewidth=0.5)
41 | #ax[1].plot(datenum_aug_data, aug_data, linewidth=0.5)
42 |
43 | # label axes
44 | ax[0].set_ylabel("Price")
45 | ax[1].set_ylabel("Seniments")
46 | ax[1].legend(["Bullish", "Bearish"])
47 |
48 | # generate the time axes
49 | plt.subplots_adjust(bottom=0.2)
50 | plt.xticks( rotation=25 )
51 | ax[0]=plt.gca()
52 | xfmt = md.DateFormatter('%Y-%m-%d %H:%M')
53 | ax[0].xaxis.set_major_formatter(xfmt)
54 |
55 | # show the plot
56 | plt.show()
57 |
58 |
59 |
--------------------------------------------------------------------------------
/examples/1_load_augmento_example_info.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import requests
3 | import datetime
4 | import time
5 | import zlib
6 | import msgpack
7 |
8 | # import files from src
9 | sys.path.insert(0, "src")
10 | import helper_functions as hf
11 | import io_helper as ioh
12 |
13 | # define the urls of the endpoints for all the info
14 | topics_endpoint_url = "http://api-dev.augmento.ai/v0.1/topics"
15 | sources_endpoint_url = "http://api-dev.augmento.ai/v0.1/sources"
16 | coins_endpoint_url = "http://api-dev.augmento.ai/v0.1/coins"
17 | bin_sizes_endpoint_url = "http://api-dev.augmento.ai/v0.1/bin_sizes"
18 |
19 | # define where we're going to save the data
20 | path_save_data = "data/example_data"
21 | filename_save_topics = "{:s}/augmento_topics.msgpack.zlib".format(path_save_data)
22 | filename_save_sources = "{:s}/augmento_sources.msgpack.zlib".format(path_save_data)
23 | filename_save_coins = "{:s}/augmento_coins.msgpack.zlib".format(path_save_data)
24 | filename_save_bin_sizes = "{:s}/augmento_bin_sizes.msgpack.zlib".format(path_save_data)
25 |
26 | # check if the data path exists
27 | ioh.check_path(path_save_data, create_if_not_exist=True)
28 |
29 | # save a list of the augmento topics
30 | r = requests.request("GET", topics_endpoint_url, timeout=10)
31 | print("saving topics to {:s}".format(filename_save_topics))
32 | with open(filename_save_topics, "wb") as f:
33 | f.write(zlib.compress(msgpack.packb(r.json())))
34 |
35 | # save a list of the augmento topics
36 | r = requests.request("GET", sources_endpoint_url, timeout=10)
37 | print("saving sources to {:s}".format(filename_save_sources))
38 | with open(filename_save_sources, "wb") as f:
39 | f.write(zlib.compress(msgpack.packb(r.json())))
40 |
41 | # save a list of the augmento topics
42 | r = requests.request("GET", coins_endpoint_url, timeout=10)
43 | print("saving coins to {:s}".format(filename_save_coins))
44 | with open(filename_save_coins, "wb") as f:
45 | f.write(zlib.compress(msgpack.packb(r.json())))
46 |
47 | # save a list of the augmento topics
48 | r = requests.request("GET", bin_sizes_endpoint_url, timeout=10)
49 | print("saving bin_sizes to {:s}".format(filename_save_bin_sizes))
50 | with open(filename_save_bin_sizes, "wb") as f:
51 | f.write(zlib.compress(msgpack.packb(r.json())))
52 |
53 |
54 | print("done!")
55 |
56 |
--------------------------------------------------------------------------------
/src/example_helper.py:
--------------------------------------------------------------------------------
1 | import msgpack
2 | import zlib
3 | import numpy as np
4 | import helper_functions as hf
5 | import datetime_helper as dh
6 |
7 | def strip_data_by_time(t_data, data, t_min, t_max):
8 | data = np.array([s for s, t in zip(data, t_data) if t >= t_min and t <= t_max])
9 | t_data = np.array([t for t in t_data if t >= t_min and t <= t_max])
10 | return t_data, data
11 |
12 | def load_example_data(filename_augmento_topics,
13 | filename_augmento_data,
14 | filename_bitmex_data,
15 | datetime_start=None,
16 | datetime_end=None):
17 |
18 | # load the topics
19 | with open(filename_augmento_topics, "rb") as f:
20 | temp = msgpack.unpackb(zlib.decompress(f.read()), encoding='utf-8')
21 | augmento_topics = {int(k) : v for k, v in temp.items()}
22 | augmento_topics_inv = {v : int(k) for k, v in temp.items()}
23 |
24 | # load the augmento data
25 | with open(filename_augmento_data, "rb") as f:
26 | temp = msgpack.unpackb(zlib.decompress(f.read()), encoding='utf-8')
27 | t_aug_data = np.array([el["t_epoch"] for el in temp], dtype=np.float64)
28 | aug_data = np.array([el["counts"] for el in temp], dtype=np.int32)
29 |
30 | # load the price data
31 | with open(filename_bitmex_data, "rb") as f:
32 | temp = msgpack.unpackb(zlib.decompress(f.read()), encoding='utf-8')
33 | t_price_data = np.array([el["t_epoch"] for el in temp], dtype=np.float64)
34 | #price_data = np.array([el["open"] for el in temp], dtype=np.float64)
35 | price_data = np.array([el["close"] for el in temp], dtype=np.float64)
36 |
37 | # set the start and end times if they are specified
38 | if datetime_start != None:
39 | t_start = dh.datetime_to_epoch(datetime_start)
40 | else:
41 | t_start = max(np.min(t_aug_data), np.min(t_price_data))
42 |
43 | if datetime_end != None:
44 | t_end = dh.datetime_to_epoch(datetime_end)
45 | else:
46 | t_end = min(np.max(t_aug_data), np.max(t_price_data))
47 |
48 | # strip the sentiments and prices outside the shared time range
49 | t_aug_data, aug_data = strip_data_by_time(t_aug_data, aug_data, t_start, t_end)
50 | t_price_data, price_data = strip_data_by_time(t_price_data, price_data, t_start, t_end)
51 |
52 | return augmento_topics, augmento_topics_inv, t_aug_data, aug_data, t_price_data, price_data
53 |
--------------------------------------------------------------------------------
/examples/0_load_augmento_example_data.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import requests
3 | import datetime
4 | import time
5 | import zlib
6 | import msgpack
7 |
8 | # import files from src
9 | sys.path.insert(0, "src")
10 | import helper_functions as hf
11 | import io_helper as ioh
12 |
13 | # define the url of the endpoint to get event data
14 | endpoint_url = "http://api-dev.augmento.ai/v0.1/events/aggregated"
15 |
16 | # define where we're going to save the data
17 | path_save_data = "data/example_data"
18 | filename_save_data = "{:s}/augmento_data.msgpack.zlib".format(path_save_data)
19 |
20 | # define the start and end times
21 | datetime_start = datetime.datetime(2017, 1, 1)
22 | datetime_end = datetime.datetime(2019, 9, 25)
23 |
24 | # initialise a store for the data we're downloading
25 | sentiment_data = []
26 |
27 | # define a start pointer to track multiple requests
28 | start_ptr = 0
29 | count_ptr = 1000
30 |
31 | # get the data
32 | while start_ptr >= 0:
33 |
34 | # define the parameters of the request
35 | params = {
36 | "source" : "twitter",
37 | "coin" : "bitcoin",
38 | "bin_size" : "1H",
39 | "count_ptr" : count_ptr,
40 | "start_ptr" : start_ptr,
41 | "start_datetime" : datetime_start.strftime("%Y-%m-%dT%H:%M:%SZ"),
42 | "end_datetime" : datetime_end.strftime("%Y-%m-%dT%H:%M:%SZ"),
43 | }
44 |
45 | # make the request
46 | r = requests.request("GET", endpoint_url, params=params, timeout=10)
47 |
48 | # if the request was ok, add the data and increment the start_ptr
49 | # else return an error
50 | if r.status_code == 200:
51 | temp_data = r.json()
52 | start_ptr += count_ptr
53 | else:
54 | raise Exception("api call failed with status_code {:d}".format(r.status_code))
55 |
56 | # if we didn't get any data, assume we've got all the data
57 | if len(temp_data) == 0:
58 | start_ptr = -1
59 |
60 | # extend the data store
61 | sentiment_data.extend(temp_data)
62 |
63 | # print the progress
64 | str_print = "got data from {:s} to {:s}".format(*(sentiment_data[0]["datetime"],
65 | sentiment_data[-1]["datetime"],))
66 | print(str_print)
67 |
68 | # sleep
69 | time.sleep(2.0)
70 |
71 | # check if the data path exists
72 | ioh.check_path(path_save_data, create_if_not_exist=True)
73 |
74 | # save the data
75 | print("saving data to {:s}".format(filename_save_data))
76 | with open(filename_save_data, "wb") as f:
77 | f.write(zlib.compress(msgpack.packb(sentiment_data)))
78 |
79 |
80 | print("done!")
81 |
82 |
--------------------------------------------------------------------------------
/src/datetime_helper.py:
--------------------------------------------------------------------------------
1 | import datetime
2 | import io_helper as ioh
3 |
4 | # set the utc value of the epoch
5 | epoch = datetime.datetime.utcfromtimestamp(0)
6 |
7 | def date_str_to_seconds(date_str, format):
8 | return (datetime.datetime.strptime(date_str, format) - datetime.datetime(1970,1,1)).total_seconds()
9 |
10 | def datetime_str_to_datetime(date_str, timestamp_format_str="%Y-%m-%d %H:%M:%S"):
11 | return datetime.datetime.strptime(date_str, timestamp_format_str)
12 |
13 | def timestamp_to_epoch(timestamp_str, timestamp_format_str):
14 | return (datetime.datetime.strptime(timestamp_str, timestamp_format_str) - epoch).total_seconds()
15 |
16 | def epoch_to_datetime(t_epoch):
17 | # must be UTC to remove timezone
18 | return datetime.datetime.utcfromtimestamp(t_epoch)
19 |
20 | def epoch_to_datetime_str(t_epoch, timestamp_format_str="%Y-%m-%d %H:%M:%S"):
21 | # must be UTC to remove timezone
22 | return datetime.datetime.utcfromtimestamp(t_epoch).strftime(timestamp_format_str)
23 |
24 | def datetime_to_str(datetime_a, timestamp_format_str="%Y-%m-%d %H:%M:%S"):
25 | # must be UTC to remove timezone
26 | return datetime_a.strftime(timestamp_format_str)
27 |
28 | def round_datetime_to_day_start(datetime_a, forward_days=0):
29 | datetime_a = datetime_a.replace(hour=0, minute=0, second=0, microsecond=0)
30 | return add_days_to_datetime(datetime_a, forward_days)
31 |
32 | def add_days_to_datetime(datetime_a, forward_days):
33 | return datetime_a + datetime.timedelta(days=forward_days)
34 |
35 | def datetime_to_epoch(datetime_a):
36 | return (datetime_a - epoch).total_seconds()
37 |
38 | def timestamp_to_datetime(timestamp_str, timestamp_format_str):
39 | return datetime.datetime.strptime(timestamp_str, timestamp_format_str)
40 |
41 | def list_file_dates_for_path(path, filename_suffix, datetime_format_str):
42 | date_strs = ioh.list_files_in_path_os(path, filename_suffix=filename_suffix)
43 | date_strs = [el.split("/")[-1].replace(filename_suffix, "") for el in date_strs]
44 | dates = [datetime_str_to_datetime(el, timestamp_format_str=datetime_format_str)
45 | for el in date_strs]
46 | return dates
47 |
48 | def get_datetimes_between_datetimes(datetime_start, datetime_end):
49 | #return [datetime_start + datetime.timedelta(days=x)
50 | # for x in range(0, (datetime_end-datetime_start).days + 1)]
51 | round_datetime_start = round_datetime_to_day_start(datetime_start)
52 | round_datetime_end = round_datetime_to_day_start(datetime_end)
53 | return [round_datetime_start + datetime.timedelta(days=x)
54 | for x in range(0, (round_datetime_end-round_datetime_start).days + 1)]
55 |
--------------------------------------------------------------------------------
/examples/5_write_strategy_to_csv.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import msgpack
3 | import zlib
4 | import numpy as np
5 | import pandas as pd
6 | import datetime
7 | import matplotlib.pyplot as plt
8 | import matplotlib.dates as md
9 |
10 | # import files from src
11 | sys.path.insert(0, "src")
12 | import example_helper as eh
13 | import analysis_helper as ah
14 |
15 | # define the location of the input file
16 | filename_augmento_topics = "data/example_data/augmento_topics.msgpack.zlib"
17 | filename_augmento_data = "data/example_data/augmento_data.msgpack.zlib"
18 | filename_bitmex_data = "data/example_data/bitmex_data.msgpack.zlib"
19 |
20 | # load the example data
21 | all_data = eh.load_example_data(filename_augmento_topics, filename_augmento_data, filename_bitmex_data)
22 | aug_topics, aug_topics_inv, t_aug_data, aug_data, t_price_data, price_data = all_data
23 |
24 |
25 |
26 | # get the signals we're interested in
27 | aug_signal_a = aug_data[:, aug_topics_inv["Positive"]].astype(np.float64)
28 | aug_signal_b = aug_data[:, aug_topics_inv["Bearish"]].astype(np.float64)
29 |
30 | sent_score = ah.nb_calc_sentiment_score_c(aug_signal_a, aug_signal_b, 28*24, 14*24)
31 |
32 | date_time = np.array([datetime.datetime.utcfromtimestamp(t).isoformat()
33 | for t in t_price_data])
34 |
35 | # define some parameters for the backtest
36 | start_pnl = 1.0
37 | buy_sell_fee = 0.00075
38 | # run the backtest
39 | pnl = ah.nb_backtest_a(price_data, sent_score, start_pnl, buy_sell_fee)
40 | # set up the figure
41 | fig, ax = plt.subplots(3, 1, sharex=True, sharey=False)
42 | # initialise some labels for the plot
43 | datenum_aug_data = [md.date2num(datetime.datetime.fromtimestamp(el)) for el in t_aug_data]
44 | datenum_price_data = [md.date2num(datetime.datetime.fromtimestamp(el)) for el in t_price_data]
45 | # plot stuff
46 | ax[0].grid(linewidth=0.4)
47 | ax[1].grid(linewidth=0.4)
48 | ax[2].grid(linewidth=0.4)
49 | ax[0].plot(datenum_price_data, price_data, linewidth=0.5)
50 | ax[1].plot(datenum_aug_data, sent_score, linewidth=0.5)
51 | ax[2].plot(datenum_price_data, pnl, linewidth=0.5)
52 | # label axes
53 | ax[0].set_ylabel("Price")
54 | ax[1].set_ylabel("Seniment score")
55 | ax[2].set_ylabel("PnL")
56 | #ax[0].set_title("4_basic_strategy_example.py")
57 | # generate the time axes
58 | plt.subplots_adjust(bottom=0.2)
59 | plt.xticks( rotation=25 )
60 | ax[0]=plt.gca()
61 | xfmt = md.DateFormatter('%Y-%m-%d')
62 | ax[0].xaxis.set_major_formatter(xfmt)
63 | # show the plot
64 | plt.show()
65 |
66 |
67 |
68 | csv_data= {"date": date_time, "ref_price":price_data,"raw_signal":sent_score,"pnl":pnl}
69 |
70 | data_frame = pd.DataFrame(csv_data)
71 |
72 | data_frame.to_csv("data/signals.csv",index=False)
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/examples/4_basic_strategy_example.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import msgpack
3 | import zlib
4 | import numpy as np
5 | import datetime
6 | import matplotlib.pyplot as plt
7 | import matplotlib.dates as md
8 |
9 | # import files from src
10 | sys.path.insert(0, "src")
11 | import example_helper as eh
12 | import analysis_helper as ah
13 |
14 | # define the location of the input file
15 | filename_augmento_topics = "data/example_data/augmento_topics.msgpack.zlib"
16 | filename_augmento_data = "data/example_data/augmento_data.msgpack.zlib"
17 | filename_bitmex_data = "data/example_data/bitmex_data.msgpack.zlib"
18 |
19 | # load the example data
20 | all_data = eh.load_example_data(filename_augmento_topics,
21 | filename_augmento_data,
22 | filename_bitmex_data)
23 | aug_topics, aug_topics_inv, t_aug_data, aug_data, t_price_data, price_data = all_data
24 |
25 | # get the signals we're interested in
26 | aug_signal_a = aug_data[:, aug_topics_inv["Negative"]].astype(np.float64)
27 | aug_signal_b = aug_data[:, aug_topics_inv["Bearish"]].astype(np.float64)
28 | #aug_signal_b = aug_data[:, aug_topics_inv["Bullish"]].astype(np.float64)
29 | #aug_signal_a = aug_data[:, aug_topics_inv["Bearish"]].astype(np.float64)
30 |
31 | # define the window size for the sentiment score calculation
32 | n_days = 7
33 | window_size = 24 * n_days
34 |
35 | # generate the sentiment score
36 | sent_score = ah.nb_calc_sentiment_score_a(aug_signal_a, aug_signal_b, window_size, window_size)
37 | #sent_score = ah.nb_calc_sentiment_score_c(aug_signal_a, aug_signal_b, window_size, window_size)
38 |
39 | # define some parameters for the backtest
40 | start_pnl = 1.0
41 | buy_sell_fee = 0.0
42 |
43 | # run the backtest
44 | pnl = ah.nb_backtest_a(price_data, sent_score, start_pnl, buy_sell_fee)
45 |
46 | # set up the figure
47 | fig, ax = plt.subplots(3, 1, sharex=True, sharey=False)
48 |
49 | # initialise some labels for the plot
50 | datenum_aug_data = [md.date2num(datetime.datetime.fromtimestamp(el)) for el in t_aug_data]
51 | datenum_price_data = [md.date2num(datetime.datetime.fromtimestamp(el)) for el in t_price_data]
52 |
53 | # plot stuff
54 | ax[0].grid(linewidth=0.4)
55 | ax[1].grid(linewidth=0.4)
56 | ax[2].grid(linewidth=0.4)
57 | ax[0].plot(datenum_price_data, price_data, linewidth=0.5)
58 | ax[1].plot(datenum_aug_data, sent_score, linewidth=0.5)
59 | ax[2].plot(datenum_price_data, pnl, linewidth=0.5)
60 |
61 | # label axes
62 | ax[0].set_ylabel("Price")
63 | ax[1].set_ylabel("Seniment score")
64 | ax[2].set_ylabel("PnL")
65 | ax[1].set_ylim([-5.5, 5.5])
66 |
67 | #ax[0].set_title("4_basic_strategy_example.py")
68 |
69 | # generate the time axes
70 | plt.subplots_adjust(bottom=0.2)
71 | plt.xticks( rotation=25 )
72 | ax[0]=plt.gca()
73 | xfmt = md.DateFormatter('%Y-%m-%d')
74 | ax[0].xaxis.set_major_formatter(xfmt)
75 |
76 | # show the plot
77 | plt.show()
78 |
--------------------------------------------------------------------------------
/examples/2_load_bitmex_example_data.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import requests
3 | import datetime
4 | import time
5 | import zlib
6 | import msgpack
7 |
8 | # import files from src
9 | sys.path.insert(0, "src")
10 | import helper_functions as hf
11 | import io_helper as ioh
12 | import datetime_helper as dh
13 |
14 | # define the url of the endpoint
15 | endpoint_url = "https://www.bitmex.com/api/v1/trade/bucketed"
16 |
17 | # define where we're going to save the data
18 | path_save_data = "data/example_data"
19 | filename_save_data = "{:s}/bitmex_data.msgpack.zlib".format(path_save_data)
20 |
21 | # define the start and end times
22 | datetime_start = datetime.datetime(2017, 1, 1)
23 | datetime_end = datetime.datetime(2019, 9, 25)
24 |
25 | # initialise a store for the data we're downloading
26 | market_data = []
27 |
28 | # define a start pointer to track multiple requests
29 | start_ptr = 0
30 | count_ptr = 750
31 |
32 | # get the data
33 | while start_ptr >= 0:
34 |
35 | # bug in bitmex ptr system, need to shift the start date forward for each request
36 | if market_data == []:
37 | str_datetime_start = datetime_start.strftime("%Y-%m-%dT%H:%M:%SZ")
38 | start_ptr = 0
39 | else:
40 | str_datetime_start = market_data[-1]["timestamp"]
41 | start_ptr = 1
42 |
43 | # define the parameters of the request
44 | params = {
45 | "symbol" : "XBt",
46 | "binSize" : "1h",
47 | "count" : count_ptr,
48 | "start" : start_ptr,
49 | "startTime" : str_datetime_start,
50 | "endTime" : datetime_end.strftime("%Y-%m-%dT%H:%M:%SZ"),
51 | }
52 |
53 | # make the request
54 | r = requests.request("GET", endpoint_url, params=params, timeout=10)
55 |
56 | # if the request was ok, add the data and increment the start_ptr
57 | # else return an error
58 | if r.status_code == 200:
59 | temp_data = r.json()
60 | start_ptr += count_ptr
61 | else:
62 | raise Exception("api call failed with status_code {:d}".format(r.status_code))
63 |
64 | # if we didn't get any data, assume we've got all the data
65 | # else add the data to the data store
66 | if len(temp_data) == 0:
67 | start_ptr = -1
68 | else:
69 |
70 | # convert the iso timestamps to epoch times
71 | for td in temp_data:
72 | t_epoch = dh.timestamp_to_epoch(td["timestamp"], "%Y-%m-%dT%H:%M:%S.000Z")
73 | td.update({"t_epoch" : t_epoch})
74 |
75 | # extend the data store
76 | market_data.extend(temp_data)
77 |
78 | # print the progress
79 | str_print = "got data from {:s} to {:s}".format(*(temp_data[0]["timestamp"],
80 | temp_data[-1]["timestamp"],))
81 | print(str_print)
82 |
83 | # sleep
84 | time.sleep(2.1)
85 |
86 | # check if the data path exists
87 | ioh.check_path(path_save_data, create_if_not_exist=True)
88 |
89 | # save the data
90 | print("saving data to {:s}".format(filename_save_data))
91 | with open(filename_save_data, "wb") as f:
92 | f.write(zlib.compress(msgpack.packb(market_data)))
93 |
94 | print("done!")
95 |
96 |
--------------------------------------------------------------------------------
/src/data_model.py:
--------------------------------------------------------------------------------
1 | import example_helper as eh
2 | import numpy as np
3 | import math
4 |
5 |
6 |
7 | # TODO: improve commenting
8 |
9 | class Data():
10 |
11 | def __init__(self):
12 |
13 | pass
14 |
15 | def load_raw(self,
16 | augmento_topic = "data/example_data/augmento_topics.msgpack.zlib",
17 | augmento_data = "data/example_data/augmento_data.msgpack.zlib",
18 | bitmex_data = "data/example_data/bitmex_data.msgpack.zlib"):
19 |
20 | # load all raw data
21 | self.aug_topics, self.aug_topics_inv, self.t_aug_data,\
22 | self.aug_data, self.t_price_data, self.price_data =\
23 | eh.load_example_data(augmento_topic, augmento_data, bitmex_data)
24 | print("loaded")
25 |
26 |
27 | def get_data(self, n_timesteps, forward):
28 |
29 | # number of sentiments
30 | n_sentiments = self.aug_data.shape[1]
31 |
32 | # number of all data points
33 | n_data = self.aug_data.shape[0]
34 |
35 | # index of the last observation
36 | last_data = n_data - forward
37 |
38 | # number of all samples
39 | n_samples = last_data - n_timesteps + 1
40 |
41 | # create empty arrays for sentiment and price
42 | arr_aug = np.zeros((n_samples, n_timesteps, n_sentiments),dtype=np.float64)
43 |
44 | #arr_price = np.zeros(n_samples)
45 | arr_price_full = np.zeros((n_samples, forward),dtype=np.float64)
46 |
47 | print("Loading...")
48 | for i in range(n_samples):
49 | arr_aug[i, :, :] = self.aug_data[i : i + n_timesteps,:]
50 | price_range = self.price_data[i + n_timesteps : i + n_timesteps + forward]
51 | #arr_price[i] = (price_range[-1]-price_range[0])/price_range[0]
52 | arr_price_full[i, :] = price_range
53 | #print(arr_aug[i])
54 | #print(i)
55 | #print(n_samples)
56 | print("Ready.")
57 |
58 | self.arr_aug = arr_aug
59 | self.arr_price_full = arr_price_full
60 |
61 | #return arr_aug, arr_price_full
62 |
63 |
64 | def get_data_batch(self, batch_size):
65 |
66 | all_sentiment = self.arr_aug
67 | all_price = self.arr_price_full
68 | n_timesteps = all_price.shape[1]
69 | forward = all_price.shape[1]
70 | n_sentiments = all_sentiment.shape[2]
71 | n_pop = all_sentiment.shape[0]
72 | batch_sentiment = np.zeros((batch_size, n_timesteps, n_sentiments), dtype=np.float64)
73 | #batch_price = np.zeros(batch_size)
74 | batch_price = np.zeros((batch_size,forward), dtype=np.float64)
75 | batch_sequence = np.random.choice(n_pop, batch_size, replace=False)
76 |
77 | for i in range(len(batch_sequence)):
78 | batch_sentiment[i] = all_sentiment[batch_sequence[i]]
79 | batch_price[i] = all_price[batch_sequence[i]]
80 |
81 | return batch_sentiment, batch_price
82 |
83 |
84 |
--------------------------------------------------------------------------------
/src/data_loader_helper.py:
--------------------------------------------------------------------------------
1 | import datetime
2 | import pprint
3 | import msgpack
4 | import zlib
5 | import numpy as np
6 |
7 | import io_helper as ioh
8 | import datetime_helper as dh
9 | import load_augmento_data_helper as ladh
10 | #import load_binance_data_helper as lbdh
11 | import load_kraken_data_helper as lbdh
12 |
13 |
14 | def find_missing_date_batches(missing_days, required_days):
15 | missing_day_batches = []
16 | for i_amd in range(len(missing_days)):
17 | if i_amd > 0 and (missing_days[i_amd] - missing_days[i_amd-1]).days == 1:
18 | missing_day_batches[-1].append(missing_days[i_amd])
19 | else:
20 | missing_day_batches.append([missing_days[i_amd]])
21 | return missing_day_batches
22 |
23 | def strip_data_by_time(t_data, data, t_min, t_max):
24 | data = np.array([s for s, t in zip(data, t_data) if t >= t_min and t <= t_max])
25 | t_data = np.array([t for t in t_data if t >= t_min and t <= t_max])
26 | return t_data, data
27 |
28 | def load_data(path_data="data/cache",
29 | augmento_coin=None,
30 | augmento_source=None,
31 | binance_symbol=None,
32 | dt_bin_size=None,
33 | datetime_start=None,
34 | datetime_end=None,
35 | augmento_api_key=None):
36 |
37 | datetime_end = min(datetime.datetime.now(), datetime_end)
38 |
39 | # check the input arguments
40 | if None in [binance_symbol, augmento_coin, augmento_source, dt_bin_size, datetime_start, datetime_end]:
41 | raise Exception("missing required param(s) in load_data()")
42 |
43 | # specify the path for the binance data cache
44 | path_augmento_data = "{:s}/augmento/{:s}/{:s}/{:d}".format(*(path_data, augmento_source, augmento_coin, dt_bin_size))
45 | path_augmento_topics = "{:s}/augmento/".format(path_data)
46 |
47 | # specify the path for the augmento data cache
48 | #path_binance_data = "{:s}/binance/{:s}/{:d}".format(*(path_data, binance_symbol, dt_bin_size))
49 | path_binance_data = "{:s}/kraken/{:s}/{:d}".format(*(path_data, binance_symbol, dt_bin_size))
50 |
51 | # make sure all the paths exist
52 | ioh.check_path(path_augmento_data, create_if_not_exist=True)
53 | ioh.check_path(path_binance_data, create_if_not_exist=True)
54 |
55 | # check which days of data exist for the augmento data and binance data
56 | augmento_dates = dh.list_file_dates_for_path(path_augmento_data, ".msgpack.zlib", "%Y%m%d")
57 | binance_dates = dh.list_file_dates_for_path(path_binance_data, ".msgpack.zlib", "%Y%m%d")
58 |
59 | # remove any dates from the last 3 days, so we reload recent data
60 | datetime_now = datetime.datetime.now()
61 | augmento_dates = [el for el in augmento_dates if el < dh.add_days_to_datetime(datetime_now, -3)]
62 | binance_dates = [el for el in binance_dates if el < dh.add_days_to_datetime(datetime_now, -3)]
63 |
64 | # get a list of the days we need
65 | required_dates = dh.get_datetimes_between_datetimes(datetime_start, datetime_end)
66 |
67 | # get a list of the days we're missing for augmento and binance data
68 | augmento_missing_dates = sorted(list(set(required_dates) - set(augmento_dates)))
69 | binance_missing_dates = sorted(list(set(required_dates) - set(binance_dates)))
70 |
71 | # group the missing days by batch
72 | augmento_missing_batches = find_missing_date_batches(augmento_missing_dates, required_dates)
73 | binance_missing_batches = find_missing_date_batches(binance_missing_dates, required_dates)
74 |
75 | # load the augmento keys
76 | aug_keys = ladh.load_keys(path_augmento_topics)
77 |
78 | # load the binance keys
79 | bin_keys = lbdh.load_keys()
80 |
81 | # for each of the missing batches of augmento data, get the data and cache it
82 | for abds in augmento_missing_batches:
83 |
84 | # get the data for the batch and cache it
85 | ladh.load_and_cache_data(path_augmento_data,
86 | augmento_source,
87 | augmento_coin,
88 | dt_bin_size,
89 | abds[0],
90 | dh.add_days_to_datetime(abds[-1], 1))
91 |
92 | # for each of the missing batches of binance data, get the data and cache it
93 | for bbds in binance_missing_batches:
94 |
95 | # get the data for the batch and cache it
96 | lbdh.load_and_cache_data(path_binance_data,
97 | binance_symbol,
98 | dt_bin_size,
99 | bbds[0],
100 | dh.add_days_to_datetime(bbds[-1], 1))
101 |
102 | # load the data
103 | t_aug_data, aug_data = ladh.load_cached_data(path_augmento_data, datetime_start, datetime_end)
104 | t_bin_data, bin_data = lbdh.load_cached_data(path_binance_data, datetime_start, datetime_end)
105 |
106 | # strip the data
107 | t_min = max([t_aug_data[0], t_bin_data[0], dh.datetime_to_epoch(datetime_start)])
108 | t_max = min([t_aug_data[-1], t_bin_data[-1], dh.datetime_to_epoch(datetime_end)])
109 | t_aug_data, aug_data = strip_data_by_time(t_aug_data, aug_data, t_min, t_max)
110 | t_bin_data, bin_data = strip_data_by_time(t_bin_data, bin_data, t_min, t_max)
111 |
112 | return t_aug_data, t_bin_data, aug_data, bin_data, aug_keys, bin_keys
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/src/load_augmento_data_helper.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import time
3 | import pprint
4 | import zlib
5 | import msgpack
6 | import numpy as np
7 |
8 | import datetime_helper as dh
9 |
10 | # define the base url of the endpoint
11 | base_url = "http://api-dev.augmento.ai/v0.1"
12 |
13 | def load_keys(path_input):
14 |
15 | # if a list of topics doesn't exist, cache it
16 | path_augmento_topics = "{:s}/topics.msgpack.zlib".format(path_input)
17 | try:
18 | with open(path_augmento_topics, "rb") as f:
19 | augmento_topics = msgpack.unpackb(zlib.decompress(f.read()), encoding='utf-8')
20 | except:
21 | augmento_topics = requests.request("GET", "{:s}/topics".format(base_url), timeout=10).json()
22 | with open(path_augmento_topics, "wb") as f:
23 | f.write(zlib.compress(msgpack.packb(augmento_topics)))
24 |
25 | return {v : int(k) for k, v in augmento_topics.items()}
26 |
27 |
28 | def load_and_cache_data(path_output, source, coin, dt_bin_size, datetime_start, datetime_end):
29 |
30 | # make sure the start date and end date are rounded to the nearest day
31 | datetime_start = dh.round_datetime_to_day_start(datetime_start)
32 | datetime_end = dh.round_datetime_to_day_start(datetime_end)
33 |
34 | # make sure the source exists
35 | available_sources = requests.request("GET", "{:s}/sources".format(base_url), timeout=10).json()
36 | if source not in available_sources:
37 | raise Exception("invalid augmento source: {:s} not in: {:s}".format(*(source, available_sources)))
38 |
39 | # make sure the coin exists
40 | available_coins = requests.request("GET", "{:s}/coins".format(base_url), timeout=10).json()
41 | if coin not in available_coins:
42 | raise Exception("invalid augmento coin: {:s} not in: {:s}".format(*(coin, available_coins)))
43 |
44 | # make sure the bin_size exists
45 | available_bin_sizes = requests.request("GET", "{:s}/bin_sizes".format(base_url), timeout=10).json()
46 | available_bin_sizes = {v : k for k, v in available_bin_sizes.items()}
47 | if dt_bin_size not in available_bin_sizes:
48 | raise Exception("invalid augmento bin_size: {:s} not in: {:s}".format(*(dt_bin_size, available_bin_sizes)))
49 |
50 | # initialise a store for the data we're downloading
51 | sentiment_data = []
52 |
53 | # define a start pointer to track multiple requests
54 | start_ptr = 0
55 | count_ptr = 1000
56 |
57 | # get the data
58 | while start_ptr >= 0:
59 |
60 | # define the parameters of the request
61 | params = {
62 | "source" : source,
63 | "coin" : coin,
64 | "bin_size" : available_bin_sizes[dt_bin_size],
65 | "count_ptr" : count_ptr,
66 | "start_ptr" : start_ptr,
67 | "start_datetime" : datetime_start.strftime("%Y-%m-%dT%H:%M:%SZ"),
68 | "end_datetime" : datetime_end.strftime("%Y-%m-%dT%H:%M:%SZ"),
69 | }
70 |
71 | # make the request
72 | r = requests.request("GET", "{:s}/events/aggregated".format(base_url), params=params, timeout=10)
73 |
74 | # if the request was ok, add the data and increment the start_ptr
75 | # else return an error
76 | if r.status_code == 200:
77 | temp_data = r.json()
78 | start_ptr += count_ptr
79 | else:
80 | raise Exception("api call failed with status_code {:d}".format(r.status_code))
81 |
82 | # if we didn't get any data, assume we've got all the data
83 | if len(temp_data) == 0:
84 | start_ptr = -1
85 |
86 | # extend the data store
87 | sentiment_data.extend(temp_data)
88 |
89 | if len(temp_data) > 0:
90 | # print the progress
91 | str_print = "got augmento data from {:s} to {:s}".format(*(sentiment_data[0]["datetime"],
92 | sentiment_data[-1]["datetime"],))
93 | print(str_print)
94 |
95 | # sleep
96 | time.sleep(2.0)
97 |
98 | # get datetimes for all datapoints
99 | datetimes = [dh.epoch_to_datetime(el["t_epoch"]) for el in sentiment_data]
100 |
101 | # get the starts of all the days
102 | days = sorted(list(set([dh.round_datetime_to_day_start(el) for el in datetimes])))
103 |
104 | # for each of the start dates, cache the data for that day
105 | for day in days:
106 |
107 | # generate the output filename
108 | output_filename_short = dh.datetime_to_str(day, timestamp_format_str="%Y%m%d")
109 | output_filename = "{:s}/{:s}.msgpack.zlib".format(*(path_output, output_filename_short))
110 |
111 | # generate/filter the output data
112 | temp_start = dh.datetime_to_epoch(day)
113 | temp_end = dh.datetime_to_epoch(dh.add_days_to_datetime(day, 1))
114 |
115 | # get the data for this day (note that t_epoch is the OPEN time of the bin)
116 | output_data = [el for el in sentiment_data if el["t_epoch"] >= temp_start and el["t_epoch"] < temp_end]
117 |
118 | # save the data
119 | with open(output_filename, "wb") as f:
120 | f.write(zlib.compress(msgpack.packb(output_data)))
121 |
122 | def load_cached_data(path_input, datetime_start, datetime_end):
123 |
124 | # initialise the output data
125 | output_data = []
126 |
127 | # get a list of the files we need to open
128 | required_dates = dh.get_datetimes_between_datetimes(datetime_start, datetime_end)
129 |
130 | # go through all the dates and load the corrisponding files
131 | for rd in required_dates:
132 |
133 | # load the file
134 | input_filename_short = dh.datetime_to_str(rd, timestamp_format_str="%Y%m%d")
135 | input_filename = "{:s}/{:s}.msgpack.zlib".format(*(path_input, input_filename_short))
136 | try:
137 | with open(input_filename, "rb") as f:
138 | output_data.extend(msgpack.unpackb(zlib.decompress(f.read()), encoding='utf-8'))
139 | except:
140 | pass
141 |
142 | # format the data
143 | t_data = np.array([el["t_epoch"] for el in output_data], dtype=np.float64)
144 | feat_data = np.array([el["counts"] for el in output_data], dtype=np.float64)
145 |
146 | return t_data, feat_data
147 |
148 |
--------------------------------------------------------------------------------
/augmento_client/rest_api.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # coding: utf-8
3 | # @Author: ArthurBernard
4 | # @Email: arthur.bernard.92@gmail.com
5 | # @Date: 2019-07-22 15:03:30
6 | # @Last modified by: ArthurBernard
7 | # @Last modified time: 2019-07-23 15:52:22
8 |
9 | """ Client connector to Augmento REST API.
10 |
11 | Examples
12 | --------
13 | >>> ra = RequestAugmento(logging_level='DEBUG')
14 | >>> df = ra.get_dataframe(source='twitter', coin='bitcoin', bin_size='24H', start='2019-06-01T00:00:00Z', end='2019-06-02T00:00:00Z')
15 | >>> print(df.loc[:, 'Hacks':'Banks'])
16 | Hacks Pessimistic/Doubtful Banks
17 | date
18 | 2019-06-01T00:00:00Z 7 15 33
19 |
20 | """
21 |
22 | # Built-in packages
23 | import logging
24 | import json
25 | import time
26 | import datetime
27 |
28 | # External packages
29 | import requests
30 | import pandas as pd
31 |
32 | # Local packages
33 |
34 | __all__ = ['RequestAugmento']
35 |
36 | # TODO : add better doctests/examples
37 |
38 |
39 | class RequestAugmento:
40 | """ Class to request Augmento data from REST public API.
41 |
42 | Methods
43 | -------
44 | send_request(method, **params)
45 | Return answere of request in list or dict.
46 | get_data(source, coin, bin_size, start, end, start_ptr=0, count_ptr=1000)
47 | Return aggregated event data in list of list.
48 | get_dataframe(source, coin, bin_size, start, end)
49 | Return aggregated event in a dataframe.
50 | get_database(source, coin, bin_size, start, end)
51 | Merge several requests of aggregated event in a dataframe.
52 |
53 | """
54 |
55 | def __init__(self, url='http://api-dev.augmento.ai/v0.1/',
56 | logging_level='WARNING'):
57 | """ Initialize object. """
58 | self.url = url
59 | self.logger = logging.getLogger('get_augmento_data.' + __name__)
60 | self.logger.setLevel(logging_level)
61 | self.logger.debug('Starting augmento client')
62 |
63 | def send_request(self, method, **params):
64 | """ Send a request to Augmento REST public API.
65 |
66 | Parameters
67 | ----------
68 | method : str
69 | Name of the relevent request.
70 | **params : dict
71 | Relevent parameters, cf augemento documentation [1]_.
72 |
73 | Returns
74 | -------
75 | dict
76 | Relevant data.
77 |
78 | References
79 | ----------
80 | .. [1] http://api-dev.augmento.ai/v0.1/documentation#introduction
81 |
82 | """
83 | self.logger.debug(f'{method} request with {params} parameters.')
84 |
85 | # Try and catch some exceptions
86 | try:
87 | ans = requests.get(self.url + method, params)
88 |
89 | return json.loads(ans.text)
90 |
91 | except json.decoder.JSONDecodeError:
92 | self.logger.error('JSON error.')
93 | time.sleep(1)
94 |
95 | return self.send_request(method, **params)
96 |
97 | except requests.exceptions.ConnectionError:
98 | self.logger.error('HTTP error.')
99 | time.sleep(1)
100 |
101 | return self.send_request(method, **params)
102 |
103 | except Exception as e:
104 | self.logger.error('Unknown error {}.'.format(type(e)),
105 | exc_info=True)
106 | time.sleep(1)
107 |
108 | return self.send_request(method, **params)
109 |
110 | def get_data(self, source, coin, bin_size, start, end, start_ptr=0,
111 | count_ptr=1000):
112 | """ Request data to Augmento REST public API.
113 |
114 | Parameters
115 | ----------
116 | source : str, {'bitcointalk', 'reddit', 'twitter'}
117 | Source of data.
118 | coin : str
119 | Name of a crypto-currency, cf augemento documentation [1]_.
120 | bin_size : str, {'1H', '24H'}
121 | Time between two observations.
122 | start, end : str, int or datetime
123 | Starting date and ending date. If string must be ISO 8601 format
124 | such that ('%Y-%m-%dT%H:%M:%SZ'), or if integer must be UTC
125 | timestamp, else can be a datetime object.
126 | start_ptr : int, optional
127 | Default is 0.
128 | count_ptr : int, optional
129 | Number of observation.
130 |
131 | Returns
132 | -------
133 | list of list
134 | Relevant data from `date_0` to `date_T` as
135 | `[[x_1, ..., date_0, ts_0], ..., [x_1, ..., date_T, ts_T]]`.
136 |
137 | References
138 | ----------
139 | .. [1] http://api-dev.augmento.ai/v0.1/documentation#introduction
140 |
141 | """
142 | start = intel_date(start)
143 | end = intel_date(end)
144 |
145 | # Request data
146 | data = self.send_request(
147 | 'events/aggregated', source=source, coin=coin, bin_size=bin_size,
148 | start_datetime=start.strftime('%Y-%m-%dT%H:%M:%SZ'),
149 | end_datetime=end.strftime('%Y-%m-%dT%H:%M:%SZ'),
150 | start_ptr=start_ptr, count_ptr=count_ptr
151 | )
152 |
153 | return [[*x['counts'], x['datetime'], x['t_epoch']] for x in data]
154 |
155 | def get_dataframe(self, source, coin, bin_size, start, end):
156 | """ Request data to Augmento REST public API.
157 |
158 | Parameters
159 | ----------
160 | source : str, {'bitcointalk', 'reddit', 'twitter'}
161 | Source of data.
162 | coin : str
163 | Name of a crypto-currency, cf augemento documentation [1]_.
164 | bin_size : str, {'1H', '24H'}
165 | Time between two observations.
166 | start, end : str, int or datetime
167 | Starting date and ending date. If string must be ISO 8601 format
168 | such that ('%Y-%m-%dT%H:%M:%SZ'), or if integer must be UTC
169 | timestamp, else can be a datetime object.
170 | Warning : `end` and `start` must have less than 1000 observations
171 | between.
172 |
173 |
174 | Returns
175 | -------
176 | pd.DataFrame
177 | Relevant dataframe.
178 |
179 | References
180 | ----------
181 | .. [1] http://api-dev.augmento.ai/v0.1/documentation#introduction
182 |
183 | """
184 | # Request data
185 | data = self.get_data(
186 | source=source, coin=coin, bin_size=bin_size, start=start, end=end
187 | )
188 |
189 | return self._set_dataframe(data)
190 |
191 | def get_database(self, source, coin, bin_size, start, end):
192 | """ Merge several data request to Augmento REST public API.
193 |
194 | Parameters
195 | ----------
196 | source : str, {'bitcointalk', 'reddit', 'twitter'}
197 | Source of data.
198 | coin : str
199 | Name of a crypto-currency, cf augemento documentation [1]_.
200 | bin_size : str, {'1H', '24H'}
201 | Time between two observations.
202 | start, end : str, int or datetime
203 | Starting date and ending date. If string must be ISO 8601 format
204 | such that ('%Y-%m-%dT%H:%M:%SZ'), or if integer must be UTC
205 | timestamp, else can be a datetime object.
206 |
207 | Returns
208 | -------
209 | pd.DataFrame
210 | Relevant dataframe.
211 |
212 | References
213 | ----------
214 | .. [1] http://api-dev.augmento.ai/v0.1/documentation#introduction
215 |
216 | """
217 | if bin_size == '24H':
218 | nb_obs_per_day = 1
219 | elif bin_size == '1H':
220 | nb_obs_per_day = 24
221 | else:
222 | raise ValueError('Unknown bin size')
223 |
224 | start = intel_date(start)
225 | end = intel_date(end)
226 |
227 | dt = (end - start).days * nb_obs_per_day
228 |
229 | data = []
230 |
231 | # Iterative download
232 | for i in range(0, dt, 1000):
233 | # Request data
234 | data += self.get_data(
235 | source, coin, bin_size, start=start, end=end, start_ptr=i,
236 | )
237 | pct = i / ((dt - 1) // 1000 * 1000)
238 | print('Downloaded {:7.2%} [{}{}] '.format(
239 | pct, '=' * int(49 * pct),
240 | '>' * (1 - int(pct)) + ' ' * int(49 * (1 - pct))
241 | ), end='\r')
242 |
243 | # Sleep
244 | time.sleep(.1)
245 |
246 | return self._set_dataframe(data)
247 |
248 | def _set_dataframe(self, data):
249 | # Request topic names
250 | topics = self.send_request('topics')
251 |
252 | # Set dataframe
253 | df = pd.DataFrame(data)
254 | df = df.rename(columns={
255 | **{93: 'date', 94: 'TS'},
256 | **{int(k): a for k, a in topics.items()}
257 | })
258 |
259 | return df.set_index('date')
260 |
261 |
262 | def intel_date(date, form='%Y-%m-%dT%H:%M:%SZ'):
263 | """ Convert date to timedate object. """
264 | if isinstance(date, datetime.datetime):
265 | return date
266 |
267 | elif isinstance(date, str):
268 | return datetime.datetime.strptime(date, form)
269 |
270 | elif isinstance(date, int):
271 | return datetime.datetime.utcfromtimestamp(date)
272 |
273 | else:
274 | raise ValueError('Unknown date object, must be datetime, string\
275 | (with relevent format), or int (UTC timestamp)')
276 |
277 |
278 | if __name__ == '__main__':
279 |
280 | import doctest
281 | import yaml
282 | import logging.config
283 |
284 | # Load config logging
285 | with open('./augmento_client/logging.ini', 'rb') as f:
286 | config = yaml.safe_load(f.read())
287 |
288 | logging.config.dictConfig(config)
289 |
290 | # Run tests
291 | doctest.testmod()
292 |
--------------------------------------------------------------------------------
/src/analysis_helper.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import numba as nb
3 |
4 |
5 | @nb.jit("(f8[:])(f8[:], f8[:])", nopython=True, nogil=True, cache=True)
6 | def nb_safe_divide(a, b):
7 | # divide each element in a by each element in b
8 | # if element b == 0.0, return element = 0.0
9 | c = np.zeros(a.shape[0], dtype=np.float64)
10 | for i in range(a.shape[0]):
11 | if b[i] != 0.0:
12 | c[i] = a[i] / b[i]
13 | return c
14 |
15 | @nb.jit("(f8[:])(f8[:], i8)", nopython=True, nogil=True, parallel=False)
16 | def nb_causal_rolling_average(arr, window_size):
17 |
18 | # create an output array
19 | out_arr = np.zeros(arr.shape[0])
20 |
21 | # create an array from the input array, with added space for the rolling window
22 | new_arr = np.hstack((np.ones(window_size-1) * arr[0], arr))
23 |
24 | # for each output element, find the mean of the last few input elements
25 | #for i in nb.prange(out_arr.shape[0]):
26 | for i in range(out_arr.shape[0]):
27 | out_arr[i] = np.mean(new_arr[i : i + window_size])
28 |
29 | return out_arr
30 |
31 | @nb.jit("(f8[:])(f8[:], i8)", nopython=True, nogil=True, parallel=False)
32 | def nb_causal_rolling_sd(arr, window_size):
33 |
34 | # create an output array
35 | out_arr = np.zeros(arr.shape[0])
36 |
37 | # create an array from the input array, with added space for the rolling window
38 | new_arr = np.hstack((np.ones(window_size-1) * arr[0], arr))
39 |
40 | # for each output element, find the mean and std of the last few
41 | # input elements, and standardise the input element by the mean and std of the window
42 | #for i in nb.prange(out_arr.shape[0]):
43 | for i in range(out_arr.shape[0]):
44 | num = new_arr[i+window_size-1] - np.mean(new_arr[i : i + window_size-1])
45 | denom = np.std(new_arr[i : i + window_size-1])
46 | if denom != 0.0:
47 | out_arr[i] = num / denom
48 |
49 | return out_arr
50 |
51 | @nb.jit("(f8[:])(f8[:], i8)", nopython=True, nogil=True, parallel=False)
52 | def nb_causal_rolling_sd_rand(arr, window_size_rand):
53 |
54 | # create an output array
55 | out_arr = np.zeros(arr.shape[0])
56 |
57 | # create an array from the input array, with added space for the rolling window
58 | new_arr = np.hstack((np.ones(window_size_rand-1) * arr[0], arr))
59 |
60 | # create an array from the input array, with added space for the rolling window
61 | new_arr = np.hstack((np.ones(window_size_rand-1) * arr[0], arr))
62 | # for each output element, find the mean and std of the last few
63 | # input elements, and standardise the input element by the mean and std of the window
64 | #for i in nb.prange(out_arr.shape[0]):
65 | for i in range(out_arr.shape[0]):
66 | window_size_std = 1.0
67 | window_size = round(np.random.normal(window_size_rand, window_size_std))
68 | num = new_arr[i+window_size-1] - np.mean(new_arr[i : i + window_size-1])
69 | denom = np.std(new_arr[i : i + window_size-1])
70 | if denom != 0.0:
71 | out_arr[i] = num / denom
72 |
73 | return out_arr
74 |
75 | @nb.jit("(f8[:])(f8[:], i8)", nopython=True, nogil=True, parallel=False)
76 | def nb_causal_rolling_norm(arr, window_size):
77 |
78 | # create an output array
79 | out_arr = np.zeros(arr.shape[0])
80 |
81 | # create an array from the input array, with added space for the rolling window
82 | new_arr = np.hstack((np.ones(window_size-1) * arr[0], arr))
83 |
84 | # for each output element, find the mean and std of the last few
85 | # input elements, and standardise the input element by the mean and std of the window
86 | #for i in nb.prange(out_arr.shape[0]):
87 | for i in range(out_arr.shape[0]):
88 | num = new_arr[i+window_size-1] - np.mean(new_arr[i : i + window_size])
89 | denom = np.max(np.abs(new_arr[i : i + window_size] - np.mean(new_arr[i : i + window_size])))
90 | if denom != 0.0:
91 | out_arr[i] = num / denom
92 |
93 | return out_arr
94 |
95 | @nb.jit("(f8[:])(f8[:], i8, f8)", nopython=True, nogil=True, parallel=False)
96 | def nb_causal_rolling_norm_rand(arr, window_size_rand, peturb):
97 |
98 | # create an output array
99 | out_arr = np.zeros(arr.shape[0])
100 |
101 | # create an array from the input array, with added space for the rolling window
102 | new_arr = np.hstack((np.ones(window_size_rand-1) * arr[0], arr))
103 |
104 | index_new = window_size_rand
105 |
106 | # for each output element, find the mean and std of the last few
107 | # input elements, and standardise the input element by the mean and std of the window
108 | #for i in nb.prange(out_arr.shape[0]):
109 | for i in range(out_arr.shape[0]):
110 |
111 | window_size_std = peturb * np.float64(window_size_rand)
112 | window_size = round(np.random.normal(window_size_rand, window_size_std))
113 |
114 | i_end_new = i + window_size_rand
115 | i_start_new = i_end_new - window_size
116 |
117 | if i_start_new < 0:
118 | i_start_new = 0
119 |
120 | out_arr[i] = np.mean(new_arr[i_start_new : i_end_new])
121 | #print(out_arr[i-1:i+1])
122 |
123 | #num = new_arr[i+window_size-1] - np.mean(new_arr[i : i + window_size])
124 | #denom = np.max(np.abs(new_arr[i : i + window_size] - np.mean(new_arr[i : i + window_size])))
125 | #if denom != 0.0:
126 | # out_arr[i] = num / denom
127 |
128 | return out_arr
129 |
130 | @nb.jit("(f8[:])(f8[:], i8)", nopython=True, nogil=True, parallel=False)
131 | def nb_causal_rolling_average(arr, window_size):
132 |
133 | # create an output array
134 | out_arr = np.zeros(arr.shape[0])
135 |
136 | # create an array from the input array, with added space for the rolling window
137 | new_arr = np.hstack((np.ones(window_size-1) * arr[0], arr))
138 |
139 | # for each output element, find the mean of the last few input elements
140 | #for i in nb.prange(out_arr.shape[0]):
141 | for i in range(out_arr.shape[0]):
142 | out_arr[i] = np.mean(new_arr[i : i + window_size])
143 |
144 | return out_arr
145 |
146 |
147 |
148 | #@nb.jit("(f8[:])(f8[:], f8[:], i8, i8, f8)", nopython=True, nogil=True)
149 | def nb_calc_sentiment_score_rand_b(sent_a, sent_b, ra_win_size_short, ra_win_size_long,peturb):
150 | # example method for creating a stationary sentiment score based on Augmento data
151 |
152 | # compare the raw sentiment values
153 | sent_ratio = nb_safe_divide(sent_a, sent_b)
154 |
155 | # smooth the sentiment ratio
156 | sent_ratio_short = nb_causal_rolling_norm_rand(sent_ratio, ra_win_size_short, peturb)
157 | sent_ratio_long = nb_causal_rolling_norm_rand(sent_ratio, ra_win_size_long, peturb)
158 |
159 | # create a stationary(ish) representation of the smoothed sentiment ratio
160 | sent_score = sent_ratio_short - sent_ratio_long
161 |
162 | return sent_score
163 |
164 |
165 | @nb.jit("(f8[:])(f8[:], f8[:], i8, i8, f8)", nopython=True, nogil=True)
166 | def nb_calc_sentiment_score_rand_a(sent_a, sent_b, ra_win_size, std_win_size, peturb):
167 | # example method for creating a stationary sentiment score based on Augmento data
168 |
169 | # compare the raw sentiment values
170 | sent_ratio = nb_safe_divide(sent_a, sent_b)
171 |
172 | # smooth the sentiment ratio
173 | sent_ratio_smooth = nb_causal_rolling_norm_rand(sent_ratio, ra_win_size, peturb)
174 |
175 | # create a stationary(ish) representation of the smoothed sentiment ratio
176 | sent_score = nb_causal_rolling_sd(sent_ratio_smooth, std_win_size)
177 |
178 | return sent_score
179 |
180 | @nb.jit("(f8[:])(f8[:], f8[:], i8, i8)", nopython=True, nogil=True)
181 | def nb_calc_sentiment_score_a(sent_a, sent_b, ra_win_size, std_win_size):
182 | # example method for creating a stationary sentiment score based on Augmento data
183 |
184 | # compare the raw sentiment values
185 | sent_ratio = nb_safe_divide(sent_a, sent_b)
186 |
187 | # smooth the sentiment ratio
188 | sent_ratio_smooth = nb_causal_rolling_average(sent_ratio, ra_win_size)
189 |
190 | # create a stationary(ish) representation of the smoothed sentiment ratio
191 | sent_score = nb_causal_rolling_sd(sent_ratio_smooth, std_win_size)
192 |
193 | return sent_score
194 |
195 | @nb.jit("(f8[:])(f8[:], f8[:], i8, i8)", nopython=True, nogil=True)
196 | def nb_calc_sentiment_score_b(sent_a, sent_b, ra_win_size_short, ra_win_size_long):
197 | # example method for creating a stationary sentiment score based on Augmento data
198 |
199 | # compare the raw sentiment values
200 | sent_ratio = nb_safe_divide(sent_a, sent_b)
201 |
202 | # smooth the sentiment ratio
203 | sent_ratio_short = nb_causal_rolling_average(sent_ratio, ra_win_size_short)
204 | sent_ratio_long = nb_causal_rolling_average(sent_ratio, ra_win_size_long)
205 |
206 | # create a stationary(ish) representation of the smoothed sentiment ratio
207 | sent_score = sent_ratio_short - sent_ratio_long
208 |
209 | return sent_score
210 |
211 | @nb.jit("(f8[:])(f8[:], f8[:], i8, i8)", nopython=True, nogil=True)
212 | def nb_calc_sentiment_score_c(sent_a, sent_b, ra_win_size, std_win_size):
213 | # example method for creating a stationary sentiment score based on Augmento data
214 |
215 | # compare the raw sentiment values
216 | sent_ratio = nb_safe_divide(sent_a, sent_b)
217 |
218 | # smooth the sentiment ratio
219 | sent_ratio_smooth = nb_causal_rolling_average(sent_ratio, ra_win_size)
220 |
221 | # create a stationary(ish) representation of the smoothed sentiment ratio
222 | sent_score = nb_causal_rolling_norm(sent_ratio_smooth, std_win_size)
223 |
224 | return sent_score
225 |
226 | @nb.jit("(f8[:])(f8[:], f8[:], f8, f8)", nopython=True, nogil=True, cache=True)
227 | def nb_backtest_a(price, sent_score, start_pnl, buy_sell_fee):
228 | # example backtest with approximate model for long/short contracts
229 |
230 | # create an array to hold our pnl, and set the first value
231 | pnl = np.zeros(price.shape, dtype=np.float64)
232 | pnl[0] = start_pnl
233 |
234 | # for each step, run the market model
235 | for i_p in range(1, price.shape[0]):
236 |
237 | # if sentiment score is positive, simulate long position
238 | # else if sentiment score is negative, simulate short position
239 | # else if the sentiment score is 0.0, hold
240 | # (note that this is a very approximate market simulation!)
241 | n_sample_delay = 2
242 | if i_p < n_sample_delay:
243 | pnl[i_p] = pnl[i_p-1]
244 | if sent_score[i_p-n_sample_delay] > 0.0:
245 | pnl[i_p] = (price[i_p] / price[i_p-1]) * pnl[i_p-1]
246 | elif sent_score[i_p-n_sample_delay] <= 0.0:
247 | pnl[i_p] = (price[i_p-1] / price[i_p]) * pnl[i_p-1]
248 | elif sent_score[i_p-n_sample_delay] == 0.0:
249 | pnl[i_p] = pnl[i_p-1]
250 |
251 | # simulate a trade fee if we cross from long to short, or visa versa
252 | if i_p > 1 and np.sign(sent_score[i_p-1]) != np.sign(sent_score[i_p-2]):
253 | pnl[i_p] = pnl[i_p] - (buy_sell_fee * pnl[i_p])
254 |
255 | return pnl
256 |
257 |
258 |
259 |
260 | @nb.jit("(f8[:])(f8[:], i8)", nopython=True, nogil=True, cache=True)
261 | def moving_average(arr, window):
262 |
263 | # output array
264 | ma_arr = np.zeros(arr.shape[0])
265 |
266 | # add space for rolling window
267 | new_arr = np.hstack((np.ones(window-1) * arr[0], arr))
268 |
269 | # calculate moving average
270 | #for i in nb.prange(arr.shape[0]):
271 | for i in range(arr.shape[0]):
272 | num = new_arr[i+window-1] - np.mean(new_arr[i : i+window-1])
273 | denom = np.std(new_arr[i : i + window-1])
274 | if denom != 0.0:
275 | ma_arr[i] = num / denom
276 |
277 | return ma_arr
278 |
279 | #@nb.jit("(f8[:])(f8[:], i8)", nopython=True, nogil=True, cache=True)
280 | #def signal_ma(positive, negative, short, long):
281 |
282 |
283 |
284 |
285 |
286 | @nb.jit("(f8[:])(f8[:], f8[:], f8[:], f8, f8, f8)",nopython=True, nogil=True,cache=True)
287 | def sma_crossover_backtest(price, leading_arr, lagging_arr, start_pnl, buy_sell_fee, threshold=0.0):
288 |
289 | # create an array to hold our pnl, and set the first value
290 | pnl = np.zeros(price.shape, dtype=np.float64)
291 | pnl[0] = start_pnl
292 |
293 | # BUY if Leading SMA is above Lagging SMA by some threshold.
294 | # SELL if Leading SMA is below Lagging SMA by some threshold.
295 | sent_signal = leading_arr - lagging_arr
296 |
297 | # for each step, run the market model
298 | for i_p in range(1, price.shape[0]):
299 | if sent_signal[i_p-1] > threshold:
300 | pnl[i_p] = (price[i_p] / price[i_p-1]) * pnl[i_p-1]
301 | elif sent_signal[i_p-1] < threshold:
302 | pnl[i_p] = (price[i_p-1] / price[i_p]) * pnl[i_p-1]
303 | elif sent_signal[i_p-1] == threshold:
304 | pnl[i_p] = pnl[i_p-1]
305 |
306 | # simulate a trade fee if we cross from long to short, or visa versa
307 | if i_p > 1 and np.sign(sent_signal[i_p-1]) != np.sign(sent_signal[i_p-2]):
308 | pnl[i_p] = pnl[i_p] - (buy_sell_fee * pnl[i_p])
309 |
310 | return pnl
311 |
312 |
313 | #@nb.jit("(f8[:])(f8[:], f8[:], i8)", nopython=True, nogil=True, cache=True)
314 | #def forward_volume(volume_data, price_data, threshold=2000000):
315 |
316 | # price_rate_change = np.full(len(volume_data), np.nan)
317 |
318 | # for i in range(len(volume_data)):
319 | # sum_volume = 0
320 |
321 | # for j in range(len(price_data)):
322 | # sum_volume += price_data[j]
323 |
324 | # if sum_volume >= threshold:
325 | # price_rate_change[i] = (price_data[j] - price_data[i])/price_data[i]
326 | # break
327 |
328 | @nb.jit("(f8[:])(f8[:], f8[:], i8)", nopython=True, nogil=True, cache=True)
329 | def forward_volume(volume_data, price_data, threshold=2000000):
330 |
331 | price_rate_change = np.zeros(len(price_data))
332 |
333 | for i in range((len(volume_data))):
334 | j = i+1
335 | sum_volume = 0.0
336 |
337 | while (sum_volume < threshold) & (j < len(price_rate_change)):
338 | sum_volume += volume_data[j]
339 |
340 | if sum_volume >= threshold:
341 | price_rate_change[i] = (price_data[j]-price_data[i])/price_data[i]
342 |
343 | j += 1
344 |
345 | return price_rate_change
346 |
347 | @nb.jit("(f8[:])(f8[:], f8[:], f8)", nopython=True, nogil=True, cache=True)
348 | def forward_volume(volume_data, price_data, threshold):
349 |
350 | price_rate_change = np.zeros(len(price_data))
351 |
352 | for i in range((len(volume_data))):
353 | j = i+1
354 | sum_volume = 0.0
355 |
356 | while (sum_volume < threshold) & (j < len(price_rate_change)):
357 | sum_volume += volume_data[j]
358 |
359 | if sum_volume >= threshold:
360 | price_rate_change[i] = (price_data[j]-price_data[i])/price_data[i]
361 |
362 | j += 1
363 |
364 | return price_rate_change
365 |
366 |
367 | @nb.jit("(f8[:])(f8[:], i8)", nopython=True, nogil=True, cache=True)
368 | def volume_normalized(volume_data, n_hours):
369 | norm_volume = np.zeros(len(volume_data))
370 | start = 0
371 | for i in range(n_hours,len(volume_data), n_hours):
372 | for j in range(start,i):
373 | norm_volume[j] = volume_data[j]/np.sum(volume_data[start:i])
374 | start = i
375 | return norm_volume
376 |
377 |
378 |
379 |
380 |
381 |
382 |
--------------------------------------------------------------------------------
/notebooks/2_moving_windows.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 2,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "import sys\n",
10 | "sys.path.insert(0, \"../src\")\n",
11 | "import example_helper as eh\n",
12 | "import analysis_helper as ah\n",
13 | "import msgpack\n",
14 | "import zlib\n",
15 | "import numpy as np\n",
16 | "import datetime\n",
17 | "import time\n",
18 | "import matplotlib.pyplot as plt\n",
19 | "import matplotlib.dates as md\n",
20 | "from matplotlib.pyplot import figure\n",
21 | "import pandas as pd\n",
22 | "import seaborn as sns; sns.set()"
23 | ]
24 | },
25 | {
26 | "cell_type": "markdown",
27 | "metadata": {},
28 | "source": [
29 | "# Get Data"
30 | ]
31 | },
32 | {
33 | "cell_type": "code",
34 | "execution_count": 3,
35 | "metadata": {},
36 | "outputs": [],
37 | "source": [
38 | "# define the location of the input file\n",
39 | "filename_augmento_topics = \"../data/example_data/augmento_topics.msgpack.zlib\"\n",
40 | "filename_augmento_data = \"../data/example_data/augmento_data.msgpack.zlib\"\n",
41 | "filename_bitmex_data = \"../data/example_data/bitmex_data.msgpack.zlib\"\n",
42 | "\n",
43 | "# load the example data\n",
44 | "all_data = eh.load_example_data(filename_augmento_topics,\n",
45 | " filename_augmento_data,\n",
46 | " filename_bitmex_data)\n",
47 | "aug_topics, aug_topics_inv, t_aug_data, aug_data, t_price_data, price_data = all_data\n",
48 | "all_topics = aug_data.T.astype(float)"
49 | ]
50 | },
51 | {
52 | "cell_type": "markdown",
53 | "metadata": {},
54 | "source": [
55 | "# Example for Topics \"Bullish\" and \"Bearish\""
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": 4,
61 | "metadata": {},
62 | "outputs": [],
63 | "source": [
64 | "aug_signal_a = aug_data[:, aug_topics_inv[\"Bullish\"]].astype(np.float64)\n",
65 | "aug_signal_b = aug_data[:, aug_topics_inv[\"Bearish\"]].astype(np.float64)\n"
66 | ]
67 | },
68 | {
69 | "cell_type": "code",
70 | "execution_count": 5,
71 | "metadata": {},
72 | "outputs": [],
73 | "source": [
74 | "# define the window size for the sentiment score calculation\n",
75 | "n_days = 7\n",
76 | "window_size = 24 * n_days\n",
77 | "\n",
78 | "# generate the sentiment score\n",
79 | "sent_score = ah.nb_calc_sentiment_score_a(aug_signal_a, aug_signal_b, window_size, window_size)\n",
80 | "\n",
81 | "# define some parameters for the backtest\n",
82 | "start_pnl = 1.0\n",
83 | "buy_sell_fee = 0.0075\n",
84 | "\n",
85 | "# run the backtest\n",
86 | "pnl = ah.nb_backtest_a(price_data, sent_score, start_pnl, buy_sell_fee)"
87 | ]
88 | },
89 | {
90 | "cell_type": "markdown",
91 | "metadata": {},
92 | "source": [
93 | "# Compare various windows sizes"
94 | ]
95 | },
96 | {
97 | "cell_type": "code",
98 | "execution_count": 6,
99 | "metadata": {},
100 | "outputs": [],
101 | "source": [
102 | "sent_score = ah.nb_calc_sentiment_score_a(aug_signal_a,aug_signal_b,1,2)\n",
103 | "pnl = ah.nb_backtest_a(price_data, sent_score, 1.0, 0.0075)"
104 | ]
105 | },
106 | {
107 | "cell_type": "code",
108 | "execution_count": 7,
109 | "metadata": {},
110 | "outputs": [],
111 | "source": [
112 | "sent_score = ah.nb_calc_sentiment_score_a(aug_signal_a,aug_signal_b,7*24,7*24)\n",
113 | "pnl = ah.nb_backtest_a(price_data, sent_score, 1.0, 0.0075)"
114 | ]
115 | },
116 | {
117 | "cell_type": "code",
118 | "execution_count": 8,
119 | "metadata": {},
120 | "outputs": [],
121 | "source": [
122 | "# different windows sizes for sentiment score b\n",
123 | "#h = 24\n",
124 | "s_days = 20 # short\n",
125 | "l_days = 20 # long\n",
126 | "\n",
127 | "win_all_a = np.zeros(shape=(s_days,l_days))\n",
128 | "win_all_b = np.zeros(shape=(s_days,l_days))\n",
129 | "\n",
130 | "# matrix of size (s_days,l_days)\n",
131 | "\n",
132 | "for i in range(0, s_days):\n",
133 | " for j in range(0, l_days):\n",
134 | " sent_score_a = ah.nb_calc_sentiment_score_a(aug_signal_a,aug_signal_b,(i+1)*24,(j+1)*24)\n",
135 | " sent_score_b = ah.nb_calc_sentiment_score_b(aug_signal_a, aug_signal_b, (i+1)*24,(j+1)*24)\n",
136 | " #pnl_a = ah.nb_backtest_a(price_data, sent_score_a, 1.0, 0.0075)\n",
137 | " #pnl_b = ah.nb_backtest_a(price_data, sent_score_b, 1.0, 0.0075)\n",
138 | " win_all_a[i,j] = ah.nb_backtest_a(price_data, sent_score_a, 1.0, 0.0075)[-1]\n",
139 | " win_all_b[i,j] = ah.nb_backtest_a(price_data, sent_score_b, 1.0, 0.0075)[-1]"
140 | ]
141 | },
142 | {
143 | "cell_type": "code",
144 | "execution_count": 9,
145 | "metadata": {},
146 | "outputs": [],
147 | "source": [
148 | "##plot\n",
149 | "#cmap = sns.cubehelix_palette(50, hue=0.05, rot=0, light=0.0, dark=1.2, as_cmap=True)\n",
150 | "#figure(num=None, figsize=(10, 7), dpi=80, facecolor='w', edgecolor='k')\n",
151 | "#ax = sns.heatmap(win_all_a, linewidth=0.01, cmap=cmap)\n",
152 | "#plt.show()"
153 | ]
154 | },
155 | {
156 | "cell_type": "code",
157 | "execution_count": 10,
158 | "metadata": {},
159 | "outputs": [],
160 | "source": [
161 | "##plot\n",
162 | "#cmap = sns.cubehelix_palette(50, hue=0.05, rot=0, light=0.0, dark=1.2, as_cmap=True)\n",
163 | "#figure(num=None, figsize=(10, 7), dpi=80, facecolor='w', edgecolor='k')\n",
164 | "#ax = sns.heatmap(win_all_b, linewidth=0.01, cmap=cmap)\n",
165 | "#plt.show()"
166 | ]
167 | },
168 | {
169 | "cell_type": "code",
170 | "execution_count": 11,
171 | "metadata": {},
172 | "outputs": [],
173 | "source": [
174 | "# different windows sizes for sentiment score b\n",
175 | "#h = 24\n",
176 | "s_days = 20 # short\n",
177 | "l_days = 20 # long\n",
178 | "\n",
179 | "win_all_a = np.zeros(shape=(s_days,l_days))\n",
180 | "\n",
181 | "# matrix of size (s_days,l_days)\n",
182 | "\n",
183 | "for i in range(0, s_days):\n",
184 | " for j in range(0, l_days):\n",
185 | " sent_score_a = ah.nb_calc_sentiment_score_a(aug_signal_a,aug_signal_b,(i+1)*24,(j+1)*24)\n",
186 | " #pnl_a = ah.nb_backtest_a(price_data, sent_score_a, 1.0, 0.0075)\n",
187 | " #pnl_b = ah.nb_backtest_a(price_data, sent_score_b, 1.0, 0.0075)\n",
188 | " win_all_a[i,j] = ah.nb_backtest_a(price_data, sent_score_a, 1.0, 0.0075)[-1]\n"
189 | ]
190 | },
191 | {
192 | "cell_type": "code",
193 | "execution_count": 12,
194 | "metadata": {},
195 | "outputs": [
196 | {
197 | "data": {
198 | "image/png": "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vKC572S+95NOekFT7bnnnp3DD396U+1VV327uXZT/fHHP7updvXqb+aVr3x1U+3nPveZPO95JzXVJsl5552bV73qNU21n/3sp5v7TuZ7L+WQptpar20eFx6L1tycm5trzr1kPvv6jL3ttts2j/3QQw815+7DDz+cnXfepan23nvvac7MZD43jzrqmU21l19+WY477vjmsS++eHWOOea4ptpLL704RxxxZFPtd75zZfPXnMx/3X36fsYzjm6qveKKNTnyyKOaapPkyisvzxvecGpT7cc+9uHeufniF5/cVPvVr34pv/Zrr2uq/du//escfPBTm2qT5LrrvtdcOy5sr7116JNd22+/ffO4DzzwwEjmmw8//HB23HHHptok2bBhQ6+56p57PqF57Dvu+GHzc/GVV16eQw45tKn22muvyQEHHNhUmyRr196Uww47oqn26qu/k6c97fDmsb/73at6zTcPPfSwptprrrm6+WtO5r/uPvPNPq9TTjzxeU21SXL++eflv/23dzTV/s//+cd5wQte1Dz22Wef1VwLj0Wf3BzlXLV1vvnQQw9lhx12aB77/vvvbz5Pe/fdP2nOzTvu+GGe9KT9m2qT5Oab1zWfp12z5tLeGXDCCb/YVHvBBf/Y/Fx69tln5dhjn9VUmySXXHJRr/zpM1d9yUt+uak2Sb7ylX/odV6i77npl770ZU21X/7ymb3eCxhjb0vyzkWOvzvJu7o8QCllnyRfTfKRRy6gSZJa6ymb3fdPk9zU0ij939scReZuqu8zV+2TuTvttFNTbZLcd9992WOPPZtq77zzjuy1197NY99++21Ztergptrrr7+ueezbb7+t+WtO5r/uPnPVffZ5YlPtrbf+oHmumczPN5///Bc21Z5zztfyO7/zX5vHfu97/7TX96z1fP7FF6/Ob//2f26qTZI///P3NZ9b+O53r2oedxoNdRENAADAuCil7Jpufx24aXvtv1m4/a/bay88zpa2135yKeW/Z34L7t+qtd69XP0DAACwVTo9839s8UiL7kLzSKWUg5OcleQvaq3vXeTzuyT59Vrrpj/kmEnyUFurADB9LKIBAABYXKe/Dqy1npokpZRNt29OcvPCsd2T/GaS1y/yOLfn326v/ZdJbK8NAAAwwRb+KKPTgplHKqU8LsnZSd5Ra/3ko9ztn5P811LK6lrrJZmfk57R1CwATCGLaAAAABbX968Dba8NAADAcjo1yZ5J3l5KefvCsTNrrX9YSvnwwsdnllJ+NckHSik7JLk+Sds1ngFgCllEAwAAsIiefx1oe20AAACWRa11/4UP37fwb7H7nLrZxxcmecbgOwOAybNi1A0AAABMks221/79xRbQLNi0vfaxC7dtrw0AAAAAMGJ2ogEAAFhettcGAAAAABhDFtEAAAAsA9trAwAAAACMN5dzAgAAAAAAAABg6llEAwAAAAAAAADA1Fvyck6llKckua/Welsp5dQkhyf5Zq317wfeHQCMEZkJAN3JTQDoTm4CQHdyE4A+trgTTSnlPyf5WpKLSikfTfKaJNcl+Y1Syh8MoT8AGAsyEwC6k5sA0J3cBIDu5CYAfS21E82vJ3lqkj2TXJPk8bXWB0opH05yWZL3DLg/gIk3Nzc3tLFmZmaGNtYUkpkAQyA3J4bcBBiwYWZmIjcHTG4CDJi55kSRmwADNum5ucWdaBY+/2Ct9eYk/6vW+sBmn1vyUlAAMEVkJgB0JzcBoDu5CQDdyU0AelkqLD6f5IJSyi/WWt+VJKWUI5J8KInrBgIsg9nZ2aGNtXLlyqGNNYVkJsAQyM2JITcBBmyYmZnIzQGTmwADZq45UeQmwIBNem5ucSeaWusfJvn9WuvGzQ4/kOSdtdZ3D7QzABgjMhMAupObANCd3ASA7uQmAH0tuW1ZrfUbj7hdk9SBdQQwZYZ9nXoGR2YCDJ7cnBxyE2CwZOZkkZsAgyU3J4vcBBisSc/NLe5EAwAAAAAAAAAA02DJnWgAGKxJX60JAMtJbgJANzITALqTmwDQ3aTnpp1oAAAAAAAAAACYenaiARixSV+tCQDLSW4CQDcyEwC6k5sA0N2k56adaAAAAAAAAAAAmHp2ogEYsUlfrQkAy0luAkA3MhMAupObANDdpOemnWgAAAAAAAAAAJh6dqIBGLHZ2dlRtwAAY0NuAkA3MhMAupObANDdpOemnWgAAAAAAAAAAJh6M0O+XtVkXxwLmCYzy/VAGzZsGNpz44477rhsfTNwMhOYFMuaPXKTRyE3gUkxlnPNRG6OGbkJTIqxzE2ZOXbkJjAp5GZHQ72c08xM+9c3NzfXXD83N5eVK1c21W7cuDE77rhjU22SbNiwIY973M5NtT/96b055pjjmse+9NKLc9JJL2iqPffcs/OTn9zdVPtzP7dbPvCBDzbVJsmb33xa3vGOP2iq/eM/fk9OOeWVzWOfccbnctRRz2yqvfzyy/K8553UVHveeefm+OOf3VSbJKtXfzP//t//x6baT37yE3nxi09uqv3qV7/Uu+/nP/+FTbXnnPO1vOENpzaP/bGPfTivetVrmmo/+9lPN48Lj0Wf3OubuStWtG1WNzs7m5122ql57Pvuu685dzds2JCXv/wVTbVf/OIXmms31fdx/vnfaK498cTnNj8Xr179zbz61a9tqv3MZz6VZzzj6KbaJLniijV56Utf1lT75S+fmWOPfVZT7SWXXJTTTntzU22SfPCDH+j1+qo195L57HvZy05pqj3zzDPy67/+xqbaj370Q80/q2T+5wXDMK65ud122zXVPvjgg70zt5RDmmprvTYveckvN4/9la/8Q57ylNJUe8MNNe9613uaat/1rj/IkUce1VSbJFdeeXmvOURrdiXz+XXyyS9vqv3Sl76YVasObqq9/vrr8pznnNBUmyQXXnhBr3lyn8zt+zva53VK6/w8mZ+jwzCMIjf7nKNN5s/Tbr/99k21DzzwQHbYYYfmse+///4cdtgRTbVXX/2dXs8pT3va4U21SfLd716V97//r5pq3/KWN/V+Pms9d/exj3241zz3uOOOb6pNkosvXp2DD35qU+11130vz33uiU213/jG+c1Zn/TP+77fsz5z9Be96KVNtWed9eWmOnisRvneZutcM5mfb+688y5Ntffee89I39vs835X67mzZP782W/8xmlNtR/5yAfz6U9/tqn2Na95Ve9zb8961i801V500bd61baeV0jmzy0cffQxTbVr1lza+3VK6+/ppZde3OucxqGHHtZUmyTXXHN181z3K1/5h+Zxp5HLOQEAAAAAAAAAMPWGuhMNAD9ruFfVA4DxJjcBoBuZCQDdyU0A6G7Sc9MiGgAeVSll5ySrk5xca11XSjktyW9n/jqwa5K8qdb6L6PsEQAAAAAAAGA5WEQDMGJzW+lyzVLKsUk+lGTVwu1VSX43yVFJfprk40nemuR9I2oRgCm0teYmAGxtZCYAdCc3AaC7Sc/NFaNuAICt1hszv0jmtoXbDyZ5c6313lrrXJKrk+w3quYAAAAAAAAAlpOdaABGbJirNUspuybZdZFPra+1rt/8QK311IWaTbdvTnLzwrHdk/xmktcPsF0A+BmT/lcOALBcZCYAdCc3AaC7Sc9NO9EATJe3JVm7yL+3dX2AUso+Sb6e5CO11vMH0CMAAAAAAADA0NmJBmDEZmdnhznc6Uk+vsjx9Ysc+xmllIOTnJXkL2qt713GvgCgkyHnJgCMLZkJAN3JTQDobtJz0yIagCmycMmmTgtmHqmU8rgkZyd5R631k8vaGAAAAAAAAMCIWUQDMGJjdN3AU5PsmeTtpZS3Lxw7s9b6hyPsCYApM0a5CQAjJTMBoDu5CQDdTXpurngsdy6luHQHwJSpte5fa11Xa31frXW7WuvTN/tnAc0WyE0A6E5uAkB3chMAupObADwWj7oTTSnlo4scflkpZbckqbX++sC6Apgik75ac1rITYDhkJuTQW4CDJ7MnBxyE2Dw5ObkkJsAgzfpubmlyzn9OMl/TPJHSdYvHPulJBcMuikAGENyEwC6k5sA0J3cBIDu5CYAvTzq5Zxqrb+b5N8leU2Sm2utn0jyk1rrJxY+BmAZzM3NDe0fgyM3AYZDbk4GuQkweMPMTLk5WHITYPBk5uSQmwCDN+m5+aiLaJKk1vr1JC9N8pZSyv9KsnIoXQHAGJKbANCd3ASA7uQmAHQnNwHoY0uXc0qS1Fp/kuRXSymnJjl88C0BTBd/fTBZ5CbAYMnNySI3AQZna87MUsrOSVYnObnWuq6UclqS304yl2RNkjfVWv9llD1ujeQmwOBszblJG7kJMDiTnptLLqLZpNb64SQfHmAvADAx5CYAdCc3AaZHKeXYJB9Ksmrh9qokv5vkqCQ/TfLxJG9N8r4RtbjVk5sA0J3cBOCx2uLlnAAAAAAAltEbM79I5raF2w8meXOt9d5a61ySq5PsN6rmAAAAmG6dd6IBYDBmZ2dH3QIAjA25CQDdDDszSym7Jtl1kU+tr7Wu33Sj1nrqwv033b45yc0Lx3ZP8ptJXj/gdgHg3zDXBIDuJj037UQDAAAAAPT1tiRrF/n3ti7FpZR9knw9yUdqrecPqEcAAADYIjvRAIzY3NzcqFsAgLEhNwGgmxFk5ulJPr7I8fWLHPs3SikHJzkryV/UWt+7zH0BwJLMNQGgu0nPTYtoAAAAAIBeFi7ZtOSCmUcqpTwuydlJ3lFr/eSyNwYAAACPgUU0ACM26as1AWA5yU0A6GaMMvPUJHsmeXsp5e0Lx86stf7hCHsCYMqMUW4CwMhNem5aRAMAAAAADFWtdf+FD9+38A8AAABGziIagBGb9NWaALCc5CYAdCMzAaA7uQkA3U16bs4M+Quc7O8mME1mluuBfvjDO4b23PiEJ+y5bH0zcDITmBTLmj1yk0chN4FJMZZzzURujhm5CUyKscxNmTl25CYwKeRmR0PdiWZmpv3rm5uby8qVK5tqN27cmB122KGp9v77789ee+3dVJskt99+W1772v/QVPupT/1NDjjgwOax1669KXvvvU9T7W233ZojjjiyqfY737kyBx/81KbaJLnuuu8111933ffy3Oee2Dz2N75xfq+x99//gFX7Y0EAACAASURBVKbadevW5rjjjm+qTZKLL16dE074xabaCy74xxxyyKFNtddee03vn/WRRx7VVHvllZc3126qX7Xq4Kba66+/rnncxUz6ak3ateZmn8xMRp+bxxxzXFPtpZdenMMOO6Kp9uqrv5Pdd9+jqTZJ7rrrzjzlKaWp9oYbako5pHnsWq/Ns5/93Kbab37zG72eh/u+TmmtX7v2pjzrWb/QVHvRRd/KKae8sqk2Sc4443M56aQXNNWee+7ZOfTQw5rHvuaaq3Pssc9qqr3kkovyjGcc3VR7xRVrmjMzkZsMT5/cXLFiRfO4s7OzzfWzs7PZZZddm2rvuWd9Tj755U21SfKlL30xxx//7Kba1au/2TvvW+c/F1+8Ok960v5NtTffvK75a07mv+7DD396U+1VV307Bx54UPPYN910Y6/5y8tedkpT7ZlnntF7jt1a/41vnN9rrto6R07m58l9Xle2Zm4yn7vLRWayJX1ys09ta+4l89m37777NdXecsv38/znv7B57HPO+Vpe8IIXNdWeffZZvfrue/6rz5zvqKOe2Tz25Zdf1jz/ueaaq5vHvvzyy/Kc55zQVJskF154QX71V/9dU+3f//3f5eijj2mqXbPm0ubsSebzp0/en3ji85rHPv/883r9nj3veSc11Z533rlNdY9GbvJo+r632We+uNNOOzWPfd9992X77bdvqn3ggQfyohe9tKn2rLO+3Pw6Ppl/Ld/nvba+udk617399tt6nXvrmwF93g/uc46277yr9fXZOed8rfdctc/rlD7nNF7xilc11SbJF77w2V59L6dJz832M4UAAAAAAAAAADAhhroTDQA/a3Z2dtQtAMDYkJsA0I3MBIDu5CYAdDfpuWknGgAAAAAAAAAApp6daABGbNKvGwgAy0luAkA3MhMAupObANDdpOemnWgAAAAAAAAAAJh6dqIBGLFJX60JAMtJbgJANzITALqTmwDQ3aTnpp1oAAAAAAAAAACYehbRAAAAAAAAAAAw9VzOCWDEJn3LMwBYTnITALqRmQDQndwEgO4mPTftRAMAAAAAAAAAwNTb4k40pZRn1lovW/j4l5K8JMlDSc6otV4yhP4AJt6kr9acFjITYDjk5mSQmwCDJzMnh9wEGDy5OTnkJsDgTXpuLrUTzV8lSSnlrUlOT3JLkjuS/FUp5TcH3BsAjBOZCQDdyU0A6E5uAkB3chOAXra4E81m3pjkxFrrj5OklPLhJJcl+ctBNQYwLWZnZ0fdAstLZgIMkNycOHITYEBk5kSSmwADIjcnktwEGJBJz82ldqLZtpSyIsmdSe7b7Pi/JJns7wwAPDYyEwC6k5sA0J3cBIDu5CYAvSy1iOauzG9z9tQk/2+SlFKel+RbST472NYApsPc3NzQ/jFQMhNgCOTmxJCbAAM2zMyUmwMnNwEGTGZOFLkJMGCTnptbvJxTrfV5SVJKKUl2Wzj8YJJ31lq/PODeAGBsyEwA6E5uAkB3chMAupObAPS1xUU0m9Ra62Yff2tw7QBMH399MFlkJsBgyc3JIjcBBkdmTh65CTA4cnPyyE2Awdmac7OUsnOS1UlOrrWuK6WcluS3k8wlWZPkTbXWf9nSYyx1OScAAAAAAAAAANhqlVKOTfLNJKsWbq9K8rtJjk9yeObXx7x1qcfptBMNAIOzFS/WBICtjtwEgG5kJgB0JzcBoLutODffmPlFMn+zcPvBJG+utd6bJKWUq5Pst9SDWEQDAAAAAAAAAMBWpZSya5JdF/nU+lrr+s0P1FpPXajZdPvmJDcvHNs9yW8mef1SY1pEAzBiW/N1AwFgayM3AaAbmQkA3clNAOhuyLn5tiTvXOT4u5O8q8sDlFL2SfLVJB+ptZ6/1P0togEAAAAAAAAAYGtzepKPL3J8/SLHfkYp5eAkZyX5i1rre7vUWEQDMGKzs7OjbgEAxobcBIBuZCYAdCc3AaC7YebmwiWbOi2YeaRSyuOSnJ3kHbXWT3ats4gGAAAAAAAAAIBJcmqSPZO8vZTy9oVjZ9Za/3BLRRbRAAAAAAAAAAAw9mqt+y98+L6Ff4/JzNzc3LI2tIShDgYwQDPL9UDXXXf90J4bDz541bL1zcDJTGBSLGv2yE0ehdwEJsVYzjUTuTlm5CYwKcYyN2Xm2JGbwKSQmx0NdSeamZn2r29ubq65fm5uLitXrmyq3bhxY37+5x/fVJskP/7xj7L33vs01d5226058MCDmse+6aYbc+yxz2qqveSSi/Kc55zQVHvhhRfkl37p+U21SfL1r5/T/HXfdNONefObf7N57A984C9z0kkvaKo999yz86IXvbSp9qyzvpzjjju+qTZJLr54dU455ZVNtWec8bk861m/0FR70UXfyvOf/8Km2iQ555yv5SUv+eWm2q985R9y5JFHNY995ZWX55BDDm2qvfbaa5rHhceiT+6tWLGiedzZ2dnssMMOTbX3339/Djroyc1j33jjP2X33fdoqr3rrjt7/b9+xjOObqpNkiuuWJPDD396U+1VV327OT+S+Qw5/vhnN9WuXv3NXrnX+jojmX+t0ScDTjjhF5tqL7jgH/PiF5/cVJskX/3ql5qz75xzvpYTT3xe89jnn39eTj755U21X/rSF3v9/9h33/2aapPkllu+31wLj0Wf3Nx2222bx33ooYeyzTZtU+uHH364eb754x//KEcffUxTbZKsWXNp9tzzCU21d9zxw965+bKXndJUe+aZZ+R1r3tDU+1f//XH8pSnlKbaJLnhhtpr7tR3/vKKV7yqqfYLX/hs3vSmtzTV/tVfvb953E1jt/6erllzaX7t117XVPu3f/vXza8zkvnXGoceelhT7TXXXN2cuYn5JsMzivnm7Oxsdt11t6baJFm//u7ss88Tm2pvvfUHzXPNZH6+2ec8a58526/8yv/VVJsk/+f/fL7X/KXv89krX/nqptrPfe4zveZ8ra8VkvnXC69+9Wubaj/zmU/lVa96TVPtZz/76bz2tf+hqTZJPvWpv+l1brp1rpnMzzf7nBPpk7kwDH3f2+zz/mRr7ab6PudZ+9TutdfeTbVJcvvtt2XVqoObaq+//rr83u9t8QotW/RHf/T/5KijntlUe/nll/Xqu+/7qn1ys8/54Te84dSm2iT52Mc+3Pze6MUXr+59XqLPHLtP7h1wwIFNtUmydu1N2X//A5pq161b2zzuNHI5J4ARG/KOYAAw1uQmAHQjMwGgO7kJAN1Nem62/5k6AAAAAAAAAABMCDvRAIzYpK/WBIDlJDcB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yFOeUppqk+SGG2p+/ucf31T74x//KHvvvU/z2Lfddmtz7zfcULP77ns01d511515/ON3b6pNkh/96K7suutuTbXr19+dXXbZtXnse+5Z32vsgw56clPtjTf+U570pP2bapPk5pvXZd9992uqveWW72effZ7YVHvrrT/IHnvs2VSbJHfeeUce97idm2p/+tN7s9tuP9c89t13/yQ777xLU+29997TPC48Fq252Sczk/nc3HbbbZtqH3rooaxadXDz2Ndff10OOODAptq1a2/qlbmt424au/X58M4772jO3GQ+d/s8j++1195NtbffflvvzG3NvptvXpcDDzyoqfamm27snbl9+t5zzyc0j33HHT/MTjvt1FR73333Nf+87rlnffO4m8aGYRhlbm633XZNtQ8++GCv5/DWOUAyPw/ok12tc59kfv7TZ+w+r+Of+MR9m2qT5Ac/uKVX361zzWR+vtkn+/q8vur7e9bn3EKf2r5z1T5jt/6OJuabDE+f3Nxmm7ZTyg8//HDv/x99XtPuv/8BzWOvW7e2V/70OW/X99x0n+zqO+drPXd3990/6fWz7vs965ObffK6tXZTfet88447ftj7PGufn1ef8/EwDH3f21y5cmVT7caNG7PDDjs0j33//ff3yq5RnjPsc/6r9T2nZP59pz7PSX2+Z621m+r7/Kz75F7fc+p9zom0vheQzL8f0Oe9hD6/o33/X/dZ80B3Q11EA8DPGvKOYJ2VUv57kjckeTDJZ2qtfzTilgBgq81NANjayEwA6E5uAkB3k56b7X9uB8DEKqWclOS1SZ6Z5Mgkx5ZSXjHargAAAAAAAAAGx040ACM2Ozs76hYWc2SSr9Va702SUspZSX4lyRdG2hUAU28rzU0A2OrITADoTm4CQHeTnpsW0QBMkVLKrkkWuyDp+lrr+s1uX5HkfaWUP0myIcnLYvcyAAAAAAAAYIJZRAMwYkO+buDbkrxzkePvTvKuTTdqrV8vpXw8yflJfpLk3CTHDb49ANiySb/eLgAsF5kJAN3JTQDobtJz0yIagOlyepKPL3J8811oUkp5XJIv1Fr/bOH2f0ly48C7AwAAAAAAABgRi2gARmyYqzUXLtm0fsk7Jgck+etSytFJdkpyapI3DrI3AOhi0v/KAQCWi8wEgO7kJgB0N+m5uWLUDQCw9am1XpXk80muSnJpkj+v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K+ZlNzVz3tFNoCt0s6U5vZ3TggX1n9/09HRWWKFu45ypqamsvPLKVbO333571lhjzarZJPnlL2/KBhtsWDV79dW/SNM8snrtUn6cjTbauGr2yiuvyLrrrlc1e9111+be97531WyS/PGPf8x6661fNXvttddkrbXWrl77xhtvyDbbbFs1e+65Z+dVrzqgavaooz6UD33oqKrZJDnggFflhBNOqprdY4/dcsghh1XNHnHEO/Oyl+1bNZskn/jE0dl556dXzZ566tez2257VK990kknDPW1hrlQ283p6emsuOKK1esuWbJkqG7Wtifp9WeYbm666aOqZi+77EdD936Y5t73vverXvvmm3+fRz96YdXspZcuzjrrrFs1e/3112XLLbeqmk2SCy9clFe/+rVVsx/+8AfzkY8cXTW7//775sQTv1Q1myS7777rUMddO3vn/DOesUvV7Ne+dnL23PMFVbPHH/+56r/jJL2/58BcGKabw56rrrbaalWzt956ax7wgAdWzf72t7+p7l7Sa98wfxffZJOmeu2f/rRk8823qJq9+OKLhjpfrJ0ddv7aa6/JrrvuXr32l750YnbZZdeq2ZNP/lIOP/xdVbOHHnpwjjnmuKrZJNl7772y1157V80ed9wxefnL96ua/fjHP5p9992/ajZJjj76I3nWs55TNXvKKV/ODjv8XfXaZ5757epZGMQ4zjeXLFmSVVZZpWo2SW677bY86EEPrpr99a9/NfT5yyMfuVnV7I9//MOhXmetPUdOeufJ87WbW2+9TdXs+eefm5e85KVVs0ly7LGfzBe/+JWq2ec+99m5+OLvV81uvvljq7uX9Nr3/Oe/qGr285//THX3kl77jjzy/VWzb3jDQdVfr2OP/WTVHAxq2PPFYZpb+xpt0nudds0116qavemmG4d6vbG2e0mvfbWv0/7ylzcNfa56n/vct2r2D3+4ORtv/LCq2SuuuHzo3u+++55VsyeeeHxe8YpXVs1+7GP/k7e//Z1Vs0nylrccVn2+uffee+UFL9ireu3Pfe64PPOZz66a/epXv5IDD3x91ewHPvDeoV8beMpTdqqaPf3006rXnURzehENAH9rjncEA4B5TTcBoB3NBID2dBMA2ut6N+u2dgEAAAAAAAAAgA6xEw3AmHX9ak0AmE26CQDtaCYAtKebANBe17tpJxoAAAAAAAAAACaenWgAxqzrV2sCwGzSTQBoRzMBoD3dBID2ut5NO9EAAAAAAAAAADDx7EQDMGZTU1PjPgQAmDd0EwDa0UwAaE83AaC9rnfTTjQAAAAAAAAAAEw8F9EAAAAAAAAAADDx3M4JYMymp6fHfQgAMG/oJgC0o5kA0J5uAkB7Xe+mnWgAAAAAAAAAAJh4dqIBGLOuX60JALNJNwGgHc0EgPZ0EwDa63o3l7kTTdM0X26aZuO5OhgAmM90EwDa000AaE83AaA93QRgGDPdzmnrJN9omuZNTdOsPBcHBDBppqen5+wXI6ebACOmm52imwAjNJfN1M05oZsAI6SZnaObACPU9W7OdBHNtUm2TfLYJD9rmubQpmkeMvrDAoB5STcBoD3dBID2dBMA2tNNAKqtNMP7p0spNybZu2maTZLsl+SbTdOsmuSaUso2Iz9CgI7zrw86RTcBRkw3O0U3AUZIMztHNwFGSDc7RzcBRqjr3ZzpIpoFd/5HKeWnSd6c5M1N0zwoiXsJAsBf000AaE83AaA93QSA9nQTgGozXUTzT/f0xlLKr5P8evYPB2DyTE0tGfchMHt0E2DEdLNTdBNghDSzc3QTYIR0s3N0E2CEut7NmS6i+WHTNBsu7Z2llF/M8vEAwHymmwDQnm4CQHu6CQDt6SYA1Wa6iOaUJJskuS532fqsbzq2PAMYWtfvGzhhdBNgxHSzU3QTYIQ0s3N0E2CEdLNzdBNghLrezZkuonlykrOSvKaUcs4cHA8AzGe6CQDt6SYAtKebANCebgJQbYVlvbOUcnOS/ZLsMzeHAzB5pqen5+wXo6WbAKOnm92hmwCjNZfN1M3R002A0dLMbtFNgNHqejdn2okmpZRFSRbNwbEAwLynmwDQnm4CQHu6CQDt6SYAtWa8iAaA0fKvDwCgPd0EgHY0EwDa000AaK/r3Vzm7ZwAAAAAAAAAAGASLJjjq4S6fUkSMEkWzNYHeuhDN5qz58arrrpy1o6bkdNMoCtmtT26yVLoJtAV8/JcM9HNeUY3ga6Yl93UzHlHN4Gu0M2W5vR2TgsW1H9+09PT1fPT09NZeeWVq2Zvv/32PPjBa1TNJsmvfvXLPP3pz6qa/frXT6mevXN+iy2eUDV70UXfzcYbP6xq9oorLs9DH7pR1WySXHXVlXnYwx5eNXv55T+rPu6kd+xPetKTq2bPO++c7LXX3lWzxx13TG644caq2SRZe+21cuaZZ1XN7rDDdtXrJsmSJUuqZ1dcccWce+75VbPbbLN1Fi++tHrthQsfnV/84uqq2Q033KB63XvS9S3PqDdM94Zt7iqrrFI1e9ttt2WttdauXvvGG2/IDjv8XdXsmWd+e6jmPvGJT6qaTZILLjhvqHYN+3eN9deve1665pqrh5qt/XtG0vu7xnbb7VA1e9ZZZ+bYYz9TNfuSl7woJ5305arZJNltt+fk1FO/VTW7885PzYUXfq967S23fHzOO++CqtknPemJWbTowqrZrbbasmpuVHSTpRlnN1daqe7U+o477shGG21cNXvllVdUP48mvefS7bffsWr2O985Y+gGDNPNNddcq2r2pptuzDrrrFs1myTXX3/dUOfJ2267ffXaZ5/9nWyzzbZVs+eee3bOP39R1ezWW2+V973vg1WzSfK61702n/3sF6pmX/jC5+WWW26tml199dXy/vd/qGo2SQ466IBcdNHFVbNbbLF5fvOb31av/cAHPqB69u40k2UZppsrrFC3ufnU1FT1a7RJ73Xarbbaump20aLzs+6661Wvfd1112azzR5TNfvDH/5gqON+xCM2rZpNkp/85LI85CEPrZr9+c+vqj5fTHrnjMP0fpjXBvbc8wVVs0ly/PGfy7vedWTV7MEHv2Gsrzd+/evfrJp7+tOflu985+zqdbffftt84AP/XTV74IGvqV53tukmSzPOn23Wvkab9F6nfcADHlg1+9vf/iaPfvTCqtlLL12czTffomo2SS6++KKh1q49x05659m1P9+86qorq883r7/+uixc+Liq2SRZvPiS6te2L7jgvOy++55VsyeeeHz1zyaT3s8n3/veD1TNvv71B1ave6dhen/yyV+rmt1ll2fki1/8StVskjz3uc+unp1tXe+m2zkBAAAAAAAAADDx5nQnGgD+1tTU1LgPAQDmDd0EgHY0EwDa000AaK/r3bQTDQAAAAAAAAAAE89ONABj1vX7BgLAbNJNAGhHMwGgPd0EgPa63k070QAAAAAAAAAAMPHsRAMwZl2/WhMAZpNuAkA7mgkA7ekmALTX9W7aiQYAAAAAAAAAgIlnJxqAMev61ZoAMJt0EwDa0UwAaE83AaC9rnfTTjQAAAAAAAAAAEw8O9EAjFnXr9YEgNmkmwDQjmYCQHu6CQDtdb2bdqIBAAAAAAAAAGDi2YkGYMympqbGfQgAMG/oJgC0o5kA0J5uAkB7Xe/mMi+iaZpmpSR7J/ljkhOSHJlkhyTfTXJwKeU3Iz9CAJgndBMA2tNNAGhPNwGgPd0EYBgz7URzdJLVk6ya5MAkFyR5fpJdk/xPkj1GenQAE6Dr9w2cMLoJMGK62Sm6CTBCmtk5ugkwQrrZOboJMEJd7+ZMF9E8vpSysGmaFZNcU0rZpv/2HzVNc8mIjw0A5hvdBID2dBMA2tNNAGhPNwGotsIM759qmuYRSR6f5H5N0zw0SZqmWSPJyiM+NgCYb3QTANrTTQBoTzcBoD3dBKDaTDvRvDnJaeldbPPCJF9rmuYHSbZK8i8jPjaAidD1Lc8mjG4CjJhudopuAoyQZnaObgKMkG52jm4CjFDXu7nMi2hKKacm2fDO3zdNc36S7ZL831LKZSM+NgCYV3QTANrTTQBoTzcBoD3dBGAYy7yIpmmaDe/hzYvufF8p5RcjOSqACdL1qzUniW4CjJ5udoduAoyWZnaLbgKMlm52i24CjFbXuznT7ZxOSbJJkuuSLLjb+6aTbDyKgwKAeUo3AaA93QSA9nQTANrTTQCqzXQRzZOTnJXkNaWUc+bgeAAmTtev1pwwugkwYrrZKboJMEKa2Tm6CTBCutk5ugkwQl3v5grLemcp5eYk+yXZZ24OBwDmL90EgPZ0EwDa000AaE83ARjGTDvRpJSyKP37BAIw++o/lDQAABRESURBVKampsZ9CMwi3QQYLd3sFt0EGB3N7B7dBBgd3ewe3QQYna53c5k70QAAAAAAAAAAwCSYcScaAEar6/cNBIDZpJsA0I5mAkB7ugkA7XW9m3aiAQAAAAAAAABg4i2Y46uEun1JEjBJFszWB7rf/e4/Z8+Nv//972btuBk5zQS6Ylbbo5sshW4CXTEvzzUT3ZxndBPoinnZTc2cd3QT6ArdbGlOb+e0YEH95zc9PZ0VVqjbOGdqaiorrrhi1eySJUuyxhprVs0myS9/eVMWLnxc1ezixZdkq622rl570aLzs8suu1bNnnzyl/L4x29ZNfu971049J/ZZps9pmr2hz/8QQ4++NDqtd/1rsNzzDHHVc3uvfdeueiii6tmt9hi86q5u7r++huq5tZZZ+2ccMJJVbN77LFbPvSho6pmk+SAA16VZz7z2VWzX/3qV6pn75w/+uhPVM3uu+/LqteFQdR2c3p6OiutVJ/4O+64Y6hurrXW2tVr33jjDXnEIzatmv3JTy7L9tvvWDX7ne+cUd29pNe+LbZ4QtXsRRd9NxtttHH12ldeeUU22aSpmv3pT0v+8R//uWr2He/4j3zhC/9bNZskz3veP+TWW2+tml1ttdWq102SW26pWzdJVl99tXzkI0dXze6//7458sj3V6/9hjcclGc96zlVs6ec8uU87Wl/XzX7zW9+I+9+93urZpPkTW96ffUsDGKc3Vx11VWrZv/0pz9lzTXXqpq96aYbs912O1TNJslZZ52ZbbbZtmr23HPPzk477Vy99mmnnZrHPrbuHOj737846667XtXsddddW93rpNfsQw/9p6rZww//zxxxxHuq1z7kkDdWzw7rmmuurZ5df/318rGPfbJq9hWveGle97q6z/t973tPdt1196rZJPnSl07MU56yU9Xs6aeflle/+rXVa3/4wx+snoVBDNPNYc4Xh/m7/K233ppVVlmlava2227Lpps+qnrtyy77UZrmkVWzpfx4qNdZhz1fXG+99atmr732mqy//gbVa19zzdXZeuttqmbPP//cHHXUR6tmX/Wq/armlgfHHvuZ6tmXvORF+dSnPl01u88+L86LX7xP9dqf/vSnhnqN9/DD31U1e+ihB1fNwaCG/dlm7fnmHXfcMfS56v3v/4Cq2d/97rfVDbjmmquHfp219nzztNNOzcMe9vDqtS+//GfV85df/rPstdfeVbPHHXdMnvSkJ1fNJsl5552TQw45rGr2iCPeOVRzr776mqrZJNlgg/Vz4YXfq5rdcsvH57DD3lK99jvf+fa88Y2HVM2+5z1HDPVziNpzzaR3vvna176uavaDH3xf9bqTaE4vogHgb3X9voEAMJt0EwDa0UwAaE83AaC9rnezbmsXAAAAAAAAAADoEDvRAIxZ16/WBIDZpJsA0I5mAkB7ugkA7XW9m3aiAQAAAAAAAABg4rmIBgAAAAAAAACAied2TgBjNjW1ZNyHAADzhm4CQDuaCQDt6SYAtNf1btqJBgAAAAAAAACAiWcnGoAxm56eHvchAMC8oZsA0I5mAkB7ugkA7XW9m3aiAQAAAAAAAABg4tmJBmDMun61JgDMJt0EgHY0EwDa000AaK/r3bQTDQAAAAAAAAAAE89ONABj1vWrNQFgNukmALSjmQDQ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\n",
199 | "text/plain": [
200 | ""
201 | ]
202 | },
203 | "metadata": {
204 | "needs_background": "light"
205 | },
206 | "output_type": "display_data"
207 | },
208 | {
209 | "data": {
210 | "text/plain": [
211 | ""
212 | ]
213 | },
214 | "metadata": {},
215 | "output_type": "display_data"
216 | },
217 | {
218 | "data": {
219 | "text/plain": [
220 | ""
221 | ]
222 | },
223 | "metadata": {},
224 | "output_type": "display_data"
225 | },
226 | {
227 | "data": {
228 | "text/plain": [
229 | ""
230 | ]
231 | },
232 | "metadata": {},
233 | "output_type": "display_data"
234 | },
235 | {
236 | "data": {
237 | "text/plain": [
238 | ""
239 | ]
240 | },
241 | "metadata": {},
242 | "output_type": "display_data"
243 | },
244 | {
245 | "data": {
246 | "text/plain": [
247 | ""
248 | ]
249 | },
250 | "metadata": {},
251 | "output_type": "display_data"
252 | }
253 | ],
254 | "source": [
255 | "# different windows sizes for sentiment score b\n",
256 | "#h = 24\n",
257 | "s_days = 20 # short\n",
258 | "l_days = 20 # long\n",
259 | "\n",
260 | "f, axes = plt.subplots(1, 5, figsize=(40,10))\n",
261 | "win_all_a = np.zeros(shape=(s_days,l_days))\n",
262 | "# matrix of size (s_days,l_days)\n",
263 | "for std in range(0,5):\n",
264 | " for i in range(0, s_days):\n",
265 | " for j in range(0, l_days):\n",
266 | " sent_score_a = ah.nb_calc_sentiment_score_a(aug_signal_a,aug_signal_b,(i+1)*24+np.random.normal(0,std),(j+1)*24+np.random.normal(0,std))\n",
267 | " win_all_a[i,j] = ah.nb_backtest_a(price_data, sent_score_a, 1.0, 0.0075)[-1]\n",
268 | " cmap = sns.cubehelix_palette(50, hue=0.05, rot=0, light=0.0, dark=1.2, as_cmap=True)\n",
269 | " figure(num=None, figsize=(10, 7), dpi=80, facecolor='w', edgecolor='k')\n",
270 | " ax = sns.heatmap(win_all_a, linewidth=0.01, cmap=cmap,ax=axes[std])\n",
271 | "plt.show()\n"
272 | ]
273 | },
274 | {
275 | "cell_type": "code",
276 | "execution_count": 13,
277 | "metadata": {},
278 | "outputs": [
279 | {
280 | "data": {
281 | "image/png": "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AAAAAAAAAMBK9OUkh5dS9ly4fEqSq5cqmpmbmxtoV5sY6mAAAzSzjLc1zMfG5eybwZKZwKRY7uyRmyxGbgKTYlznmoncHCdyE5gU45qbMnO8yE1gUkxNbpZS7khyYq31jlLKq5P8UZKtk3wjyVtrrY9udsBhLqKZmZlpHmxubi6rV69uql2/fn1WrWrbdGd2djZbbNF+1qsnn3wyW221VVPt448/nh13/InmsX/wg+9np512bqp94IH7s+eez2mqveuub+eII45sqk2Sq666Mscdd0JT7cUXX9jcdzLf+8knv7yp9txzv5xDDnlhU+11132juXZD/bHHvqSp9rLLLsnrX//GptpPf/oTOemkk5tqk+T888/NG97w8021n/rU3zf3ncz3XsqBTbW13phMUdAwMnMzM20/rj6ZmUxnbvbJzGQ6c7NPZiajy80+mZlMZ272ycwkqfVGi2gYhrHNzT7z3K233rqpNkkee+yxXrn5zGfu1Dz29773QHbddbem2nvvXZsDDnh+U+1NN30rL3nJ8U21SXLJJRdln332baq97bZbc/jhL24e++qrv5aDDz60qfb666/tVXvooYc11SbJtddek9e85nVNtWeddWZ+6qdOaar94hc/nze+8U1NtUnyiU/8bX7u536hqfaTn/y77L//Ac1j33zzTeM610zk5jjplZt9cq+1dkN9n9xsnWsm8/PN7bbbvqn24Ycfym677d5Uu3btPTnwwIOaapPkxhtvyItedERT7de/flX22680j33LLTW77PLsptr77vtOjj/+xKbaiy66IIcddnhTbZJcc83VOfLIo5tqr7zyirz0pS9rqj3vvK/kF3/xl5tqk+TjH/9or777jn3KKT/TVPv5z/9Dr9e14zVahqDve5t9crM1r5dj7C233LKp9oknnuiduWvW7NhUu27dD7LDDmuax37wwXXNr9NeddWVvfK+NTOT+dxszexbbqnN85ebb76p9/OUPtnV97XpPq8t9Hk9/phjfrKpNkkuv/zSXvP7yM3OnM4JAAAAAAAAAICpZxENAAAAAAAAAABTzyIaAAAAAAAAAACmnkU0AAAAAAAAAABMPYtoAAAAAAAAAACYehbRAAAAAAAAAAAw9SyiAQAAAAAAAABg6llEAwAAAAAAAADA1LOIBgAAAAAAAACAqbfFUl9QStkvySO11rWllFOT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V1xxWV73utc31Z555qdzzDE/2VR7+eWX5mUve0VTbZJ85Stfyqte9dNNtV/4wj/msMMObx77mmuuzoEHHtRUe+ONNzSPC09Hn9zrm7nTlpt9MjOZztzsk5nJ6HKzT2Ym05mbfTIzkZsMT5/cXLWqfZPW2dnZ7LDDmqbaBx9cl513flZT7f33fzc77bRzU22SPPDA/TnooIObam+44focccSRzWNfddWVeclLjm+qveSSi3LSSSc31Z5//rnZd9/nNdUmya23/lOOP/7EptqLLrogL3rREc1jf/3rV+XlL39lU+2Xv3xOTjzxpKbaCy44P6997b9pqk2Sz33uMzn88Bc31V599ddywgn/uqn2wgv/V4488uim2iS58sor8oIXHNJU+81vXpcDDnh+89g33fSt5lp4Okb1OuvWW2/dVJskjz32WHbZ5dlNtffd953muWYyP9/s87jQp/b1r39jU22SfPrTn+j1WNr38extb3tHU+2HP/zXveZ8v/mbv91UmyR/+qf/V97ylrc11Z5xxofzmte8rqn2rLPObM7rZD6zW39XPv3pT+RXfuXU5rH/5m8+1Ot3fM89n9NUe9dd326qg6er7+usrfPN2dnZbLXVVs1jP/74481zxgceuD+7775HU+0999zdXLuhvpQDm2prvbF3dh188KFNtddff2322mvvpto77ri99+vDfXKzzxz7kENe2FSbJNdd941eP+vW2g31fZ4jvfrVr2mqPfvss7LffqWpNkluuaVm1113a6q99961zeNOo6EuogHgxw15RzAAGGtyEwC6kZkA0J3cBIDuJj032//dDgAAAAAAAAAAJoSdaABGbNJXawLAcpKbANCNzASA7uQmAHQ36blpJxoAAAAAAAAAAKaenWgARmzSV2sCwHKSmwDQjcwEgO7kJgB0N+m5aScaAAAAAAAAAACmnp1oAEZsdnZ21C0AwNiQmwDQjcwEgO7kJgB0N+m5aScaAAAAAAAAAACmnp1oAEZs0s8bCADLSW4CQDcyEwC6k5sA0N2k56adaAAAAAAAAAAAmHpL7kRTSnlFkq/WWteVUt6c5MgkV9da/2bg3QFMgUlfrTlNZCbA4MnNySE3AQZLZk4WuQkwWHJzsshNgMGa9Nzc7E40pZTTk7w3ydallPcn+d+T3JDkdaWUPxtCfwAwFmQmAHQnNwGgO7kJAN3J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aCYAdKebANDd2Lu5asLv4Lg/msAsWbVUb+gd77huYl8br7rqB5ds3QxOM4GxWNL26CaPQjeBsViR55qJbq4wugmMxYrspmauOLoJjIVudjTRnWhWrWp//+bn57NmzZqm2f379+fkk9c3zT7wwM6cf/4FTbNJctddd2bDhtObZrdt25oTTzyp+di7d+/KCSec0DT74IMP5pRTHtc0u2PHt3LOOec2zSbJvffek0suubRp9qtfvTlnnXV287E3b96USy+9vGn25ptvyrnnntc0e889dzd/vJOFj/mpp57WNHv//dubP892796VtWvXNs0myd69e5vn9+7dm9NO29B87O3bt/X6+1pKc3NzS/r2GI/WbvZpZjKb3ezTzGQ2u9mnmcn0utmnmclsdrNPMxPdZHKm2c2TTjq5aXbXrgeau9mnmclCN/ucL06zmxde+MSm2dtv/3rOSTNhHwAAIABJREFUOOPxTbNJsmXLN7N+/SlNszt37sjFFz+p+di33npLr2b3OV9sfZ+Thfe7TzePP/74ptl9+/b1/hzt081Sntx87Fq/1jx7OM3kaPp089hj255Sfvjhh5vPNZOF880+DejbzT7fi69bt65pds+ePb3X3ee8q++50+mnn9E0u3XrlmzceGHT7B133J4zzzyraTZJ7rtvc6/nRPr0o2+7+nxv1/fnEH3e7+/8zsuaZv/8z7/SNPdodJNH0/dnm8ccc0zT7COPPNLcj6RfQ7Zt2zqVnzkl/X+22fe5tz5fz/q0q+/3SK3tu+++zb3e576fo32+R2o9X0wWzhmPO+64ptmHHnqo1/eF0/y7Xkpj7+bqaS8AAAAAAAAAAACmbaI70QDw7cZ+30AAWEq6CQDdaCYAdKebANDd2LtpJxoAAAAAAAAAAGaenWgApmzsV2sCwFLSTQDoRjMBoDvdBIDuxt5NO9EAAAAAAAAAADDz7EQDMGVjv1oTAJaSbgJAN5oJAN3pJgB0N/Zu2okGAAAAAAAAAICZZycagCkb+9WaALCUdBMAutFMAOhONwGgu7F30040AAAAAAAAAADMPBfRAAAAAAAAAAAw89zOCWDK5ubmpr0EAFgxdBMAutFMAOhONwGgu7F30040AAAAAAAAAADMvEV3oimlfF+SlyU5J8lcks1JPlJrfd/AawOYCfPz89NeAktINwGGpZvjopsAw9HM8dFN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\n",
282 | "text/plain": [
283 | ""
284 | ]
285 | },
286 | "metadata": {
287 | "needs_background": "light"
288 | },
289 | "output_type": "display_data"
290 | },
291 | {
292 | "data": {
293 | "text/plain": [
294 | ""
295 | ]
296 | },
297 | "metadata": {},
298 | "output_type": "display_data"
299 | },
300 | {
301 | "data": {
302 | "text/plain": [
303 | ""
304 | ]
305 | },
306 | "metadata": {},
307 | "output_type": "display_data"
308 | },
309 | {
310 | "data": {
311 | "text/plain": [
312 | ""
313 | ]
314 | },
315 | "metadata": {},
316 | "output_type": "display_data"
317 | },
318 | {
319 | "data": {
320 | "text/plain": [
321 | ""
322 | ]
323 | },
324 | "metadata": {},
325 | "output_type": "display_data"
326 | },
327 | {
328 | "data": {
329 | "text/plain": [
330 | ""
331 | ]
332 | },
333 | "metadata": {},
334 | "output_type": "display_data"
335 | }
336 | ],
337 | "source": [
338 | "# different windows sizes for sentiment score b\n",
339 | "#h = 24\n",
340 | "s_days = 20 # short\n",
341 | "l_days = 20 # long\n",
342 | "\n",
343 | "f, axes = plt.subplots(1, 5, figsize=(40,10))\n",
344 | "win_all_a = np.zeros(shape=(s_days,l_days))\n",
345 | "# matrix of size (s_days,l_days)\n",
346 | "for std in range(0,5):\n",
347 | " for i in range(0, s_days):\n",
348 | " for j in range(0, l_days):\n",
349 | " sent_score_a = ah.nb_calc_sentiment_score_a(aug_signal_a,aug_signal_b,(i+1)*24+np.random.uniform(0,std),(j+1)*24+np.random.uniform(0,std))\n",
350 | " win_all_a[i,j] = ah.nb_backtest_a(price_data, sent_score_a, 1.0, 0.0075)[-1]\n",
351 | " cmap = sns.cubehelix_palette(50, hue=0.05, rot=0, light=0.0, dark=1.2, as_cmap=True)\n",
352 | " figure(num=None, figsize=(10, 7), dpi=80, facecolor='w', edgecolor='k')\n",
353 | " ax = sns.heatmap(win_all_a, linewidth=0.01, cmap=cmap,ax=axes[std])\n",
354 | "plt.show()\n"
355 | ]
356 | },
357 | {
358 | "cell_type": "code",
359 | "execution_count": 14,
360 | "metadata": {},
361 | "outputs": [
362 | {
363 | "data": {
364 | "image/png": "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3nhjjfLThAEAgFopPT1dS5YsOeNjkyZN0uTJk2scKzc3V/fff7+aNWumadOm1ejP0IQBAICAZ2ISdtttt2nAgAFnfCwqKqrGcTZt2qRJkyYpISFBycnJCgqq2dleNGEAAKBWio6O/sWS49naunWrxowZozlz5uimm246qz9LEwYAAAJeoO6otXjxYnk8Hi1btkzLli2run/FihVe/6zXJmz//v264AKzX0EGAACojsfj8XcJVX5+rtizzz57znG8LloOHjxYL7744jknAAAAwC95bcJiY2P18ccfa8yYMdqzZ48vagIAADhNIOwTZjevTVhYWJhefPFF9e7dW6NGjVJycrK+/PJLnThxwhf1AQAAOFKNvkMZFBSksWPHas2aNerSpYv+9re/6fLLL1f//v0NlwcAAODMSZjXE/N/XmSjRo00duxYjR07VseOHVNmZqbJ2gAAACQF7rcjz4fXSdjo0aPPeH9YWJguueQS2wsCAACoDbxOwkaOHOmLOgAAAH5VrZyEAQAAwH7smA8AAAJeIG3WaheaMAAAEPBYjgQAAIAtmIQBAICA58BBmFyWE+d7AADAUT744CPbY1533bW2xzwbfpmEuVwuo/Ety/JJjiZNwo3FLyoqVGhoqLH4klRSUqIWLVoazZGdfdAnz6Np02ZGcxQUHDGao6DgiBo0aGAsviSVlpYqNraV0RxZWQeMHhfSyWOjceMmRnMUFxepTZu2xuL/9FOmT469mJjmRnPk5Bzyyfvti98hJnOUlJSoUaPGxuJL0tGjxT75HeJPTpwZsRwJAAACnhObME7MBwAA8AMmYQAAIOA5cZ8wJmEAAAB+wCQMAAAEPCeeE0YTBgAAAp4Tm7CzWo4sKyvT1q1bVVJSYqoeAACAWqHaSdju3bv16KOPqkGDBpo6daruvfdeud1uud1uPfvss+rWrZuv6gQAALVYrZuEPfrooxo8eLAuv/xy3XXXXZo6darWrl2rRYsW6fHHH/dVjQAAAI5T7STs2LFjuuOOOyRJr732moYMGSJJuuKKK/y+cy4AAKg9nDgJq7YJc7vd2rNnj4qKinT48GH99NNPatOmjXJycnTixAlf1QgAAGo5J+4TVm0Tdv/992vYsGEKCgrSY489pqSkJHXr1k0bNmzQxIkTfVUjAACA41TbhA0cOFDffPON3G63QkND1blzZ61du1a3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wOu1I/3piy++0F//+leVl5erRYsWWrBggaKjo43keuqpp5SXl6e5c+faGve1117T//7v/8rlcqlBgwaaMWOG4uPjbc0hSW+++aZefPFFSVLTpk01e/ZstWvXzvY8mzZt0ujRo7VmzRo1b97c1tjTp0/X119/rUaNGkmS2rRpo0WLFtma48cff9ScOXN09OhRBQUFadasWerevbtt8d944w298sorVT8fP35cBw4c0OrVq9WmTRtbcqxZs0ZPP/20goKCFBYWpjlz5qhDhw62xD7ltdde00svvaSQkBC1bNlSjz76qG3v938faytWrNCyZctUWVmpzp0767HHHlNYWJitOSTJ4/Fo+vTpatOmje67777zin+mHEuWLNF7772noKAgRURE6JFHHjnvY/C/cyxbtkz//ve/5XK51Lp1a6WmpioyMtLWHKd8+OGH+p//+R9t2bLF1vh33XWXcnJyVL9+fUnSFVdcoZkzZ9qaY/369Vq4cKHKysrUsGFDzZs3z9b3YsmSJfrwww+rHissLFRBQYHWrVun0NBQ257Hv/71L7300ksKDg5W8+bNNXfu3PP+O/DnOSzL0pIlS/TOO++obt266tSpk1JSUtS4cePzyoGzYAWow4cPW1deeaW1Y8cOy7IsKy0tzRozZoztefbv32/dd999Vnx8vPXnP//Z1tgbNmyw+vfvbx0+fNiyLMv6+OOPrd69e1sej8fWPLt377auuuoqKz8/37Isy3rppZesO+64w9YclmVZ+fn5VkJCgnXRRRdZ2dnZtscfNGiQtXPnTtvjnlJaWmr16dPHWr16tWVZlvXJJ59Y/fv3t/39OKWystK64447rH/+85+2xSwtLbW6du1q/fjjj5ZlnXyvR48ebVt8y7KsdevWWb1797aysrIsy7Kst99+2xo5cuR5xz3TsbZr1y7rqquusg4dOmRZlmXNnz/fSklJsTWHZVnW9u3brcTERCs+Pt76+9//bvvzWLlypTV8+HDr+PHjlmVZ1ssvv2zdcssttub44osvrBtuuKEqx7x586yHHnrI1hynZGRkWAMGDLA6d+5sa/wTJ05Yl156qVVUVHTOcb3lOHTokHXFFVdY33//vWVZlvXKK69YiYmJtub4uaNHj1o33nij9e6779qaY9++fdZll11m5eXlWZZ18tiYNm2arTneeust66abbrIKCwsty7KsJUuWWFOmTDnnHDh7AbscuXbtWsXFxSkuLk6SdPvtt+vrr79WXl6erXnS09N19dVXKykpyda4ktSkSROlpqaqWbNmkqT4+HgdPnxYpaWltuZp3769PvvsM0VERKiyslIHDx5U06ZNbc1RWVmp5ORkTZ061da4p+Tn5+vgwYNatGiRbr75Zk2ePFlZWVm25li7dq2ioqJ03XXXSZL69eunZ555Rpahy6e++OKLCg4O1pgxY2yL6Xa75XK5VFRUJEkqKSmpmijYZcuWLbryyivVsmVLSdJ1112nTZs2nff7caZjbc2aNerXr59iYmIkSaNHj9aqVavk8XhsyyFJL7/8skaNGqUbbrjh3J9ANTnatGmjmTNnVk1B4uPjz+v1OlOOPn36aMWKFQoNDVV5ebny8vLO6zj/tdfq2LFjmjp1qmbMmHHOsX8t/rZt21S3bl396U9/0s0336zp06eroKDA1hzvv/++evXqpW7dukmSRo4cqdmzZ9ua4+eeeOIJdevW7bw+W2fK4fF45Ha7VVJSIsuyzvtYP1OOH374Qddcc42aNGki6eSx/uGHH+rEiRPnnAdnJ2CbsEOHDqlFixZVP9etW1dNmzZVdna2rXkefPBBjR49WsHBwbbGlaQOHTqoT58+kk4eUPPmzVP//v3Pa1z9a0JCQrR+/Xr169dP6enptjeVCxcuVM+ePdW7d29b456Sm5urPn36aPr06Vq5cqXi4+M1YcIEud1u23Ls3btX0dHRmjlzpoYPH667775bJ06cUFCQ/YdBcXGxli5dqpkzZ8rlctkWt2HDhpo9e7buvvtu9e3bV88//7ztjXF8fLy++eYb7d+/X5L073//W9LJ9+h8nOlYy87OPu04b968uUpKSlRYWGhbDkmaO3euhgwZcm6F1yBHfHy8Lr30UklSeXm5/vKXv+jGG2+0NYd08jh/55131LdvX3377be67bbbbM8xffp03X333brooovOOfavxS8qKlKvXr20YMECvf322woNDT2vz++Zcuzdu1cNGzZUcnKyhg0bpsmTJ5/X7/fq/o7IzMzUqlWr9Kc//emc4/9ajjZt2mjChAm68cYb1adPH61du/a8ltF/7XP76aef6siRI7IsSytXrlRFRcU5H384ewHbhFmWdca/vEz8hWnasWPHNGnSJGVlZWnBggXG8vTo0UNffvmlFi5cqPHjx6u4uNiWuO+884727dunP/7xj7bEO5OLL75Yzz77rGJjY+VyuXTvvfcqKytLmZmZtuWorKzUl19+qaFDh+qtt97S2LFjNX78eB07dsy2HKe8/vrruvrqq3XhhRfaGnfnzp1atGiRVq5cqc8//1wzZ87UuHHjVFJSYluOK664Qg888IDuv/9+jRgxQiUlJQoPD1dISIhtOX7uTMe5nY2rL+Xm5uruu+9Wo0aNNG3aNCM5hgwZoq+//lrjx4/X2LFjz3lqeCZLly5VZGSkEhISbIv5c3379tVTTz2lpk2bqk6dOpo0aZLWrl1r6+e3srJSn3zyiSZOnKi3335b11xzjSZMmGBb/J9LS0vTrbfeWrXaYae1a9fqnXfe0UcffaS1a9fq9ttv14QJE2yd3A8dOlRDhgzR3Xffrdtvv73qvE9Txzp+KWA7mpYtWyonJ6fq5xMnTqigoKBqieS3Yu/evbrlllsUFhamtLQ0Iyc8HjhwQP/5z3+qfh44cKBCQkK0b98+W+K/+eab2rdvn4YOHVr1y3ns2LFav369LfElaePGjXr//fdPu8+yLNWpY993R2JiYtS2bVv16NFD0snlyDp16mjPnj225Tjl3Xff1YgRI2yPu3btWnXt2lXt27eXJN18881yu93avXu3bTmOHz+uHj166O2339abb76pESNG6OjRo2rdurVtOU757+M8JydHDRs2rFoe+S3ZtGmTRowYoR49emjJkiWqW7eurfF//PFHbdq0qernkSNH6sCBA1VL03Z4++23tX79eiUkJGj8+PFyu91KSEiw7XfJZ599pi+//LLqZ8uyFBQUZPtx3r1796ovqwwfPlyZmZk6cuSIbTmkk6sb7733npHjXJI+/vhj9e3bVzExMXK5XLrrrru0bdu281q+/W+FhYW66aabtGrVKqWnp6tbt24KDw9XeHi4bTlQvYBtwnr37q1t27Zp165dkk5+66xbt25G/sVhysGDBzV69GiNHDlSCxcuVL169YzkKSoq0pQpU3To0CFJJ3/RBQUF2faNuRdeeEHvvvuuVqxYoRUrVkiSli9fXtXM2OHEiRNKTU2tWvJ6+eWX1aFDB1v/4u/bt6+ys7P1/fffS5I2bNigEydOVDU0djl69Kh27dqlK664wta4ktSlSxdt2LCh6r3+9ttvVVlZaes3YXNzczV69Oiqv9z/8Y9/aMCAAUb+AXHttdfqs88+q2rEXn31VQ0cOPA3N/HeunWrxowZo4cfflh/+tOfjNSfmZmpqVOn6ujRo5Kkt956S3Fxcbae//n+++9r1apVVd9YDQ4O1ooVK2w7Do8cOaJ58+ZVTZ+XLVumgQMH2tqwDho0SBs3bqyaon/wwQdq3bq17Y3Frl27VLduXdt/f5zSpUsXffHFF1Xv96lvWNv5d+C2bdv0hz/8QSdOnJDb7dbSpUs1dOjQ3+wk+rcoYLeoaNasmZ588kk99NBDKi8vV0REhBYuXOjvss7K8uXLVVxcrJUrV2rlypVV9y9btqzqRGQ7dOnSRQ899JDGjRunoKAgNW7cWM8995waNGhgWw7Tevbsqfvuu09JSUlyu91q2bKlnn76aVt/GURGRmrp0qWaN2+eSkpKFBwcrMWLF5/3dgj/LTMzU82aNbP9hHlJ6tWrlyZOnKikpCSFhIQoNDRUzzzzjK3PoV27dpo8ebJGjRolt9utiy++WPPmzbMt/s917NhR06ZN07333quKigq1a9dOjz/+uJFcJi1evFgej0fLli3TsmXLqu4/9Y8WOwwaNEh79+7Vbbfdpjp16qhFixb6+9//blt8Xxg2bJj27dunkSNHyuPxKC4uTnPmzLE1R6dOnTR37lw98MADqqysVFhYmBYvXmx7Y5yZmanY2FhbY/7c8OHDlZ2drVtuuUX16tVTs2bN9Mwzz9ia4+qrr9bgwYM1dOhQVVRUqE+fPnrwwQdtzYHquSxTXw0DAADAr/ptzfwBAAAcgiYMAADAD2jCAAAA/IAmDAAAwA9owgAAAPyAJgwAAMAPaMIAAAD8gCYMAADAD2jCAAAA/OD/As7goqgI680lAAAAAElFTkSuQmCC\n",
365 | "text/plain": [
366 | ""
367 | ]
368 | },
369 | "metadata": {},
370 | "output_type": "display_data"
371 | }
372 | ],
373 | "source": [
374 | "cmap = sns.cubehelix_palette(50, hue=0.05, rot=0, light=0.0, dark=1.2, as_cmap=True)\n",
375 | "figure(num=None, figsize=(10, 7), dpi=80, facecolor='w', edgecolor='k')\n",
376 | "ax = sns.heatmap(win_all_a, linewidth=0.01, cmap=cmap)\n",
377 | "plt.show()"
378 | ]
379 | },
380 | {
381 | "cell_type": "code",
382 | "execution_count": 15,
383 | "metadata": {},
384 | "outputs": [],
385 | "source": [
386 | "# different windows sizes for sentiment score b\n",
387 | "#h = 24\n",
388 | "s_days = 20 # short\n",
389 | "l_days = 20 # long\n",
390 | "\n",
391 | "win_all_b = np.zeros(shape=(s_days,l_days))\n",
392 | "\n",
393 | "# matrix of size (s_days,l_days)\n",
394 | "\n",
395 | "for i in range(0, s_days):\n",
396 | " for j in range(0, l_days):\n",
397 | " sent_score_a = ah.nb_calc_sentiment_score_a(aug_signal_a,aug_signal_b,(i+1)*24+np.random.normal(0,1),(j+1)*24+np.random.normal(0,1))\n",
398 | " win_all_b[i,j] = ah.nb_backtest_a(price_data, sent_score_a, 1.0, 0.0075)[-1]\n"
399 | ]
400 | },
401 | {
402 | "cell_type": "code",
403 | "execution_count": 16,
404 | "metadata": {},
405 | "outputs": [
406 | {
407 | "data": {
408 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAmsAAAHLCAYAAACXuN+XAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAMTQAADE0B0s6tTgAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAgAElEQVR4nOzde3zP9f//8ft7B4c524nNWU7JJEQISaXwGUrYdJhTPqL2WR/6+DCphfh8O6FCKdNx9SuhE+lIZ5IIsViY2cFhDmNse/3+8LFPy9p78Xq+91rv2/Vy2eXi/X7P4/F4bXvPw+P5ej1fLsuyLAEAAMCRfMq6AAAAAPwxmjUAAAAHo1kDAABwMJo1AAAAB6NZAwAAcDCaNQAAAAejWQMAAHAwv7JI6nK5jMa3LKvc5/grHAM5nBOfHM7K8Vc4hnM5fHzM/p+/oKCg3H+t/krfb5QNJmsAAAAORrMGAADgYDRrAAAADkazBgAA4GA0awAAAA5GswYAAOBgpdq64+DBg0pLS5OPj4/q1q2rWrVqma4LAAAActOsZWVl6V//+pe+/vpr1a5dW5J0+PBhXX755ZozZ47q1q3rkSIBAAC8lcsqYZe7kSNHqmfPnho6dKj8/f0lSWfOnNHrr7+uVatWaenSpReW9C+yOSCbKJKjvMQnh7Ny/BWO4VwONsUt+/iezIGyUeK7LC0tTbfddlthoyZJ/v7+io6O1qFDh4wXBwAA4O1KbNYqVKig5OTk855PTk5WhQoVjBUFAACAs0o8Z+2+++5TdHS0WrVqVXh+Wnp6urZt26bHHnvMIwUCAAB4sxLPWZOkQ4cO6YsvvlBaWpokKSwsTF27dr2oK0L/Kmv3nONAjvISnxzOyvFXOIZzOThnrezjezIHyobbZs1I0r/IDy1vbnKUl/jkcFaOv8IxnMtBs1b28T2ZA2WDTXEBAAAcjGYNAADAwWjWAAAAHIxmDQAAwMFo1gAAABysTK4GBQAAQOmUuCmuKX+VS5hNXrJeUFAgX19fY/ElKT8/3yOX3Xsihye+Vn5+5t4ueXl5RuOfy/HbW8eZcObMGVWuXNlojpMnT6pGjZpGc2RnH1GtWrWNxT98+JACAgKMxZeknJwcValSxWiOEydOqFq16kZzHDt21CM/t9Wr1zAW/+jRbFWqVMlYfEk6deqUR3KgbLAMCgAA4GA0awAAAA5GswYAAOBgNGsAAAAORrMGAADgYDRrAAAADkazBgAA4GA0awAAAA5GswYAAOBgNGsAAAAO5vb+NvHx8SW+npCQYFsxAAAAKMptsxYYGKjExETFxMQYv8cjAAAAinLbrMXGxio5OVlBQUGKioryRE0AAAD4r1KNyiZPnqwDBw6YrgUAAAC/U6pmLTw8XHFxcaZrAQAAwO9wEhoAAICD0awBAAA4GM0aAACAg9GsAQAAOJjLsiyrrIsAAABA8dzus2aCy+UyGt+yLOMb+BYUFMjX19dY/Pz8fPn5mf325OXlqWLFikZz5ObmKjS0jtEc6ekH1LhxE6M5du/epWrVqhuLf+zYUdWsWctYfEk6cuSwGjZsZDTHr7+m6LLLIozm2LLlR8XEjDKa44UXnlNwcIix+JmZGQoLCzcWX5L270/VFVd0MJrj++/Xe+T77Ymf22bNWhiLv3Pnz3+Z7zfKBsugAAAADkazBgAA4GA0awAAAA5GswYAAOBgNGsAAAAORrMGAADgYDRrAAAADlaqZu3UqVPnPZeZmWl7MQAAACiqxGbtxx9/VLdu3dS+fXuNHz9ex48fL3xtzJgxxosDAADwdiU2azNnztTDDz+szz//XBUrVtTo0aN15swZSWfvEgAAAACzSmzWTp06pZ49eyowMFD/93//p1q1amnatGmeqg0AAMDrldis5efnKzs7W9LZ+3nOmTNHP/zwg1544QXj9/cEAACAm2YtKipKAwcO1JdffilJqlq1qp5++mk999xzSk5O9kiBAAAA3syvpBeHDRumli1bqnr16oXPNW7cWG+88Yaef/5548UBAAB4uxKbNUlq167dec+FhYVp6tSpRgoCAABwsieeeEKZmZmaMWOGJGn+/Pl6//335ePjo8DAQD3wwANq3LjxeX9v/vz5eu211xQYGChJqly5sl577TW3+dw2awAAAJD27dunWbNmad26derXr58kaeXKlfrkk0/0xhtvKCAgQC+99JImTZqkN95447y/v2HDBiUkJOiaa675U3m5gwEAAEApJCUlqUuXLoqJiSl8rmHDhpo6daoCAgIkSREREUpNTT3v7+bn5+uHH37QG2+8ocjISI0cOVLbt28vVV4mawAAwCtlZGT84R2ZgoODFRISUuS5++67T5I0b968wuciIiIK/5ybm6v//Oc/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JmsAAMBjCgoKbP8oL0ps1rKzs5WcnKxGjRrpwIEDhc9nZWUZv50TAADAOSyD/oFOnTrp7rvv1scff6wHH3xQkrRq1SoNGDBA0dHRHikQAADAm5W4dcesWbMkSQcPHlRGRoYkKTQ0VI899piuvNLsDcABAADOKU+TMLuVap+1wMBABQYGSpIuv/xyowUBAADgf9gUFwAAOJ4XD9Zo1gAAgPN58zIol3QCAAA4GJM1AADgeOVpXzS7MVkDAABwMJflzYvAAACgXNi+fYftMVu2bG57TBPKZBnU5XIZjW9ZlvE7LBQUFMjf399Y/DNnzqhevfrG4kvSvn17FR5ez2iO1NR96tDB7J5869d/q/btOxrNsWHDd7r22uuMxf/oow8VFzfRWHxJeuyx/6hbt+5Gc6xb97l6977eaI41a1Zr8OChRnO88cZruu66G4zF//DDVercuYux+JL09ddfGj0G6exxeOJnasSI0UZzPP/8s/rb3wYai79ixTJdcUUHY/El6fvv16tNm7ZGc2zevMlofHe8ebbEMigAAICD0awBAADHc9K9QZ944glNmTKl8PHy5cvVt29f3XDDDYqNjdXx48eL/Xt79+7Vbbfdpr59+6p///7auHFjqfLRrAEAAJTCvn37dPfdd+uFF14ofG7nzp2aPXu2nn/+ea1atUp16tTRnDlziv37cXFx6tevn959913NmjVLEyZMUE5Ojtu8NGsAAMDxnDBZS0pKUpcuXRQTE1P43Jo1a9SjRw+FhoZKkqKjo7Vy5crzthpJT0/X9u3bNWjQIEnSZZddpkaNGunTTz91m5d91gAAgOOZ2GctIyNDmZmZxb4WHByskJCQIs/dd999kqR58+YVPpeWlqa6desWPq5Tp45ycnJ05MgR1a5du8jnBQUFFbk4MTQ0VPv373dbJ80aAADwSklJSZo/f36xr40fP14TJkwoVZzidrn4/XOWZRX7eaXZveJPNWs5OTnatWuXmjRpooCAgD/zVwEAAC6Yia07hgwZol69ehX7WnBwcKlihIWFad++fYWP09PTVaVKFdWoUeO8z8vKylJeXp78/M62XxkZGerdu7fbHCU2a5s2bdI//vEPPfPMM8rNzdVdd90lX19fnTlzRk899ZQ6dDC7bwwAAIApISEh5y11/lnXXnutRowYofT0dIWGhurll19W7969z5uYhYaG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HvBUjQAAwMtZlmX7R3lRYrOWlpamyMhIVa5cWVFRUXr//fdVs2ZNTZkyRT/99JOnagQAAPBaJS6Dnj59Wunp6QoNDVVqaqry8/MlSUePHjV6X0wAAIDfKutJ2BtvvKGXXnqp8PGJEye0b98+rVq1Sg0bNix8/u2339asWbNUp87/7pv74osvqnr16hecu8Rm7bbbbtMtt9yiK6+8Ut99953uvfdepaSkKDo6Wvfcc88FJwUAAPgzyrpZGzx4sAYPHixJys/P15133qlhw4YVadQkaf369ZowYYKGDx9uW+4Sm7Vhw4apSZMm+umnnzRs2DB16NBBOTk5evnll9WoUSPbigAAAPC0jIwMZWZmFvtacHCwQkJCin1tyZIl8vX11YgRI857bcOGDUpLS9Nbb72lSpUqKTY2VldeeeVF1el2645OnTqpU6dOhY8DAgJo1AAAgEeZ2GctKSlJ8+fPL/a18ePHa8KECec9f/ToUS1cuFCvvPKKXC5XkddOnz6tsLAwjRw5Ul26dNF3332ncePG6a233lL9+vUvuE42xQUAAF5pyJAh6tWrV7GvBQcHF/v866+/ri5duuiSSy4577UKFSpo8eLFhY87duyo9u3ba+3atYqKirrgOmnWAACA45k4Zy0kJOQPlzr/yHvvvad//OMfxb6Wnp6ud999t8jyqGVZ8vf3v6g6uTcoAABwPCfss3bs2DHt2LFDHTt2LPb1gIAAPf300/rqq68kSZs3b9YPP/yga6655qKOnckaAABAKaSkpKh27dqqVKlS4XPp6ekaM2aMFi1apNDQUD311FOaM2eOcnNz5efnpyeeeEJBQUEXlZdmDQAAOF5Zb90hSW3atNHnn39e5LnQ0FAtX7688HGnTp305ptv2prXZTnh6AEAAErw7LPP2x5z9Ojzt95wojKZrP3+Ule7WZalihUrGs2Rm5trNEdubq7q1bvwy3xLY9++vapfv4HRHHv37lG1ahe+a3NpHDt21CPf7+DgP3cS6p+RmZnhke9F06bnX71kp19+SfbIcbRq1dpojm3bflJoaB33n3iB0tMPKCio+CvN7JKVlam6dcOM5khL22/06ySd/Vr9dsnJhFOnThn9PXXs2FGPfJ088d4rSya27igvWAYFAACO580LgVwNCgAA4GBM1gAAgON582SNZg0AADieNzdrLIMCAAA4GJM1AADgeEzWAAAA4EhM1gAAgOOxz1opHT58WD4+PqpRo4apegAAAM7jzcugbpu1nJwczZ49WytWrNDJkyclSVWrVlXv3r01ZcoUVatWzXiRAAAA3srtOWtTp05VQECAVq5cqS1btmjLli16++23Vbt2bf3rX//yRI0AAMDLWZZl+0d54bZZ27p1q+6//37Vq1dPfn5+8vPzU7169TRp0iTt3r3bEzUCAAB4LbfNmp+fn7Kyss57PiMjQ76+vkaKAgAA+C1vnqy5PWdt9OjRioyMVM+ePVW3bl1JZxu1zz77TJMmTTJeIAAAQHlqruzmtlmLjIzUpZdeqo8++khpaWmyLEvh4eFavHixLrnkEk/UCAAA4LVKtXVHs2bN1KxZM9O1AAAAFIt91koQHx9f4usJCQm2FQMAAICi3DZrgYGBSkxMVExMjHx8uDsVAADwPM5ZK0FsbKySk5MVFBSkqKgoT9QEAABQhDc3ay6rFEefmpqqpKQkxcXFeaImAACAIv7zn8dsjzlxYvnoa0p1gUF4eLitjZrL5bItVnEsy5K/v7/RHGfOnFGVKlWMxT9x4oRCQkKNxZekjIx0NW1q9oreX35JVlhYuNEc+/en6qqruhrN8dVXX+jGG/sZi//++++oTZu2xuJL0ubNm1S/fgOjOfbu3aPw8HpGc6Sm7jP63pPOvv8qVapkLP6pU6dUuXJlY/El6eTJk0aPQTp7HJ74XgQEBBjNkZOTo5o1axmLf+TIYQUHhxiLL0mZmRlq3ryl0Rw7dmw3Gt8db56scRIaAACAg5VqsgYAAFCWvHmyRrMGAAAcz5v3WWMZFAAAwMGYrAEAAMfz5mVQJmsAAAAOxmQNAAA4njdP1mjWAACA43lzs8YyKAAAgIMxWQMAAI7nzZM1t83aggULSnx97NixthUDAACAotw2a7t379bq1avVp08fT9QDAABwHm/eFNdts/bII48oNTVVV199tW666SZP1AQAAFCENy+Dur3AwOVyKT4+Xl9++aUn6gEAAMBvlOoCgxYtWujhhx82XQsAAECxmKwBAADAkdxO1uLj40t8PSEhwbZiAAAAiuPNkzW3zVpgYKASExMVExMjHx8GcQAAwPNo1koQGxur5ORkBQUFKSoqyhM1AQAA4L9cVila1dTUVCUlJSkuLs4TNQEAABQxZco022POmPGQ7TFNKNXVoOHh4bY2ai6Xy7ZYxbEsy/iSbUFBgSpWrGgsfm5urmrUqGksviRlZx9R9eo1jOY4ejRbNWvWMprjyJHDatSosdEcKSm7FRQUbCx+VlamgoNDjMWXpMzMDKPHIJ09Dk98vwMCAozmyMnJUeXKlY3FP3nypGrVqm0sviQdPnzI6DFIZ4+jSpUqRnOcOHHCI7+nTB7HiRMnPPL99sTvkLLkzcugnIQGAADgYNzIHQAAOB6TNQAAADgSkzUAAOB43jxZo1kDAACO583NGsugAAAADsZkDQAAOF5BQUFZl1BmmKwBAAA4GJM1AADgeJyzVoKUlI94YGoAACAASURBVBTdeuut6tatm2bNmqUzZ84UvjZw4ECjxQEAAEhnmzW7P8oLt83aQw89pMjISD399NPatm1bkdtOlacDBQAAKI/cNmsHDx5UdHS0IiIi9OyzzyorK0uPP/64J2oDAACQ5N2TNbfnrOXn5ys3N1cVK1ZUxYoV9eSTT+qWW25RixYtjN+QHQAAwNu5naz16dNHw4cP16ZNmyRJISEhmjdvnqZNm6Zff/3VeIEAAABM1kowfvx4NWrUSL6+voXPtW3bVomJiZo3b57R4gAAACTv3metVFt39OvX77znWrdurQULFtheEAAAAP7HbbMWHx9f4usJCQm2FQMAAFCc8rRsaTe3zVpgYKASExMVExMjHx9ueAAAAOBJbpu12NhYJScnKygoSFFRUZ6oCQAAoAhvnqy5rFIcfWpqqpKSkopsiAsAAOAp48ffa3vM+fOf/FOfP3nyZH3zzTeqVq2aJKlhw4aaO3dukc/Zu3ev/v3vf+vQoUPy8fHRQw89pHbt2l1UnaW6wCA8PNzWRs30/myWZXkkh8ll4YKCAvn5mb11a15enipWrGg0R25urqpXr2E0x9Gj2apbN8xojrS0/QoJCTUWPyMjXc2atTAWX5J27vxZDRs2Mprj119TFB5ez2iO1NR9atSosdEcKSm71bhxE2Pxd+/epeDgEGPxJSkzM0P16zcwmmPv3j0KCgo2miMrK1O1atU2muPw4UNq0qSpsfi7dv2ievXqG4svSfv27VXbthfXELizadNGo/HLgw0bNmjBggVq3rz5H35OXFycbrnlFg0ZMkRbtmzR2LFjtXr1agUEBFxwXk5CAwAAjlfW+6xlZWVp//79mjt3rvr3768JEyYoNTW1yOekp6dr+/btGjRokCTpsssuU6NGjfTpp59e1LGbHd0AAAA4VEZGhjIzM4t9LTg4WCEhIUU+t1u3bpo8ebLCwsL03HPPaezYsXr77bcL96JNS0tTUFCQ/P39C/9eaGio9u/ff1F10qwBAADHM7EpblJSkubPn1/sa+PHj9eECRMKH1966aVF9pcdNWqUnnnmGaWkpKhp07PL6H90GtbFnjZFswYAABzPxNWgQ4YMUa9evYp9LTi46PmYGzduVHp6uvr06VOkpt+eXx4WFqasrCzl5eUVPp+RkaHevXtfVJ00awAAwCuFhIQUWeosyenTp5WQkKArrrhCISEhevHFF9W0aVM1aPC/C3lCQ0PVsmVLLVu2TIMHD9bWrVu1c+dOdenS5aLqpFkDAACOV9b7rHXq1Enjxo1TTEyM8vPzFRYWpieffFIZGRkaM2aMFi1apNDQUD366KOKj4/X0qVLJUmPPfaYatS4uF0RaNYAAABKITo6WtHR0ec9v3z58sI/169fX0uWLLE1L80aAABwvLKerJWlC2rWsrOzL3qkBwAAUFomrgYtL9xeS3ro0CFNnjxZc+bM0Z49e9S7d2917txZAwYMOG8zOAAAANjLbbMWHx+vGjVqKD09XbfddpvuvPNO/fDDD7r11luVkJDgiRoBAICXK+s7GJQlt8uge/bs0VNPPaXc3Fx1795dw4cPlyRFRUXp9ddfN14gAACAN3PbrBUUFCg3N1cVK1bUtGnTCp8/fvy4zpw5Y7Q4AAAAybsvMHC7DBoZGambb75Z+fn56tu3ryTpxx9/1M0336yBAwcaLxAAAIBl0BKMGTNGrVu3LrxJqSQFBARo4sSJF337BAAAAJSsVFt3dO3atcjjSy65RJdccomRggAAAH6vPE3C7Oa2WYuPjy/xda4IBQAApnnzPmtum7XAwEAlJiYqJiZGPj5uT3EDAACAjdw2a7GxsUpOTlZQUJCioqI8URMAAEAR3rwM6rJKcfSpqalKSkpSXFycJ2oCAAAo4rbb7rQ95osvLrE9pgmlusAgPDzc1kbN5XLZFqs4lmUVuXrVhPz8fKM58vPzVb262fuvHj2arZCQUKM5MjLSVa9efaM59u3bq/DwekZzpKbuU8uWlxqLv337VjVp0tRYfEnatesXNW7cxGiO3bt3qU2btkZzbN68SU2bmr3A6Zdfko3+3O7bt1eBgUHG4kvSwYNZCgoKNpojKytTwcEhRnNkZmZ4JEfNmrWMxT9y5LBHftd64vdgWfLmydoF3cgdAADAk7y5WeOKAQAAAAdjsgYAAByPyRoAAAAcickaAABwPDbFBQAAcDCWQQEAAOBITNYAAIDjMVn7k/bu3Wt3HQAAACjGBTVr99xzj911AAAA/CHLsmz/KC/cLoNedtll5z2Xl5en1q1by+VyacuWLUYKAwAAOKc8NVd2cztZe/zxx1WnTh3Nnz9fq1at0gcffKCmTZtq9erVWrVqlSdqBAAA8FpuJ2vXXXedmjRpokmTJikmJkb9+vVThQoVFB4e7on6AAAA2GfNnaZNmyoxMVH//ve/tXHjRuXn55uuCwAAAPoTFxhUrVpVc+fOVUhIiM6cOWOyJgAAgCK8+QKDP3016F133aX333/fRC0AAADF8uZmze0yaHx8fImvJyQk2FYMAAAAinLbrAUGBioxMVExMTHy8eHuVAAAwPPK0yTMbm6btdjYWCUnJysoKEhRUVGeqAkAAAD/5bJK0aqmpqYqKSlJcXFxnqgJAACgiL/9baDtMVesWGZ7TBNKtXVHeHi4rY2ay+WyLVZxLMvySA5fX19j8fPz8+XnV6pvzwXLy8tTpUqVjOY4deqUatWqbTTH4cOHPJIjODjEWPzMzAwFBQUbiy9JWVmZRo9B8txxeCJH3bphxuKnpe1X+/YdjcWXpA0bvlPbtu2M5ti0aaPq129gNMfevXvUokUrozl+/nmbOnfuYiz+119/qS5duhmLL0lffrlOV1/dw2iOtWs/MxrfHW/eZ42T0AAAABzM7OgGAADABt58gQGTNQAAAAdjsgYAABzPmydrNGsAAMDxvLlZYxkUAADAwZisAQAAx2OyBgAAAEf605O1U6dOydfXV/7+/ibqAQAAOE9BQX5Zl1Bm3E7WZsyYIUk6cuSIRo8erXbt2qldu3aKjY3V0aNHjRcIAABgWZbtH+WF22Zt/fr1kqTZs2erYcOG+uqrr/T555+rTp06mjZtmvECAQAAvFmpl0G3bNmi5cuXy8fnbH/3r3/9S3369DFWGAAAwDnlaRJmN7fN2smTJ3X8+HGFh4fr+PHjql69uiTpxIkThY0bAACASd7crLnttkJCQtSjRw9t2rRJ06dPlyR9+eWXGjp0qG688UbT9QEAAHg1t5O1pUuXKi8vT1u3blV2drYkKS8vTyNHjtSAAQOMFwgAAODNk7VSnbPm5+eniIiIwsfdu3c3VhAAAAD+x22zFh8fX+LrCQkJthUDAABQnIKCgrIuocy4bdYCAwOVmJiomJgYLigAAABlgmXQEsTGxio5OVlBQUGKioryRE0AAAD4L5dVilY1NTVVSUlJiouL80RNAAAARXTv3tP2mJ9//qntMU0oVbNme1KXy2h8y7I8ksPk/VHPnDmjypUrG4svnd1DLzS0jtEc6ekHPJKjZs1aRnMcOXLYaI4jRw575OsUFBRsNEdWVqZHjqNp00uM5vjll2TVq1ffWPx9+/Z65Bj69Ys0muOdd5YrOvp2ozlefnmpevXqbTTHxx+vUd++fzMW/913V+j6681uIr969Qfq1Okqozm++eYro/Hd8eZm7U/fyB0AAMDTOGcNAADAwby5WePyTgAAAAdjsgYAABzPm/dZY7IGAADgYEzWAACA43nzOWs0awAAwPFo1gAAAFCiV199Va+88opcLpcqV66sKVOmKCIiosjnvP3225o1a5bq1PnfnpMvvviiqlevfsF5adYAAIDjlfVk7fvvv9eiRYv05ptvqnbt2vrkk080btw4rV27tshG/OvXr9eECRM0fPhw23Jf0AUGhw8ftq0AAAAAp6tRo4YSEhJUu3ZtSVJERIQOHjyokydPFvm8DRs26JNPPtGgQYMUFRWlb7/99qJzu52spaSkKD4+XtOnT5evr6/uuusu/frrr2rYsKHmzZun5s2bX3QRAAAAJTExWcvIyFBmZmaxrwUHByskJKTwcdOmTdW0aVNJZ7cRmTlzpnr27KmAgIDCzzl9+rTCwsI0cuRIdenSRd99953GjRunt956S/XrX/gt7Nw2a1OmTFHfvn1Vv3593XPPPRoxYoQGDhyo1atXa9q0aXrttdcuODkAAEBpmNhnLSkpSfPnzy/2tfHjx2vChAnnPX/8+HFNmjRJhw4d0qJFi4q8VqFCBS1evLjwcceOHdW+fXutXbtWUVFRF1yn22bt+PHjhQkyMjI0ZMgQSVK/fv20cOHCC04MAABQloYMGaJevXoV+1pwcPB5z+3evVt///vfFRERoccff1wVK1Ys8np6erreffddjRgxovA5y7Lk7+9/UXW6bdYqVaqkzZs3q02bNmrcuLF2796txo0ba8+ePfL19b2o5AAAAKVhYhk0JCSkyFJnSfbv36/o6GiNHDlSI0eOLPZzAgIC9PTTT6tVq1a66qqrtHnzZv3www+aMWPGRdXptlmbOHGiRo0apc6dOysgIEDR0dG6/PLLtXHjxotODgAAUB4sXrxYR48e1YoVK7RixYrC5xctWqQxY8Zo0aJFCg0N1VNPPaU5c+YoNzdXfn5+euKJJxQUFHRRud02ax06dNCKFSu0atUq7d69W9dee61CQ0N17733qkWLFheVHAAAoDTKeuuO+Ph4xcfHF/va8uXLC//cqVMnvfnmm7bmLtU+a6Ghobr99tttTQwAAFBaZd2slSW3zdofdZHnJCQk2FYMAAAAinLbrAUGBioxMVExMTHy8bmgPXQBAAAuiomtO8oLt81abGyskpOTFRQUdFF7hAAAAODPc1mlWAROTU1VUlKS4uLiPFETAABAERERl9se88cff7A9pgmlatZsT/qbG56aYFmW8T3g8vPzVblyZWPxT548qeDg0u39cqEyMzPUqlVrozm2bftJV1zRwWiO779fr0aNGhvNkZKyW3XrhhmLn5a2X6GhdYzFl6T09ANq3LiJ0Ry7d+9Sw4aNjOb49dcUXX11D6M51q79THfdNc5Y/IULn9aUKdOMxZekGTMe0qeffm40R8+e3XX33fcYzfHUU3M1YUKs0Rzz5j2hm27qbyz+e++tNBr/XI5evXobzfHxx2uMxnenTZu2tsfcvHmT7TFN4CQ0AAAAByvV1h0AAABlia07AAAAHMybmzWWQQEAAByMyRoAAHA8b95njckaAACAgzFZAwAAjufN56zRrAEAAMfz5mbN7TLoqVOnPFEHAAAAiuG2WevcubNWr17tiVoAAACKZVmW7R/lhdtmrWbNmpo7d66mTp2q7OxsT9QEAACA/3LbrNWqVUtJSUmqUKGCrr/+ej366KNKSUnxQGkAAABnMVlzo0qVKpo2bZqSkpJ04sQJDRs2TD179lR0dLTp+gAAAFRQkG/7R3nh9mrQ33aejRo10rRp0xQfH68dO3YwYQMAADDMbbN23XXXnfecy+VSixYt1KJFCyNFAQAA/FZ5Wra0m9tl0LvvvtsTdQAAAKAYbidr8fHxJb6ekJBgWzEAAADF8ebJmttmLTAwUImJiYqJiZGPD7cSBQAAnkezVoLY2FglJycrKChIUVFRnqgJAAAA/+WyStGqpqamKikpSXFxcZ6oCQAAoIiGDRvZHvPXX1Nsj2lCqZo125O6XEbjW5blkRz+/v7G4p85c0aBgUHG4kvSwYNZ6t69p9Ecn3/+qVq3bmM0x08/bdaVV3Y2muPbb79Ws2bmrn7eufNnNWrU2Fh8SUpJ2W30GKSzx1G3bpjRHGlp+3X11T2M5li79jNddVVXY/G/+uoLxcdPNxZfkhISpuu1194wmmPo0MFG43vS22+vNBZ7wID+2rcv1Vh8SapXL9xofCfw5mbN7TIoAABAWSsoKCjrEsoMzRoAAHA8b77AgMs7AQAAHIzJGgAAcDwmawAAAHAkJmsAAMDxvHmyRrMGAAAcz5ubNZZBAQAAHOyCJmtHjhxRzZo17a4FAACgWN68z5rbyVpWVpYmT56sBx98UBkZGRo0aJA6d+6sG264Qbt27fJEjQAAAF7LbbM2ZcoU1axZUwUFBYqKilKfPn20adMmjRs3Tg8//LAnagQAAF7OsizbP8oLt8ugBw4c0MKFC2VZlq6++mqNGTNGkhQZGakXXnjBeIEAAADlqbmym9vJWl5eng4dOqR9+/bpyJEjysrKkiQdP35cp06dMl4gAACAN3M7Wbvtttt0/fXXKz8/XxMmTFBMTIx69Oihzz//XH/72988USMAAPBy3jxZc9usDR06VN26dVNBQYEaNGig1q1b65NPPtGdd96pQYMGeaJGAAAAr1WqrTvq1atX+Odu3bqpW7duxgoCAAD4PSZrJYiPjy/x9YSEBNuKAQAAKI4377PmtlkLDAxUYmKiYmJi5OPDDQ8AAAA8yW2zFhsbq+TkZAUFBSkqKsoTNQEAABThzcugLqsUR5+amqqkpCTFxcV5oiYAAIAiatSw/zaX2dlHbI9pQqmaNduTulxG41uWJV9fX6M58vPz5ed3QbdWLZW8vDw1atTYWHxJSknZrebNWxrNsWPHdnXu3MVojq+//lJXXdXVaI6vvvpCbdu2MxZ/06aNql+/gbH4krR37x61a9feaI6NGzdo6NBoozlee+1lvfJKktEcUVFDtHLle8bi9+9/k7HYv5WZmWU0fnBwkNGvk3T2a/X00wuN5hg37i716xdpLP477yzXwIG3GIsvScuW/T8995zZjepHjYoxGt8db27WzHUbAAAANvHmZVCuGAAAAHAwJmsAAMDxvHmyRrMGAAAcr6Agv6xLKDMsgwIAADgYkzUAAOB43rwMymQNAADAwZisAQAAx/PmyVqpm7W8vDwdOXJE/v7+qlGjhsmaAAAAiqBZK8Hx48c1bdo0rVmzRmfOnJEk1axZUwMGDFBcXJz8/f2NFwkAAOCt3J6zlpCQoEsuuURvvfWWRo0apfj4eD333HNKTU3V7NmzPVEjAADwcpZl2f5RXrht1rZt26Zx48bpkksu0X333acVK1aodevWevzxx7V27VpP1AgAAOC13C6Dnj59WsePH1fVqlV16NAh5eTkSDJ/I3MAAIBzCgoKyrqEMuO22+rbt6+GDRumXr166dNPP1W/fv2Umpqqu+66SzfeeKMnagQAAF6uPC1b2s1tszZhwgTVq1dPW7Zs0YgRIxQZGans7GxNmTJFV111lSdqBAAA8FqlWsccOHCgBg4cWPi4Ro0aNGoAAMBjmKyVID4+vsTXExISbCsGAAAARblt1gIDA5WYmKiYmBj5+HB3KgAA4HlM1koQGxur5ORkBQUFKSoqyhM1AQAAFOHNzZrLKsXRp6amKikpSXFxcZ6oCQAAAP9VqmYNAAAAZYOT0AAAAByMZg0AAMDBaNYAAAAcjGYNAADAwWjWAAAAHIxmDQAAwMFo1gAAAByMZg0AAMDBaNYAAAAczO29QcvS2rVr9X//93/Kzc1V3bp1NXv2bIWEhBjJ9cQTTygzM1MzZsywNe6rr76qV155RS6XS5UrV9aUKVMUERFhaw5JevPNN7VkyRJJUq1atfTggw+qcePGtufZtGmToqOjtWbNGtWpU8fW2JMnT9Y333yjatWqSZIaNmyouXPn2ppj586deuihh3Ts2DH5+Pho2rRpuvzyy22L/8Ybb+ill14qfHzixAnt27dPq1atUsOGDW3JsWbNGj355JPy8fFR1apV9dBDD6lp06a2xD7n1Vdf1dKlS+Xv76+wsDBNnz7dtu/3799ry5cv16JFi5SXl6dWrVrp4YcfVtWqVW3NIUkFBQWaPHmyGjZsqHHjxl1U/OJyzJ8/X++//758fHwUGBioBx544KLfg7/PsWjRIr399ttyuVxq0KCBEhISFBQUZGuOcz788EP94x//0JYtW2yNf/vttys9PV2VKlWSJHXs2FFTp061Ncf69es1Z84cnTp1SlWqVNHMmTNt/V7Mnz9fH374YeFrR44c0eHDh/X1118rICDAtuN47bXXtHTpUvn6+qpOnTqaMWPGRf8b+NsclmVp/vz5euedd1ShQgW1bNlS8fHxql69+kXlgAGWQx08eNC68sorre3bt1uWZVmJiYnWiBEjbM+zd+9ea9y4cVZERIT173//29bYGzZssHr27GkdPHjQsizL+vjjj62uXbtaBQUFtub55ZdfrKuuusrKysqyLMuyli5dag0fPtzWHJZlWVlZWVZkZKTVvHlzKy0tzfb41113nfXzzz/bHveckydPWt26dbNWrVplWZZlffLJJ1bPnj1t/36ck5eXZw0fPtx67rnnbIt58uRJq02bNtbOnTstyzr7vY6OjrYtvmVZ1tdff2117drVSk1NtSzLspYtW2YNHjz4ouMW917bsWOHddVVV1kHDhywLMuyZs2aZcXHx9uaw7Isa9u2bVZUVJQVERFhPfXUU7Yfx4oVK6xBgwZZJ06csCzLsl588UXrlltusTXH2rVrrRtvvLEwx8yZM63777/f1hznJCcnW7169bJatWpla/zTp09b7dq1s7Kzsy84rrscBw4csDp27Gj98MMPlmVZ1ksvvWRFRUXZmuO3jh07Zt10003We++9Z2uOPXv2WFdccYWVmZlpWdbZ98akSZNszfHWW29Zffv2tY4cOWJZlmXNnz/fio2NveAcMMexy6Dr1q1TixYt1KJFC0nS0KFD9c033ygzM9PWPElJSerSpYtiYmJsjStJNWrUUEJCgmrXri1JioiI0MGDB3Xy5Elb8zRp0kSfffaZAgMDlZeXp/3796tWrVq25sjLy1NcXJwmTpxoa9xzsrKytH//fs2dO1f9+/fXhAkTlJqaamuOdevWKTg4WNdff70kqUePHnrmmWdkGbo97pIlS+Tr66sRI0bYFjM/P18ul0vZ2dmSpJycnMIJhV22bNmiK6+8UmFhYZKk66+/Xps2bbro70dx77U1a9aoR48eCg0NlSRFR0dr5cqVKigosC2HJL344osaNmyYbrzxxgs/gBJyNGzYUFOnTi2cqkRERFzU16u4HN26ddPy5csVEBCg3NxcZWZmXtT7/I++VsePH9fEiRM1ZcqUC479R/G3bt2qChUq6J///Kf69++vyZMn6/Dhw7bm+OCDD9S5c2e1bdtWkjR48GA9+OCDtub4rccee0xt27a9qJ+t4nIUFBQoPz9fOTk5sizrot/rxeXYvHmzrrnmGtWoUUPS2ff6hx9+qNOnT19wHpjh2GbtwIEDqlu3buHjChUqqFatWkpLS7M1z3333afo6Gj5+vraGleSmjZtqm7dukk6+8abOXOmevbseVFj8j/i7++v9evXq0ePHkpKSrK9+ZwzZ446deqkrl272hr3nIyMDHXr1k2TJ0/WihUrFBERobFjxyo/P9+2HLt371ZISIimTp2qQYMG6Y477tDp06fl42P/2+Do0aNauHChpk6dKpfLZVvcKlWq6MEHH9Qdd9yh7t276/nnn7e9gY6IiNC3336rvXv3SpLefvttSWe/RxejuPdaWlpakfd5nTp1lJOToyNHjtiWQ5JmzJihfv36XVjhpcgRERGhdu3aSZJyc3P1n//8RzfddJOtOaSz7/N33nlH3bt313fffachQ4bYnmPy5Mm644471Lx58wuO/Ufxs7Oz1blzZ82ePVvLli1TQEDARf38Fpdj9+7dqlKliuLi4jRw4EBNmDDhon6/l/RvREpKilauXKl//vOfFxz/j3I0bNhQY8eO1U033aRu3bpp3bp1F7V8/0c/t59++qkOHToky7K0YsUKnTlz5oLffzDHsc2aZVnF/iNn4h9W044fP67x48crNTVVs2fPNpanQ4cO+uKLLzRnzhyNGTNGR48etSXuO++8oz179ujvf/+7LfGKc+mll2rBggUKDw+Xy+XSqFGjlJqaqpSUFNty5OXl6YsvvtCAAQP01ltvaeTIkRozZoyOHz9uW45zXn/9dXXp0kWXXHKJrXF//vlnzZ07VytWrNDnn3+uqVOnavTo0crJybEtR8eOHXXvvffqnnvu0c0336ycnBzVrFlT/v7+tuX4reLe53Y2uJ6UkZGhO+64Q9WqVdOkSZOM5OjXr5+++eYbjRkzRiNHjrzgKWRxFi5cqKCgIEVGRtoW87e6d++uJ554QrVq1ZKfn5/Gjx+vdevW2frzm5eXp08++UR33323li1bpmuuuUZjx461Lf5vJSYm6tZbby1cPbHTunXr9M477+ijjz7SunXrNHToUI0dO9bWlYABAwaoX79+uuOOOzR06NDC81JNvddx4Rzb+YSFhSk9Pb3w8enTp3X48OHCpZnyYvfu3brllltUtWpVJSYmGjlxc9++ffrqq68KH/fu3Vv+/v7as2ePLfHffPNN7dmzRwMGDCj8JT5y5EitX7/elviStHHjRn3wwQdFnrMsS35+9l0DExoaqkaNGqlDhw6Szi6D+vn5adeuXbblOOe9997TzTffbHvcdevWqU2bNmrSpIkkqX///srPz9cvv/xiW44TJ06oQ4cOWrZsmd58803dfPPNOnbsmBo0aGBbjnN+/z5PT09XlSpVCpdlypNNmzbp5ptvVocOHTR//nxVqFDB1vg7d+7Upk2bCh8PHjxY+/btK1wSt8OyZcu0fv16RUZGasyYMcrPz1dkZKRtv0s+++wzffHFF4WPLcuSj4+P7e/zyy+/vPCim0GDBiklJUWHDh2yLYd0drXk/fffN/I+l6SPP/5Y3bt3V2hoqFwul26//XZt3br1opaNf+/IkSPq27evVq5cqaSkJLVt21Y1a9ZUzZo1bcsBezi2Wevatau2bt2qHTt2SDp7lV3btm2N/A/GlP379ys6OlqDBw/WnDlzVLFiRSN5srOzFRsbqwMHDkg6Fiu4NwAAAxNJREFU+wvRx8fHtisEX3jhBb333ntavny5li9fLklavHhxYdNjh9OnTyshIaFwqe3FF19U06ZNbW0QunfvrrS0NP3www+SpA0bNuj06dOFjY9djh07ph07dqhjx462xpWk1q1ba8OGDYXf6++++055eXm2XvmbkZGh6Ojowibg6aefVq9evYz8R+Paa6/VZ599Vtiwvfzyy+rdu3e5m6D/9NNPGjFihP71r3/pn//8p5H6U1JSNHHiRB07dkyS9NZbb6lFixa2np/6wQcfaOXKlYVX6Pr6+mr58uW2vQ8PHTqkmTNnFk6zFy1apN69e9va2F533XXauHFj4VR+9erVatCgge0NyI4dO1ShQgXbf3+c07p1a61du7bw+33uinI7/w3cunWr7rrrLp0+fVr5+flauHChBgwYUG4n239ljt26o3bt2nr88cd1//33Kzc3V4GBgZozZ05Zl/WnLF68WEePHtWKFSu0YsWKwucXLVpUeEK1HVq3bq37779fo0ePlo+Pj6pXr65nn31WlStXti2HaZ06ddK4ceMUExOj/Px8hYWF6cknn7T1l0ZQUJAWLlyomTNnKicnR76+vpo3b95FbxPxeykpKapdu7btJ/5LUufOnXX33XcrJiZG/v7+CggI0DPPPGPrMTRu3FgTJkzQsGHDlJ+fr0svvVQzZ860Lf5vNWvWTJMmTdKoUaN05swZNW7cWI888oiRXCbNmzdPBQUFWrRokRYtWlT4/Ln/3Njhuuuu0+7duzVkyBD5+fmpbt26euqpp2yL7wkDBw7Unj3/v307to0QiKIo+h2RbERKAVAD2pwUIbYOAjpA2goIaG/lhCJA2Klzz0pj+ZwC5qVX+prPeDwecV1X1HUdy7Ik3WiaJp7PZ0zTFOd5xu12i3Vdkwf06/WKqqqSvvnTMAyx73uM4xhFUURZlrFtW9KNtm2j67ro+z6O44j7/R7zPCfdII2Pr3d9hQMA4Nf+1q0BAOCfEWsAABkTawAAGRNrAAAZE2sAABkTawAAGRNrAAAZE2sAABkTawAAGfsGjcmROpk9H9MAAAAASUVORK5CYII=\n",
409 | "text/plain": [
410 | ""
411 | ]
412 | },
413 | "metadata": {},
414 | "output_type": "display_data"
415 | }
416 | ],
417 | "source": [
418 | "cmap = sns.cubehelix_palette(50, hue=0.05, rot=0, light=0.0, dark=1.2, as_cmap=True)\n",
419 | "figure(num=None, figsize=(10, 7), dpi=80, facecolor='w', edgecolor='k')\n",
420 | "ax = sns.heatmap(win_all_b, linewidth=0.01, cmap=cmap)\n",
421 | "plt.show()"
422 | ]
423 | },
424 | {
425 | "cell_type": "code",
426 | "execution_count": null,
427 | "metadata": {},
428 | "outputs": [],
429 | "source": []
430 | }
431 | ],
432 | "metadata": {
433 | "kernelspec": {
434 | "display_name": "Python 3",
435 | "language": "python",
436 | "name": "python3"
437 | },
438 | "language_info": {
439 | "codemirror_mode": {
440 | "name": "ipython",
441 | "version": 3
442 | },
443 | "file_extension": ".py",
444 | "mimetype": "text/x-python",
445 | "name": "python",
446 | "nbconvert_exporter": "python",
447 | "pygments_lexer": "ipython3",
448 | "version": "3.7.2"
449 | }
450 | },
451 | "nbformat": 4,
452 | "nbformat_minor": 2
453 | }
454 |
--------------------------------------------------------------------------------