├── web
├── static
│ └── css
│ │ └── dashboard.css
├── templates
│ └── dashboard.html
└── app.py
├── for_setup_airlfow
├── airflowignore.template
└── docker-compose.yaml
├── .gitignore
├── airflow_requirements.txt
├── requirements.txt
├── tests
├── reports
│ └── financial_reports
│ │ ├── resources
│ │ ├── mock_financial_report_fail_example.html
│ │ └── mock_financial_report_success_example.html
│ │ └── test_financial_report_agent.py
├── toolbox
│ └── test_date_tool.py
└── db_bridges
│ └── mongo_bridge
│ └── test_collection_structure.py
├── reports
├── financial_reports
│ ├── balance_sheet.py
│ ├── comprehensive_income_sheet.py
│ ├── sheet.py
│ └── financial_report_agent.py
└── monthly_revenue
│ └── monthly_revenue.py
├── dags
├── common
│ └── setup_project.py
├── parse_monthly_revenue
│ └── parse_monthly_revenue.py
├── three_days_strategy
│ └── three_days_strategy.py
├── crawl_daily_transaction
│ ├── crawl_daily_transaction.py
│ └── crawl_yahoo_daily_transaction.py
└── parse_financial_report
│ └── parse_financial_report.py
├── strategies
└── three_days_strategy.py
├── toolbox
└── date_tool.py
├── db_bridges
└── mongo_bridge
│ └── collection_structure.py
├── daily_transaction
├── yahoo_daily_transaction.py
└── daily_transaction.py
├── README.md
└── lab
└── experiment1
├── .ipynb_checkpoints
└── three_days_strategy-checkpoint.ipynb
└── three_days_strategy.ipynb
/web/static/css/dashboard.css:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/for_setup_airlfow/airflowignore.template:
--------------------------------------------------------------------------------
1 | venv/
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | venv/
2 | __pycache__
3 | *.swp
4 | .idea
5 | .DS_Store
6 |
--------------------------------------------------------------------------------
/airflow_requirements.txt:
--------------------------------------------------------------------------------
1 | beautifulsoup4
2 | requests
3 | apache-airflow-providers-mongo==2.0.0
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | apache-airflow==2.1.3
2 | autopep8
3 | beautifulsoup4
4 | requests
5 | apache-airflow-providers-mongo==2.0.0
6 | plotly==5.2.1
7 | pandas==1.2.4
8 | pymongo==3.12.0
9 | Flask==1.1.4
10 | pytest==6.2.5
--------------------------------------------------------------------------------
/tests/reports/financial_reports/resources/mock_financial_report_fail_example.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YanHaoChen/tw-financial-report-analysis/HEAD/tests/reports/financial_reports/resources/mock_financial_report_fail_example.html
--------------------------------------------------------------------------------
/tests/reports/financial_reports/resources/mock_financial_report_success_example.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YanHaoChen/tw-financial-report-analysis/HEAD/tests/reports/financial_reports/resources/mock_financial_report_success_example.html
--------------------------------------------------------------------------------
/reports/financial_reports/balance_sheet.py:
--------------------------------------------------------------------------------
1 | from reports.financial_reports.sheet import Sheet
2 | from bs4 import BeautifulSoup
3 |
4 |
5 | class BalanceSheet(Sheet):
6 | def __init__(self, sheet: BeautifulSoup):
7 | self.magic_id = ''
8 | self.sheet = sheet
9 | self.dollar_unit = 0
10 |
11 | def set_magic_id(self):
12 | self.magic_id = 'BalanceSheet'
13 |
--------------------------------------------------------------------------------
/reports/financial_reports/comprehensive_income_sheet.py:
--------------------------------------------------------------------------------
1 | from reports.financial_reports.sheet import Sheet
2 | from bs4 import BeautifulSoup
3 |
4 |
5 | class ComprehensiveIncomeSheet(Sheet):
6 | def __init__(self, sheet: BeautifulSoup):
7 | self.magic_id = ''
8 | self.sheet = sheet
9 | self.dollar_unit = 0
10 |
11 | def set_magic_id(self):
12 | self.magic_id = 'StatementOfComprehensiveIncome'
13 |
--------------------------------------------------------------------------------
/web/templates/dashboard.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | tw-financial-report-analysis
8 | ROA(Per Season)
9 |
10 | ROE(Per Season)
11 |
12 |
13 |
14 |
21 |
--------------------------------------------------------------------------------
/tests/toolbox/test_date_tool.py:
--------------------------------------------------------------------------------
1 | from toolbox.date_tool import DateTool
2 | import unittest
3 |
4 |
5 | class DateToolTestCase(unittest.TestCase):
6 |
7 | def test_date_to_ex_year_and_season_successfully(self):
8 | ex_year, ex_season = DateTool.date_to_ex_year_and_season(2019, 10)
9 | assert (ex_year == 2019 and ex_season == 3) is True
10 |
11 | ex_year, ex_season = DateTool.date_to_ex_year_and_season(2020, 1)
12 | assert (ex_year == 2019 and ex_season == 4) is True
13 |
14 | def test_season_to_ex_year_and_season_int_successfully(self):
15 | ex_year_and_season_int = DateTool.season_to_ex_year_and_season_int(20201)
16 | assert ex_year_and_season_int == 20194
17 |
18 | def test_to_tw_year_successfully(self):
19 | tw_year = DateTool.to_tw_year(2020)
20 | assert tw_year == 109
21 |
22 | def test_tw_year_to_year_successfully(self):
23 | year = DateTool.tw_year_to_year(109)
24 | assert year == 2020
25 |
26 |
27 | if __name__ == '__main__':
28 | unittest.main()
29 |
--------------------------------------------------------------------------------
/dags/common/setup_project.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | from functools import wraps
4 |
5 | from airflow.utils.dates import days_ago
6 | from airflow.settings import AIRFLOW_HOME
7 | from airflow import DAG
8 | from airflow.operators.bash import BashOperator
9 |
10 |
11 | class EnvSetting(object):
12 | PROJECT_HOME = f'{AIRFLOW_HOME}/dags/tw-financial-report-analysis'
13 |
14 | @staticmethod
15 | def append_project_to_path(f):
16 | @wraps(f)
17 | def insert_path(*args, **kwds):
18 | sys.path.insert(0, EnvSetting.PROJECT_HOME)
19 | return f(*args, **kwds)
20 |
21 | return insert_path
22 |
23 |
24 | args = {
25 | 'owner': 'sean',
26 | }
27 |
28 | dag = DAG(
29 | dag_id='setup_tw_financial_report_analysis',
30 | default_args=args,
31 | schedule_interval='@daily',
32 | start_date=days_ago(1),
33 | )
34 |
35 | check_requirements = BashOperator(
36 | task_id='check_requirements',
37 | bash_command=f'pip3 install -r {EnvSetting.PROJECT_HOME}/airflow_requirements.txt',
38 | depends_on_past=True,
39 | dag=dag
40 | )
41 |
42 | check_requirements
43 |
--------------------------------------------------------------------------------
/web/app.py:
--------------------------------------------------------------------------------
1 | import json
2 | import logging
3 | import plotly
4 | import plotly.express as px
5 | from flask import Flask, render_template
6 | import pandas as pd
7 | from pymongo import MongoClient
8 | from urllib.parse import quote_plus
9 |
10 | uri = "mongodb://%s:%s@%s:%s/%s" % (
11 | quote_plus('airflower'),
12 | quote_plus('money'),
13 | '127.0.0.1',
14 | '27017',
15 | 'stock'
16 | )
17 | stock_db = MongoClient(uri).stock
18 |
19 | app = Flask(__name__, template_folder='./templates')
20 |
21 | @app.route("/")
22 | def dashboard():
23 | financial_report_data = pd.DataFrame(stock_db.financialReports.find({}))
24 | financial_report_data['stockCode'] = financial_report_data['stockCode'].astype(str)
25 | roa_fig = px.bar(financial_report_data, x="yearAndSeason", y="roa", color="stockCode", barmode="group")
26 | roa_fig.update_layout(xaxis_type='category')
27 | roa_fig.update_xaxes(categoryorder='category ascending')
28 | roa_json = json.dumps(roa_fig, cls=plotly.utils.PlotlyJSONEncoder)
29 |
30 | roe_fig = px.bar(financial_report_data, x="yearAndSeason", y="roe", color="stockCode", barmode="group")
31 | roe_fig.update_layout(xaxis_type='category')
32 | roe_fig.update_xaxes(categoryorder='category ascending')
33 | roe_json = json.dumps(roe_fig, cls=plotly.utils.PlotlyJSONEncoder)
34 | return render_template('dashboard.html', roaJson=roa_json, roeJson=roe_json)
35 |
36 | if __name__ == '__main__':
37 | app.run()
--------------------------------------------------------------------------------
/strategies/three_days_strategy.py:
--------------------------------------------------------------------------------
1 | from db_bridges.mongo_bridge.collection_structure import CollectionStructure
2 | from toolbox.date_tool import DateTool
3 |
4 |
5 | class ThreeDaysStrategyDataCollection(CollectionStructure):
6 | def set_name(self):
7 | return 'threeDaysStrategyData'
8 |
9 | def set_unique_fields(self):
10 | return {
11 | 'stockCode': str,
12 | 'year': int,
13 | 'month': int,
14 | 'day': int,
15 | 'intDate': int,
16 | }
17 |
18 | def set_data_fields(self):
19 | return {
20 | 'd1AgoTradeVolume': 0,
21 | 'd1AgoAmount': 0,
22 | 'd1AgoOpeningPrice': 0.0,
23 | 'd1AgoHighestPrice': 0.0,
24 | 'd1AgoLowestPrice': 0.0,
25 | 'd1AgoClosingPrice': 0.0,
26 | 'd1AgoClosingDiff': 0.0,
27 | 'd1AgoTransaction': 0,
28 | 'd1AgoMaxDiff': 0.0,
29 | 'd2AgoTradeVolume': 0,
30 | 'd2AgoAmount': 0,
31 | 'd2AgoOpeningPrice': 0.0,
32 | 'd2AgoHighestPrice': 0.0,
33 | 'd2AgoLowestPrice': 0.0,
34 | 'd2AgoClosingPrice': 0.0,
35 | 'd2AgoClosingDiff': 0.0,
36 | 'd2AgoTransaction': 0,
37 | 'd2AgoMaxDiff': 0.0,
38 | 'd3AgoTradeVolume': 0,
39 | 'd3AgoAmount': 0,
40 | 'd3AgoOpeningPrice': 0.0,
41 | 'd3AgoHighestPrice': 0.0,
42 | 'd3AgoLowestPrice': 0.0,
43 | 'd3AgoClosingPrice': 0.0,
44 | 'd3AgoClosingDiff': 0.0,
45 | 'd3AgoTransaction': 0,
46 | 'd1AgoMaxDiff': 0.0,
47 | 'dDayPriseRise': 0,
48 | 'dDayClosingDiff': 0,
49 | }
50 |
--------------------------------------------------------------------------------
/tests/db_bridges/mongo_bridge/test_collection_structure.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from db_bridges.mongo_bridge.collection_structure import CollectionStructure
3 |
4 |
5 | class FakeCollection(CollectionStructure):
6 |
7 | def set_name(self):
8 | return 'fake'
9 |
10 | def set_unique_fields(self):
11 | return {'a': int, 'b': str}
12 |
13 | def set_data_fields(self):
14 |
15 | return {'c': 1, 'd': 'hi'}
16 |
17 |
18 | class IncompleteFakeCollection(CollectionStructure):
19 |
20 | def set_name(self):
21 | return 'fake'
22 |
23 | def set_unique_fields(self):
24 | return {'a': int, 'b': str}
25 |
26 | # without this
27 | # def set_data_fields(self):
28 | # return {'c': 1, 'd': 'hi'}
29 |
30 |
31 | class TestCollectionStructure(unittest.TestCase):
32 |
33 | def test_create_collection_structure_successfully(self):
34 | try:
35 | fake = FakeCollection()
36 | new_document = fake.document_operator(a=123, b='str', c=2)
37 |
38 | self.assertEqual(fake.name, 'fake')
39 | self.assertEqual(fake.unique_fields, {'a': int, 'b': str})
40 | self.assertEqual(fake.data_fields, {'c': 1, 'd': 'hi'})
41 | self.assertEqual(new_document, {
42 | 'a': 123,
43 | 'b': 'str',
44 | 'c': 2,
45 | 'd': 'hi'
46 | })
47 |
48 | except Exception as e:
49 | self.fail(f'Raise {e}. So The testing is fail.')
50 |
51 | def test_create_collection_structure_unsuccessfully(self):
52 | try:
53 | _ = IncompleteFakeCollection()
54 | self.fail(f'Except create fail')
55 | except TypeError as e:
56 | self.assertEqual(
57 | str(e),
58 | "Can't instantiate abstract class IncompleteFakeCollection with abstract methods set_data_fields"
59 | )
60 | pass
61 |
--------------------------------------------------------------------------------
/toolbox/date_tool.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 | import time
3 |
4 |
5 | class DateTool:
6 |
7 | @staticmethod
8 | def date_to_timestamp(year: int, month: int, day: int, end=False):
9 | if end:
10 | this_date = datetime(
11 | year=year,
12 | month=month,
13 | day=day,
14 | hour=23,
15 | minute=59,
16 | second=59
17 | )
18 | else:
19 | this_date = datetime(
20 | year=year,
21 | month=month,
22 | day=day
23 | )
24 |
25 | return int(time.mktime(this_date.timetuple()))
26 |
27 | @staticmethod
28 | def date_to_ex_year_and_season(year, month):
29 | ex_season_mapping = {
30 | 1: 4,
31 | 2: 4,
32 | 3: 4,
33 | 4: 1,
34 | 5: 1,
35 | 6: 1,
36 | 7: 2,
37 | 8: 2,
38 | 9: 2,
39 | 10: 3,
40 | 11: 3,
41 | 12: 3
42 | }
43 | season = ex_season_mapping[month]
44 | season_year = year if season != 4 else year - 1
45 |
46 | return season_year, season
47 |
48 | @staticmethod
49 | def season_to_ex_year_and_season_int(now_year_and_season: int):
50 | now_season = now_year_and_season % 10
51 | now_year = now_year_and_season // 10
52 | ex_season = now_season - 1
53 | ex_year = now_year
54 | if ex_season == 0:
55 | ex_season = 4
56 | ex_year -= 1
57 | return ex_year * 10 + ex_season
58 |
59 | @staticmethod
60 | def to_tw_year(year: int) -> int:
61 | return year - 1911
62 |
63 | @staticmethod
64 | def tw_year_to_year(year: int) -> int:
65 | return year + 1911
66 |
67 | @staticmethod
68 | def to_next_year_month(year: int, month: int) -> (int, int):
69 | month += 1
70 | if month == 13:
71 | year += 1
72 | month = 1
73 | return year, month
74 |
75 |
--------------------------------------------------------------------------------
/db_bridges/mongo_bridge/collection_structure.py:
--------------------------------------------------------------------------------
1 | import abc
2 | import logging
3 |
4 |
5 | class CollectionStructure(abc.ABC):
6 | def __init__(self):
7 | self.name = self.set_name()
8 | self.__unique_fields = self.set_unique_fields()
9 | self.__data_fields = self.set_data_fields()
10 |
11 | @abc.abstractmethod
12 | def set_name(self):
13 | # For Example: return 'collectionA'
14 | raise NotImplementedError
15 |
16 | @abc.abstractmethod
17 | def set_unique_fields(self):
18 | # {'key': 'type'} For Example: return {'a': int(), 'b': str}
19 | raise NotImplementedError
20 |
21 | @property
22 | def unique_fields(self):
23 | return self.__unique_fields
24 |
25 | @abc.abstractmethod
26 | def set_data_fields(self):
27 | # {key: default_value} For Example: return {'c': 123}
28 | raise NotImplementedError
29 |
30 | @property
31 | def data_fields(self):
32 | return self.__data_fields
33 |
34 | def get_unique_fields(self, document):
35 | unique_fields = {}
36 | for key in self.unique_fields.keys():
37 | unique_fields[key] = document[key]
38 |
39 | return unique_fields
40 |
41 | def bind_db(self, db):
42 | return db[self.name]
43 |
44 | def document_operator(self, **kwargs):
45 | document_dict = {}
46 | document_dict.update(self.__data_fields)
47 | try:
48 | for field in self.__unique_fields.keys():
49 | document_dict[field] = kwargs[field]
50 | except KeyError as e:
51 | logging.error(f'The unique field, {e}:{self.__unique_fields[e]}, is not included in kwargs.')
52 | return None
53 |
54 | for field in self.__data_fields.keys():
55 | try:
56 | document_dict[field] = kwargs[field]
57 | except KeyError as e:
58 | logging.warning((f'The data field, {e}, is not included in kwargs. '
59 | f'So use the default value for this.'))
60 |
61 | return document_dict
62 |
63 |
64 | class TryThis(CollectionStructure):
65 | def set_name(self):
66 | return 'monthly'
67 |
68 | def set_unique_fields(self):
69 | return ['a', 'b']
70 |
71 | def set_data_fields(self):
72 | return ['c', 'd']
73 |
74 |
75 | if __name__ == '__main__':
76 | a = TryThis()
77 | print(a.name)
78 | print(a.key_fields)
79 |
80 | print(a.data_fields)
--------------------------------------------------------------------------------
/reports/financial_reports/sheet.py:
--------------------------------------------------------------------------------
1 | import abc
2 | import re
3 |
4 | from bs4 import BeautifulSoup
5 |
6 |
7 | class Sheet(abc.ABC):
8 | def __init__(self):
9 | self.magic_id = ""
10 | self.dollar_unit = 0
11 | self.sheet = None
12 |
13 | def set_dollar_unit(self, dollar_unit):
14 | self.dollar_unit = dollar_unit
15 |
16 | @abc.abstractmethod
17 | def set_magic_id(self):
18 | raise NotImplementedError
19 |
20 | def get_magic_id(self):
21 | return self.magic_id
22 |
23 | def parse_items_to_dict(self, item_set, columns={1: ''}):
24 | result = self.search_key_string_set(self.sheet, item_set, columns)
25 | self.sheet_str_to_number(result)
26 | return result
27 |
28 | @staticmethod
29 | def search_key_string_set(sheet: BeautifulSoup, search_set: set, columns):
30 | result = {}
31 |
32 | td = sheet.find_next('td')
33 | while search_set and td:
34 | zh_td_span = td.find('span', class_='zh')
35 | en_td_span = td.find('span', class_='en')
36 | for td_span in [zh_td_span, en_td_span]:
37 | if td_span:
38 | span_item = td_span.string.lstrip()
39 | if span_item in search_set:
40 | span_item = re.split(' \\(|(', span_item)[0]
41 | str_list = re.split(' |-', span_item.lower())
42 | formatted_item_name = f'{str_list[0]}'
43 | for this_str in str_list[1:]:
44 | formatted_item_name += f'{this_str[0].upper()}{this_str[1:]}'
45 |
46 | siblings_tds = td.find_next_siblings('td')
47 | for idx, prefix in columns.items():
48 | td_value = siblings_tds[idx - 1].find('ix:nonfraction').string
49 | if prefix != '':
50 | new_formatted = f'{formatted_item_name[0].upper()}{formatted_item_name[1:]}'
51 | result[f'{prefix}{new_formatted}'] = td_value
52 | else:
53 | result[formatted_item_name] = td_value
54 | search_set.remove(span_item)
55 | break
56 |
57 | td = td.find_next('td')
58 |
59 | return result
60 |
61 | @staticmethod
62 | def sheet_str_to_number(result_dict: dict):
63 | for key, acc_number in result_dict.items():
64 | number = acc_number.replace(",", "")
65 | if '(' in number:
66 | result_dict[key] = float(number[1:-1]) * -1.0
67 | else:
68 | result_dict[key] = float(number)
69 |
--------------------------------------------------------------------------------
/daily_transaction/yahoo_daily_transaction.py:
--------------------------------------------------------------------------------
1 | import requests
2 |
3 | from db_bridges.mongo_bridge.collection_structure import CollectionStructure
4 | from toolbox.date_tool import DateTool
5 |
6 |
7 | class YahooDailyTransactionsCollection(CollectionStructure):
8 | def set_name(self):
9 | return 'yahooDailyTransactions'
10 |
11 | def set_unique_fields(self):
12 | return {
13 | 'stockCode': str,
14 | 'year': int,
15 | 'month': int,
16 | 'day': int,
17 | 'intDate': int,
18 | }
19 |
20 | def set_data_fields(self):
21 | return {
22 | 'high': 0.0,
23 | 'low': 0.0,
24 | 'volume': 0,
25 | 'close': 0.0,
26 | 'open': 0.0,
27 | }
28 |
29 |
30 | class YahooDailyTransaction(object):
31 |
32 | def __init__(self, stock: str, year: int, month: int, day: int):
33 | self.document = None
34 | start_period = DateTool.date_to_timestamp(
35 | year=year,
36 | month=month,
37 | day=day
38 | )
39 | end_period = DateTool.date_to_timestamp(
40 | year=year,
41 | month=month,
42 | day=day,
43 | end=True
44 | )
45 | headers = {
46 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) '
47 | 'Chrome/39.0.2171.95 Safari/537.36'
48 | }
49 |
50 | resp = requests.get(
51 | url=f'https://query1.finance.yahoo.com/v8/finance/chart/{stock}',
52 | params={
53 | 'period1': start_period,
54 | 'period2': end_period,
55 | 'interval': '1d',
56 | 'events': 'history',
57 | },
58 | headers=headers
59 | )
60 | resp.encoding = 'utf8'
61 | json_resp = resp.json()
62 | this_day_data = json_resp['chart']['result'][0]['indicators']['quote'][0]
63 | if this_day_data:
64 | self.document = YahooDailyTransactionsCollection().document_operator(
65 | stockCode=stock,
66 | year=year,
67 | month=month,
68 | day=day,
69 | intDate=year*10000+month*100+day,
70 | high=this_day_data['high'][0],
71 | low=this_day_data['low'][0],
72 | volume=this_day_data['volume'][0],
73 | close=this_day_data['close'][0],
74 | open=this_day_data['open'][0]
75 | )
76 |
77 |
78 | def main():
79 | # ^GSPC
80 | new_stock = YahooDailyTransaction('^GSPC', 2022, 1, 2)
81 | print(new_stock.document)
82 | pass
83 |
84 |
85 | if __name__ == '__main__':
86 | main()
--------------------------------------------------------------------------------
/dags/parse_monthly_revenue/parse_monthly_revenue.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import sys
3 | from datetime import datetime
4 | from datetime import timedelta
5 | from functools import wraps
6 |
7 | from airflow.settings import AIRFLOW_HOME
8 | from airflow import DAG
9 | from airflow.operators.python import PythonOperator
10 | from functools import wraps
11 |
12 |
13 | class EnvSetting(object):
14 | PROJECT_HOME = f'{AIRFLOW_HOME}/dags/tw-financial-report-analysis'
15 |
16 | @staticmethod
17 | def append_project_to_path(f):
18 | @wraps(f)
19 | def insert_path(*args, **kwds):
20 | sys.path.insert(0, EnvSetting.PROJECT_HOME)
21 | return f(*args, **kwds)
22 |
23 | return insert_path
24 |
25 |
26 | # 2633 A
27 |
28 | def init_dag(start_date, schedule_interval='30 12 12 * *'):
29 | args = {
30 | 'owner': 'sean',
31 | }
32 | dag = DAG(
33 | dag_id='parse_monthly_revenue',
34 | default_args=args,
35 | max_active_runs=2,
36 | concurrency=2,
37 | schedule_interval=schedule_interval,
38 | start_date=start_date,
39 | )
40 |
41 | @EnvSetting.append_project_to_path
42 | def parse_monthly_revenue(**context):
43 | from airflow.providers.mongo.hooks.mongo import MongoHook
44 |
45 | from reports.monthly_revenue.monthly_revenue import MonthlyRevenue
46 | from reports.monthly_revenue.monthly_revenue import MonthlyRevenueCollection
47 | from toolbox.date_tool import DateTool
48 |
49 | mongo_hook = MongoHook(conn_id='stock_mongo')
50 | stock_db = mongo_hook.get_conn().stock
51 | mr_collection_struct = MonthlyRevenueCollection()
52 | monthly_revenue_collection = mr_collection_struct.bind_db(stock_db)
53 |
54 | next_execution_date = context['next_ds']
55 | target_year, target_month, _ = map(int, next_execution_date.split('-'))
56 | logging.info(f'parsing {target_year}/{target_month} monthly revenue.')
57 |
58 | mr_results = MonthlyRevenue(tw_year=DateTool.to_tw_year(target_year), month=target_month).monthly_revenues
59 |
60 | for result in mr_results:
61 | monthly_revenue_collection.update_one(
62 | filter=mr_collection_struct.get_unique_fields(result),
63 | update={'$set': result},
64 | upsert=True
65 | )
66 |
67 | logging.info(f'{target_year}/{target_month} monthly revenue is finished!')
68 |
69 | parse_monthly_revenue_task = PythonOperator(
70 | task_id='parse_monthly_revenue',
71 | provide_context=True,
72 | python_callable=parse_monthly_revenue,
73 | depends_on_past=True,
74 | retries=3,
75 | retry_delay=timedelta(seconds=30),
76 | dag=dag
77 | )
78 |
79 | parse_monthly_revenue_task
80 |
81 | return dag
82 |
83 |
84 | parse_monthly_revenue_dag = init_dag(start_date=datetime(year=2018, month=12, day=1))
85 |
--------------------------------------------------------------------------------
/reports/monthly_revenue/monthly_revenue.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import requests
3 |
4 | from db_bridges.mongo_bridge.collection_structure import CollectionStructure
5 | from toolbox.date_tool import DateTool
6 |
7 | class MonthlyRevenueCollection(CollectionStructure):
8 | def set_name(self):
9 | return 'monthlyRevenues'
10 |
11 | def set_unique_fields(self):
12 | return {
13 | 'stockCode': str,
14 | 'year': int,
15 | 'month': int,
16 | }
17 |
18 | def set_data_fields(self):
19 | return {
20 | 'company': 'unknown',
21 | 'industrialClass': 'unknown',
22 | 'theMonthlyRevenue': 0.0,
23 | 'exMonthlyRevenue': 0.0,
24 | 'exYearTheMonthlyRevenue': 0.0,
25 | 'mom': 0.0,
26 | 'yoy': 0.0,
27 | 'cumTheMonthlyRevenue': 0.0,
28 | 'cumExYearTheMonthlyRevenue': 0.0,
29 | 'cmocm': 0.0,
30 | 'note': '-'
31 | }
32 |
33 |
34 | class MonthlyRevenue(object):
35 | def __init__(self, tw_year, month):
36 | resp = requests.post(
37 | url='https://mops.twse.com.tw/server-java/FileDownLoad',
38 | data={
39 | 'step': '9',
40 | 'functionName': 'show_file',
41 | 'filePath': '/home/html/nas/t21/sii/',
42 | 'fileName': f't21sc03_{tw_year}_{month}.csv'
43 | }
44 | )
45 | resp.encoding = 'utf8'
46 | self.content = resp.text
47 |
48 | self.monthly_revenues = list()
49 |
50 | def str_to_float(this_str: str):
51 | try:
52 | return float(this_str)
53 | except ValueError:
54 | return 0.0
55 |
56 | for company in resp.text.split('\r\n')[1:-1]:
57 | items = company.replace('"', '').split(',')
58 | tw_year, month = map(int, items[1].split('/'))
59 |
60 | self.monthly_revenues.append(
61 | MonthlyRevenueCollection().document_operator(
62 | stockCode=items[2],
63 | year=DateTool.tw_year_to_year(tw_year),
64 | month=month,
65 | company=items[3],
66 | industrialClass=items[4],
67 | theMonthlyRevenue=str_to_float(items[5]),
68 | exMonthlyRevenue=str_to_float(items[6]),
69 | exYearTheMonthlyRevenue=str_to_float(items[7]),
70 | mom=str_to_float(items[8]),
71 | yoy=str_to_float(items[9]),
72 | cumTheMonthlyRevenue=str_to_float(items[10]),
73 | cumExYearTheMonthlyRevenue=str_to_float(items[11]),
74 | cmocm=str_to_float(items[12]),
75 | note=items[13]
76 | )
77 | )
78 |
79 |
80 | if __name__ == '__main__':
81 | for document in MonthlyRevenue(110, 8).monthly_revenues:
82 | print(document)
--------------------------------------------------------------------------------
/dags/three_days_strategy/three_days_strategy.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import sys
3 | from datetime import datetime
4 | from datetime import timedelta
5 | from functools import wraps
6 |
7 | from airflow.settings import AIRFLOW_HOME
8 | from airflow import DAG
9 | from airflow.operators.python import PythonOperator
10 | from functools import wraps
11 |
12 |
13 | class EnvSetting(object):
14 | PROJECT_HOME = f'{AIRFLOW_HOME}/dags/tw-financial-report-analysis'
15 |
16 | @staticmethod
17 | def append_project_to_path(f):
18 | @wraps(f)
19 | def insert_path(*args, **kwds):
20 | sys.path.insert(0, EnvSetting.PROJECT_HOME)
21 | return f(*args, **kwds)
22 |
23 | return insert_path
24 |
25 |
26 | # 2633 A
27 |
28 | def init_dag(stock_code, start_date, schedule_interval='30 12 1 * *'):
29 | args = {
30 | 'owner': 'sean',
31 | }
32 | dag = DAG(
33 | dag_id=f'crawl_{stock_code}_daily_transaction',
34 | default_args=args,
35 | max_active_runs=2,
36 | concurrency=2,
37 | schedule_interval=schedule_interval,
38 | start_date=start_date,
39 | tags=['stock'],
40 | )
41 |
42 | @EnvSetting.append_project_to_path
43 | def crawl_daily_transaction(**context):
44 | from time import sleep
45 |
46 | from airflow.providers.mongo.hooks.mongo import MongoHook
47 |
48 | from daily_transaction.daily_transaction import DailyTransactionsInMonth
49 | from daily_transaction.daily_transaction import DailyTransactionsCollection
50 |
51 | mongo_hook = MongoHook(conn_id='stock_mongo')
52 | stock_db = mongo_hook.get_conn().stock
53 | dt_collection_struct = DailyTransactionsCollection()
54 | daily_transaction_collection = dt_collection_struct.bind_db(stock_db)
55 |
56 | execution_date = context['ds']
57 | target_year, target_month, _ = map(int, execution_date.split('-'))
58 | logging.info(f'parsing daily stock of {target_year}/{target_month}.')
59 |
60 | dt_results = DailyTransactionsInMonth(stock=stock_code, year=target_year, month=target_month).documents
61 |
62 | for result in dt_results:
63 | daily_transaction_collection.update_one(
64 | filter=dt_collection_struct.get_unique_fields(result),
65 | update={'$set': result},
66 | upsert=True
67 | )
68 |
69 | logging.info(f'sleep 5 second.')
70 | sleep(5)
71 | logging.info(f'{target_year}/{target_month} daily transaction is finished!')
72 |
73 | parse_daily_transaction_task = PythonOperator(
74 | task_id='crawl_daily_transaction',
75 | provide_context=True,
76 | python_callable=crawl_daily_transaction,
77 | depends_on_past=True,
78 | retries=3,
79 | retry_delay=timedelta(seconds=30),
80 | dag=dag
81 | )
82 |
83 | parse_daily_transaction_task
84 |
85 | return dag
86 |
87 |
88 | parse_0050_transaction_dag = init_dag(stock_code='0050', start_date=datetime(year=2018, month=12, day=1))
89 |
--------------------------------------------------------------------------------
/dags/crawl_daily_transaction/crawl_daily_transaction.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import sys
3 | from datetime import datetime
4 | from datetime import timedelta
5 | from functools import wraps
6 |
7 | from airflow.settings import AIRFLOW_HOME
8 | from airflow import DAG
9 | from airflow.operators.python import PythonOperator
10 | from functools import wraps
11 |
12 |
13 | class EnvSetting(object):
14 | PROJECT_HOME = f'{AIRFLOW_HOME}/dags/tw-financial-report-analysis'
15 |
16 | @staticmethod
17 | def append_project_to_path(f):
18 | @wraps(f)
19 | def insert_path(*args, **kwds):
20 | sys.path.insert(0, EnvSetting.PROJECT_HOME)
21 | return f(*args, **kwds)
22 |
23 | return insert_path
24 |
25 |
26 | # 2633 A
27 |
28 | def init_dag(stock_code, start_date, schedule_interval='30 12 * * *'):
29 | args = {
30 | 'owner': 'sean',
31 | }
32 | dag = DAG(
33 | dag_id=f'crawl_{stock_code}_daily_transaction',
34 | default_args=args,
35 | max_active_runs=2,
36 | concurrency=2,
37 | schedule_interval=schedule_interval,
38 | start_date=start_date,
39 | tags=['stock'],
40 | )
41 |
42 | @EnvSetting.append_project_to_path
43 | def crawl_daily_transaction(**context):
44 | from time import sleep
45 |
46 | from airflow.providers.mongo.hooks.mongo import MongoHook
47 |
48 | from daily_transaction.daily_transaction import DailyTransactionsInMonth
49 | from daily_transaction.daily_transaction import DailyTransactionsCollection
50 |
51 | mongo_hook = MongoHook(conn_id='stock_mongo')
52 | stock_db = mongo_hook.get_conn().stock
53 | dt_collection_struct = DailyTransactionsCollection()
54 | daily_transaction_collection = dt_collection_struct.bind_db(stock_db)
55 |
56 | execution_date = context['ds']
57 | target_year, target_month, _ = map(int, execution_date.split('-'))
58 | logging.info(f'parsing daily stock of {target_year}/{target_month}.')
59 |
60 | dt_results = DailyTransactionsInMonth(stock=stock_code, year=target_year, month=target_month).documents
61 |
62 | for result in dt_results:
63 | daily_transaction_collection.update_one(
64 | filter=dt_collection_struct.get_unique_fields(result),
65 | update={'$set': result},
66 | upsert=True
67 | )
68 |
69 | logging.info(f'sleep 5 second.')
70 | sleep(5)
71 | logging.info(f'{target_year}/{target_month} daily transaction is finished!')
72 |
73 | parse_daily_transaction_task = PythonOperator(
74 | task_id='crawl_daily_transaction',
75 | provide_context=True,
76 | python_callable=crawl_daily_transaction,
77 | depends_on_past=True,
78 | retries=3,
79 | retry_delay=timedelta(seconds=30),
80 | dag=dag
81 | )
82 |
83 | parse_daily_transaction_task
84 |
85 | return dag
86 |
87 |
88 | parse_0050_transaction_dag = init_dag(stock_code='0050', start_date=datetime(year=2018, month=12, day=1))
89 |
--------------------------------------------------------------------------------
/daily_transaction/daily_transaction.py:
--------------------------------------------------------------------------------
1 | import requests
2 |
3 | from db_bridges.mongo_bridge.collection_structure import CollectionStructure
4 | from toolbox.date_tool import DateTool
5 |
6 |
7 | class DailyTransactionsCollection(CollectionStructure):
8 | def set_name(self):
9 | return 'dailyTransactions'
10 |
11 | def set_unique_fields(self):
12 | return {
13 | 'stockCode': str,
14 | 'year': int,
15 | 'month': int,
16 | 'day': int,
17 | 'intDate': int,
18 | }
19 |
20 | def set_data_fields(self):
21 | return {
22 | 'tradeVolume': 0,
23 | 'amount': 0,
24 | 'openingPrice': 0.0,
25 | 'highestPrice': 0.0,
26 | 'lowestPrice': 0.0,
27 | 'closingPrice': 0.0,
28 | 'closingDiff': 0.0,
29 | 'transaction': 0,
30 | }
31 |
32 |
33 | class DailyTransactionsInMonth(object):
34 | @staticmethod
35 | def remove_comma_to_int(with_comma: str) -> int:
36 | return int(with_comma.replace(',', ''))
37 |
38 | @staticmethod
39 | def remove_comma_to_float(with_comma: str) -> float:
40 | return float(with_comma.replace(',', ''))
41 |
42 | @staticmethod
43 | def distinguish_sign_to_float(with_sign: str) -> float:
44 | if with_sign[0] == '-':
45 | return -1.0 * float(with_sign[1:])
46 | else:
47 | return float(with_sign[1:])
48 |
49 | def __init__(self, stock: str, year: int, month: int):
50 | self.documents = list()
51 |
52 | resp = requests.get(
53 | url='https://www.twse.com.tw/exchangeReport/STOCK_DAY',
54 | params={
55 | 'response': 'json',
56 | 'date': f'{year}{month:0>2}01',
57 | 'stockNo': stock,
58 | }
59 | )
60 | resp.encoding = 'utf8'
61 | json_resp = resp.json()
62 |
63 | for daily_info in json_resp['data']:
64 | got_tw_year, got_month, got_day = map(int, daily_info[0].split('/'))
65 | got_year = DateTool.tw_year_to_year(got_tw_year)
66 | self.documents.append(
67 | DailyTransactionsCollection().document_operator(
68 | stockCode=stock,
69 | year=got_year,
70 | month=got_month,
71 | day=got_day,
72 | intDate=got_year * 10000 + got_month * 100 + got_day,
73 | tradeVolume=self.__class__.remove_comma_to_int(daily_info[1]),
74 | amount=self.__class__.remove_comma_to_int(daily_info[2]),
75 | openingPrice=self.__class__.remove_comma_to_float(daily_info[3]),
76 | highestPrice=self.__class__.remove_comma_to_float(daily_info[4]),
77 | lowestPrice=self.__class__.remove_comma_to_float(daily_info[5]),
78 | closingPrice=self.__class__.remove_comma_to_float(daily_info[6]),
79 | closingDiff=self.__class__.distinguish_sign_to_float(daily_info[7]),
80 | transaction=self.__class__.remove_comma_to_int(daily_info[8]),
81 | )
82 | )
83 |
84 |
85 | def main():
86 | new_stock = DailyTransactionsInMonth('0050', 2021, 1)
87 | print(new_stock.documents)
88 | pass
89 |
90 |
91 | if __name__ == '__main__':
92 | main()
--------------------------------------------------------------------------------
/reports/financial_reports/financial_report_agent.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import logging
3 |
4 | from bs4 import BeautifulSoup
5 |
6 | from reports.financial_reports.sheet import Sheet
7 | from reports.financial_reports.balance_sheet import BalanceSheet
8 | from reports.financial_reports.comprehensive_income_sheet import ComprehensiveIncomeSheet
9 |
10 |
11 | class FinancialReportAgent(object):
12 | def __new__(
13 | cls,
14 | company_id: str,
15 | year: int,
16 | season: int,
17 | report_type: str
18 | ):
19 | try:
20 | resp = requests.get(
21 | f'https://mops.twse.com.tw/server-java/t164sb01?step=1&'
22 | f'CO_ID={company_id}&'
23 | f'SYEAR={year}&'
24 | f'SSEASON={season}&'
25 | f'REPORT_ID={report_type}')
26 | resp.encoding = 'big5'
27 | soup = BeautifulSoup(resp.text, 'html.parser')
28 |
29 | check_status = soup.find('h4')
30 | # print(type(check_status))
31 | if check_status and check_status.string == '檔案不存在!':
32 | return None
33 | else:
34 | instance = super(FinancialReportAgent, cls).__new__(cls)
35 | instance.__dict__['soup'] = soup
36 | return instance
37 | except Exception as e:
38 | logging.exception(e)
39 |
40 | def __init__(
41 | self,
42 | company_id: str,
43 | year: int,
44 | season: int,
45 | report_type: str,
46 | ):
47 | self.company_id = company_id
48 | self.year = year
49 | self.season = season
50 | self.report_type = report_type
51 | self.balance_sheet = BalanceSheet(self.soup.find('table'))
52 | self.parse_sheet_unit(self.balance_sheet, self.soup)
53 | self.comprehensive_income_sheet = ComprehensiveIncomeSheet(self.balance_sheet.sheet.find_next_sibling('table'))
54 | self.parse_sheet_unit(self.comprehensive_income_sheet, self.soup)
55 |
56 | @staticmethod
57 | def parse_sheet_unit(sheet: Sheet, report_html: BeautifulSoup):
58 | unit_string = report_html.find(
59 | 'div', id=sheet.get_magic_id()
60 | ).find_next(
61 | 'div', 'rptidx'
62 | ).find(
63 | 'span', 'en'
64 | ).string
65 |
66 | if 'thousands' in unit_string:
67 | sheet.set_dollar_unit(1000)
68 | else:
69 | logging.warning(f'Unkown unit: {unit_string}')
70 |
71 | return sheet
72 |
73 |
74 | if __name__ == '__main__':
75 | # search_comprehensive_income_set = {
76 | # 'Total operating revenue',
77 | # 'Total operating costs',
78 | # 'Total basic earnings per share'
79 | # }
80 | fn_report_agent = FinancialReportAgent("2605", 2020, 3, "C")
81 | search_balance_sheet_set = {
82 | 'Total assets',
83 | 'Total current assets',
84 | 'Total non-current assets',
85 | 'Total liabilities',
86 | 'Total current liabilities',
87 | 'Total non-current liabilities',
88 | 'Total equity'
89 | }
90 | balance_sheet_res = fn_report_agent.balance_sheet.parse_items_to_dict(search_balance_sheet_set)
91 | print(balance_sheet_res)
92 | search_comprehensive_income_sheet_set = {
93 | 'Total operating revenue',
94 | 'Total operating costs',
95 | 'Total basic earnings per share'
96 | }
97 | income_res = fn_report_agent.comprehensive_income_sheet.parse_items_to_dict(search_comprehensive_income_sheet_set)
98 | print(income_res)
99 |
--------------------------------------------------------------------------------
/dags/crawl_daily_transaction/crawl_yahoo_daily_transaction.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import sys
3 | from datetime import datetime
4 | from datetime import timedelta
5 | from functools import wraps
6 |
7 | from airflow.settings import AIRFLOW_HOME
8 | from airflow import DAG
9 | from airflow.operators.python import BranchPythonOperator
10 | from airflow.operators.dummy import DummyOperator
11 |
12 |
13 | class EnvSetting(object):
14 | PROJECT_HOME = f'{AIRFLOW_HOME}/dags/tw-financial-report-analysis'
15 |
16 | @staticmethod
17 | def append_project_to_path(f):
18 | @wraps(f)
19 | def insert_path(*args, **kwds):
20 | sys.path.insert(0, EnvSetting.PROJECT_HOME)
21 | return f(*args, **kwds)
22 |
23 | return insert_path
24 |
25 |
26 | def init_dag(stock_code, start_date, schedule_interval='30 12 * * *'):
27 | args = {
28 | 'owner': 'sean',
29 | }
30 | dag = DAG(
31 | dag_id=f'crawl_{stock_code}_yahoo_daily_transaction',
32 | default_args=args,
33 | max_active_runs=2,
34 | concurrency=2,
35 | schedule_interval=schedule_interval,
36 | start_date=start_date,
37 | tags=['stock'],
38 | )
39 |
40 | @EnvSetting.append_project_to_path
41 | def crawl_daily_transaction(**context):
42 | from time import sleep
43 |
44 | from airflow.providers.mongo.hooks.mongo import MongoHook
45 |
46 | from daily_transaction.yahoo_daily_transaction import YahooDailyTransaction
47 | from daily_transaction.yahoo_daily_transaction import YahooDailyTransactionsCollection
48 |
49 | mongo_hook = MongoHook(conn_id='stock_mongo')
50 | stock_db = mongo_hook.get_conn().stock
51 | ydt_collection_struct = YahooDailyTransactionsCollection()
52 | yahoo_daily_transaction_collection = ydt_collection_struct.bind_db(stock_db)
53 |
54 | execution_date = context['ds']
55 | target_year, target_month, target_day = map(int, execution_date.split('-'))
56 | logging.info(f'parsing daily stock of {target_year}/{target_month}/{target_day}.')
57 |
58 | ydt_result = YahooDailyTransaction(
59 | stock=stock_code,
60 | year=target_year,
61 | month=target_month,
62 | day=target_day
63 | ).document
64 | logging.info(f'data: {ydt_result}')
65 |
66 | if ydt_result:
67 | yahoo_daily_transaction_collection.update_one(
68 | filter=ydt_collection_struct.get_unique_fields(ydt_result),
69 | update={'$set': ydt_result},
70 | upsert=True
71 | )
72 | logging.info(f'sleep 10 second.')
73 | sleep(10)
74 | logging.info(f'{target_year}/{target_month}/{target_day} daily transaction is finished!')
75 | return 'done'
76 | else:
77 | return 'no_data'
78 |
79 | parse_daily_transaction_task = BranchPythonOperator(
80 | task_id='crawl_daily_transaction',
81 | provide_context=True,
82 | python_callable=crawl_daily_transaction,
83 | depends_on_past=True,
84 | retries=3,
85 | retry_delay=timedelta(seconds=30),
86 | dag=dag
87 | )
88 |
89 | no_data_task = DummyOperator(
90 | task_id='no_data',
91 | dag=dag
92 | )
93 |
94 | done_task = DummyOperator(
95 | task_id='done',
96 | dag=dag
97 | )
98 |
99 | parse_daily_transaction_task >> [no_data_task, done_task]
100 |
101 | return dag
102 |
103 |
104 | parse_0050_transaction_dag = init_dag(stock_code='0050.TW', start_date=datetime(year=2018, month=12, day=1))
105 |
--------------------------------------------------------------------------------
/tests/reports/financial_reports/test_financial_report_agent.py:
--------------------------------------------------------------------------------
1 | from reports.financial_reports.financial_report_agent import FinancialReportAgent
2 | import unittest
3 | from unittest import mock
4 |
5 | FINANCIAL_REPORT_RESOURCE_PATH = './tests/reports/financial_reports/resources'
6 |
7 |
8 | class FinancialReportAgentTestCase(unittest.TestCase):
9 |
10 | def mocked_requests_get(*args, **kwargs):
11 | class MockResponse(object):
12 | def __init__(self, text):
13 | self.encoding = 'big5'
14 | self.text = text
15 |
16 | if args[0] == (f'https://mops.twse.com.tw/server-java/t164sb01?step=1&'
17 | f'CO_ID=6666&'
18 | f'SYEAR=2021&'
19 | f'SSEASON=4&'
20 | f'REPORT_ID=C'):
21 |
22 | with open(
23 | f'{FINANCIAL_REPORT_RESOURCE_PATH}/mock_financial_report_success_example.html',
24 | 'r',
25 | encoding='big5'
26 | ) as f:
27 | success_html = f.read()
28 | return MockResponse(text=success_html)
29 | elif args[0] == (f'https://mops.twse.com.tw/server-java/t164sb01?step=1&'
30 | f'CO_ID=6666&'
31 | f'SYEAR=2021&'
32 | f'SSEASON=5&'
33 | f'REPORT_ID=C'):
34 |
35 | with open(
36 | f'{FINANCIAL_REPORT_RESOURCE_PATH}/mock_financial_report_fail_example.html',
37 | 'r',
38 | encoding='big5'
39 | ) as f:
40 | fail_html = f.read()
41 | return MockResponse(text=fail_html)
42 |
43 | @mock.patch('requests.get', side_effect=mocked_requests_get)
44 | def test_get_financial_report_successfully(self, mock_get):
45 | agent = FinancialReportAgent(company_id='6666',
46 | year=2021,
47 | season=4,
48 | report_type='C')
49 |
50 | search_balance_sheet_set_us = {'Total assets'}
51 | search_balance_sheet_set_tw = {'資產總計'}
52 | us_result = agent.balance_sheet.parse_items_to_dict(search_balance_sheet_set_us, {2: ''})
53 | tw_result = agent.balance_sheet.parse_items_to_dict(search_balance_sheet_set_tw, {2: ''})
54 |
55 | self.assertIsNotNone(agent)
56 | self.assertIn(mock.call(f'https://mops.twse.com.tw/server-java/t164sb01?step=1&'
57 | f'CO_ID=6666&'
58 | f'SYEAR=2021&'
59 | f'SSEASON=4&'
60 | f'REPORT_ID=C'), mock_get.call_args_list)
61 |
62 | # test parsing unit
63 | self.assertEqual(agent.balance_sheet.dollar_unit, 1000)
64 | # test parsing column
65 | self.assertEqual(us_result['totalAssets'], tw_result['資產總計'])
66 | # test parsing result
67 | self.assertEqual(us_result['totalAssets'], 5564612)
68 |
69 | @mock.patch('requests.get', side_effect=mocked_requests_get)
70 | def test_get_financial_report_when_file_is_not_exist_unsuccessfully(self, mock_get):
71 | agent = FinancialReportAgent(company_id='6666',
72 | year=2021,
73 | season=5,
74 | report_type='C')
75 | self.assertIsNone(agent)
76 | self.assertIn(mock.call(f'https://mops.twse.com.tw/server-java/t164sb01?step=1&'
77 | f'CO_ID=6666&'
78 | f'SYEAR=2021&'
79 | f'SSEASON=5&'
80 | f'REPORT_ID=C'), mock_get.call_args_list)
81 |
82 |
83 | if __name__ == '__main__':
84 | unittest.main()
85 |
--------------------------------------------------------------------------------
/for_setup_airlfow/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | #
18 |
19 | # Basic Airflow cluster configuration for CeleryExecutor with Redis and PostgreSQL.
20 | #
21 | # WARNING: This configuration is for local development. Do not use it in a production deployment.
22 | #
23 | # This configuration supports basic configuration using environment variables or an .env file
24 | # The following variables are supported:
25 | #
26 | # AIRFLOW_IMAGE_NAME - Docker image name used to run Airflow.
27 | # Default: apache/airflow:master-python3.8
28 | # AIRFLOW_UID - User ID in Airflow containers
29 | # Default: 50000
30 | # AIRFLOW_GID - Group ID in Airflow containers
31 | # Default: 50000
32 | # _AIRFLOW_WWW_USER_USERNAME - Username for the administrator account.
33 | # Default: airflow
34 | # _AIRFLOW_WWW_USER_PASSWORD - Password for the administrator account.
35 | # Default: airflow
36 | #
37 | # Feel free to modify this file to suit your needs.
38 | ---
39 | version: '3'
40 | x-airflow-common:
41 | &airflow-common
42 | image: ${AIRFLOW_IMAGE_NAME:-apache/airflow:2.1.3-python3.8}
43 | environment:
44 | &airflow-common-env
45 | AIRFLOW__CORE__EXECUTOR: CeleryExecutor
46 | AIRFLOW__CORE__SQL_ALCHEMY_CONN: postgresql+psycopg2://airflow:airflow@postgres/airflow
47 | AIRFLOW__CELERY__RESULT_BACKEND: db+postgresql://airflow:airflow@postgres/airflow
48 | AIRFLOW__CELERY__BROKER_URL: redis://:@redis:6379/0
49 | AIRFLOW__CORE__FERNET_KEY: ''
50 | AIRFLOW__CORE__DAGS_ARE_PAUSED_AT_CREATION: 'true'
51 | AIRFLOW__CORE__LOAD_EXAMPLES: 'false'
52 | volumes:
53 | - ./dags:/opt/airflow/dags
54 | - ./logs:/opt/airflow/logs
55 | - ./plugins:/opt/airflow/plugins
56 | user: "${AIRFLOW_UID:-50000}:${AIRFLOW_GID:-50000}"
57 | depends_on:
58 | redis:
59 | condition: service_healthy
60 | postgres:
61 | condition: service_healthy
62 |
63 | services:
64 | mongo:
65 | image: mongo
66 | hostname: stock_mongo
67 | restart: always
68 | ports:
69 | - 27017:27017
70 | environment:
71 | MONGO_INITDB_ROOT_USERNAME: root
72 | MONGO_INITDB_ROOT_PASSWORD: example
73 |
74 | postgres:
75 | image: postgres:13
76 | environment:
77 | POSTGRES_USER: airflow
78 | POSTGRES_PASSWORD: airflow
79 | POSTGRES_DB: airflow
80 | volumes:
81 | - postgres-db-volume:/var/lib/postgresql/data
82 | healthcheck:
83 | test: ["CMD", "pg_isready", "-U", "airflow"]
84 | interval: 5s
85 | retries: 5
86 | restart: always
87 |
88 | redis:
89 | image: redis:latest
90 | ports:
91 | - 6379:6379
92 | healthcheck:
93 | test: ["CMD", "redis-cli", "ping"]
94 | interval: 5s
95 | timeout: 30s
96 | retries: 50
97 | restart: always
98 |
99 | airflow-webserver:
100 | <<: *airflow-common
101 | command: webserver
102 | ports:
103 | - 8080:8080
104 | healthcheck:
105 | test: ["CMD", "curl", "--fail", "http://localhost:8080/health"]
106 | interval: 10s
107 | timeout: 10s
108 | retries: 5
109 | restart: always
110 |
111 | airflow-scheduler:
112 | <<: *airflow-common
113 | command: scheduler
114 | restart: always
115 |
116 | airflow-worker:
117 | <<: *airflow-common
118 | command: celery worker
119 | restart: always
120 |
121 | airflow-init:
122 | <<: *airflow-common
123 | command: version
124 | environment:
125 | <<: *airflow-common-env
126 | _AIRFLOW_DB_UPGRADE: 'true'
127 | _AIRFLOW_WWW_USER_CREATE: 'true'
128 | _AIRFLOW_WWW_USER_USERNAME: ${_AIRFLOW_WWW_USER_USERNAME:-airflow}
129 | _AIRFLOW_WWW_USER_PASSWORD: aLrfIow
130 |
131 | flower:
132 | <<: *airflow-common
133 | command: celery flower
134 | ports:
135 | - 5555:5555
136 | healthcheck:
137 | test: ["CMD", "curl", "--fail", "http://localhost:5555/"]
138 | interval: 10s
139 | timeout: 10s
140 | retries: 5
141 | restart: always
142 |
143 | volumes:
144 | postgres-db-volume:
145 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # tw-financial-report-analysis
2 |
3 | 遲早都要分析財報,怎麼不一開始就自己分析?
4 |
5 | 這個專案希望能提供一個可以快速上手的財報分析系統樣板。此系統樣板可以分成三個主要單元:
6 |
7 | * `dags(Airflow)`:數據收集,排程分析。
8 | * `reports` Modules:財報解析。
9 | * `web`:視覺化數據。
10 |
11 | ## 已完成項目
12 | * 財報定期抓取
13 | * 資產負載表
14 | * 綜合損益表
15 | * 每月營業收入
16 | * 指標
17 | * ROE
18 | * ROA
19 | * 每股淨值(bookValuePerShare)
20 | * EPS(totalBasicEarningsPerShare)
21 | * 財報公佈日期(publishedDate)
22 | * 視覺化
23 | * ROA and ROE
24 |
25 | ## Get Started!
26 |
27 | ### 環境安裝
28 |
29 | 在家目錄下安裝:
30 | ```bash
31 | $ cd ~
32 | $ mkdir airflow
33 | $ cd airflow
34 | $ curl -LfO 'https://github.com/YanHaoChen/tw-financial-report-analysis/raw/main/for_setup_airlfow/docker-compose.yaml'
35 | $ mkdir ./dags ./logs ./plugins
36 | $ echo -e "AIRFLOW_UID=$(id -u)\nAIRFLOW_GID=0" > .env
37 | $ docker-compose up airflow-init
38 | $ docker-compose up -d
39 | ```
40 |
41 | ### 建立 mongo 使用者
42 |
43 | ```bash
44 | $ docker exec -it airflow-mongo-1 bash
45 | $ mongosh -u root -p example
46 |
47 | > use stock
48 | > db.createUser(
49 | {
50 | user:"airflower",
51 | pwd: "money",
52 | roles:[
53 | { role: "readWrite", db: "stock" }
54 | ]
55 | }
56 | )
57 |
58 | > exit
59 | $ exit
60 | ```
61 | ### 建立 Mongo Connection
62 | 在建立之前,先讓 Airflow Webserver 新增 Mongo 的 Connection Type。
63 | ```
64 | $ docker exec -it airflow-airflow-webserver-1 pip3 install apache-airflow-providers-mongo==2.0.0
65 |
66 | # 刷新 Airflow Web
67 | $ docker-compose restart
68 | ```
69 | 接下來,連進 Airflow Webserver `127.0.0.1:8080`。點選 Admin -> Connections -> 點選加號(Add a new record)。再照以下項目填寫:
70 |
71 | * Conn Id: stock_mongo
72 | * Conn Type: MongoDB
73 | * Host: stock_mongo
74 | * Schema: stock
75 | * Login: airflower
76 | * Password: money
77 | * Port: 27017
78 |
79 | > Airflow Webserver 的帳號密碼如下:
80 | > account: airflow
81 | > password: aLrfIow
82 |
83 | ### 把檔案導入 `dags`
84 | 在把專案放進 `dags` 前,先把 `airflowignore.template` 放進去。
85 |
86 | ```bash
87 | $ cd ./dags
88 | $ curl -LfO 'https://github.com/YanHaoChen/tw-financial-report-analysis/raw/main/for_setup_airlfow/airflowignore.template'
89 | $ mv airflowignore.template .airflowignore
90 | ```
91 | 現在把可以把專案拉下來囉!
92 | ```bash
93 | $ git clone https://github.com/YanHaoChen/tw-financial-report-analysis.git
94 | ```
95 | 現在回到 Airflow Webserver, 等 3~5 分鐘就可以看到這個專案裡的拉報表的 DAG 囉!
96 |
97 | ### 初始化專案
98 |
99 | 在 Airflow Webserver 上,開啟 `setup_parse_financial_report` DAG。把所需 package 在 Worker 上安裝好。
100 |
101 | ### 開始拉報表囉!
102 |
103 | 在 Airflow Webserver 上,開啟 `stock_2633`。檢查是否有資料導入 Mongo:
104 | ```bash
105 | $ docker exec -it airflow_mongo_1 bash
106 | $ mongosh -u airflower -p money stock
107 | stock> db.financialReports.find({})
108 | [
109 | {
110 | _id: ObjectId("612a16f0163eec9d5d34d670"),
111 | stockCode: 2633,
112 | year: 2021,
113 | season: 2,
114 | yearAndSeason: 20212,
115 | publishedDate: ISODate("2021-08-05T08:24:03.000Z"),
116 | balanceSheetUnit: 1000,
117 | bookValuePerShare: 11.7343,
118 | comprehensiveIncomeSheetUnit: 1000,
119 | netWorth: 66044317,
120 | ordinaryShare: 56282930,
121 | roa: 0.12,
122 | roe: 0.72,
123 | shares: 5628293,
124 | totalAssets: 425359870,
125 | totalBasicEarningsPerShare: 0.09,
126 | totalComprehensiveIncome: 493284,
127 | totalCurrentAssets: 42588522,
128 | totalCurrentLiabilities: 18949504,
129 | totalEquity: 66044317,
130 | totalLiabilities: 359315553,
131 | totalNonCurrentAssets: 382771348,
132 | totalNonCurrentLiabilities: 340366049,
133 | totalOperatingCosts: 6459969,
134 | totalOperatingRevenue: 6101721
135 | }
136 | ]
137 | ```
138 |
139 | ### 新增其他公司財報
140 | 1. 先到以下網址,查詢欲新增的公司。
141 |
142 | [公開資訊觀測站-資產負債表查詢](https://mops.twse.com.tw/mops/web/t164sb03)
143 |
144 | 2. 取得欲新增公司的財報類型。
145 |
146 | 點選 「投資人若需了解更詳細資訊可至XBRL資訊平台或電子書查詢」中的`XBRL資訊平台`。透過 URL 就可以知道財報的種類。
147 | ```
148 | # 以 2207 為例,財報類型為: REPORT_ID=C
149 | https://mops.twse.com.tw/server-java/t164sb01?step=1&CO_ID=2207&SYEAR=2021&SSEASON=2&REPORT_ID=C
150 | ```
151 | 3. 新增對應 DAG。
152 | 至檔案 `dags/parse_financial_report/parse_financial_report.py` 的最下方,加入以下程式碼即可:
153 | ```python
154 | ...
155 | stock_2633 = init_dag(
156 | 'stock_2633',
157 | stock_code=2633,
158 | report_type='A',
159 | start_date=datetime(year=2019, month=4, day=1),
160 | schedule_interval='1 0 * * *',
161 | )
162 |
163 | stock_5283 = init_dag(
164 | 'stock_5283',
165 | stock_code=5283,
166 | report_type='C',
167 | start_date=datetime(year=2019, month=4, day=1),
168 | schedule_interval='2 0 * * *',
169 | )
170 |
171 | stock_2207 = init_dag(
172 | 'stock_2207',
173 | stock_code=2207,
174 | report_type='C',
175 | start_date=datetime(year=2019, month=4, day=1),
176 | schedule_interval='3 0 * * *',
177 | )
178 |
179 | ```
180 | > 目前規劃抓取 2019 年第一季以後的非金融財報格式,所以 `start_date` 需大於 2019-04-01 才能正確抓取,也暫時無法抓取銀行財報。
181 |
182 | ### 看到圖表比較有感覺嗎? 那你可以試試這個
183 |
184 | 在 `web` 資料夾中,放了一個簡易 flask + plotly 的範例,來呈現 ROA 和 ROE。其執行方式,如下:
185 |
186 | ```bash
187 | # 至專案目錄
188 | $ cd ~/airflow/dags/tw-financial-report-analysis/
189 |
190 | # 安裝相關套件
191 | $ pip3 install -r requirements.txt
192 |
193 | # 至 web 目錄下,並執行以下指令
194 | $ cd web
195 | $ flask run [±main ●]
196 | * Environment: production
197 | WARNING: This is a development server. Do not use it in a production deployment.
198 | Use a production WSGI server instead.
199 | * Debug mode: off
200 | * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
201 | ```
202 |
203 | 現在,你可以透過 [127.0.0.1:5000](http://127.0.0.1:5000/) 看到 ROA 及 ROE 的圖表囉!
204 |
205 |
206 |
207 | ## 財報
208 |
209 | ### 欄位對應
210 |
211 | 同 XBRL 資訊平台上的英文版欄位名稱。例如:
212 |
213 | | XBRL 資訊平台上的英文版欄位 | Mongo 中對欄位名稱 |
214 | | --- | --- |
215 | | Total assets | totalAssets |
216 |
217 | 某些欄位最會加上前綴 `cumulative` 表示是從當年年初`累計`至當季的意思。
218 |
219 | | XBRL 資訊平台上的英文版欄位 | Mongo 中對欄位名稱 |
220 | | --- | --- |
221 | | Total Comprehensive Income | cumulativeTotalComprehensiveIncome |
222 |
223 | ## 每月營收
224 |
225 | ### 欄位對應
226 | | 欄位名稱 | 敘述 |
227 | | --- | --- |
228 | | stockCode | 公司代號 |
229 | | year | 報表年份 |
230 | | month | 報表月份 |
231 | | company | 公司代號 |
232 | | industrialClass | 產業別 |
233 | | theMonthlyRevenue | 營業收入-當月營收 |
234 | | exMonthlyRevenue | 營業收入-上月營收 |
235 | | exYearTheMonthlyRevenue | 營業收入-去年當月營收 |
236 | | mom |營業收入-上月比較增減(%) |
237 | | yoy | 營業收入-去年同月增減(%) |
238 | | cumTheMonthlyRevenue | 累計營業收入-當月累計營收 |
239 | | cumExYearTheMonthlyRevenue | 累計營業收入-去年累計營收 |
240 | | cmocm | 累計營業收入-前期比較增減(%) |
241 | | note | 備註 |
242 |
--------------------------------------------------------------------------------
/dags/parse_financial_report/parse_financial_report.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from datetime import datetime
3 | import logging
4 | from functools import wraps
5 |
6 | from airflow.settings import AIRFLOW_HOME
7 | from airflow import DAG
8 | from airflow.operators.python import BranchPythonOperator
9 | from airflow.operators.dummy import DummyOperator
10 | from functools import wraps
11 |
12 |
13 | class EnvSetting(object):
14 | PROJECT_HOME = f'{AIRFLOW_HOME}/dags/tw-financial-report-analysis'
15 |
16 | @staticmethod
17 | def append_project_to_path(f):
18 | @wraps(f)
19 | def insert_path(*args, **kwds):
20 | sys.path.insert(0, EnvSetting.PROJECT_HOME)
21 | return f(*args, **kwds)
22 |
23 | return insert_path
24 |
25 |
26 | # 2633 A
27 |
28 | def init_dag(dag_id, stock_code, report_type, start_date, schedule_interval='0 0 27 * *'):
29 | args = {
30 | 'owner': 'sean',
31 | }
32 | dag = DAG(
33 | dag_id=dag_id,
34 | default_args=args,
35 | max_active_runs=1,
36 | concurrency=1,
37 | schedule_interval=schedule_interval,
38 | start_date=start_date,
39 | )
40 |
41 | @EnvSetting.append_project_to_path
42 | def check_report_in_mongo(code, **context):
43 | from airflow.providers.mongo.hooks.mongo import MongoHook
44 |
45 | from toolbox.date_tool import DateTool
46 |
47 | mongo_hook = MongoHook(conn_id='stock_mongo')
48 | stock_db = mongo_hook.get_conn().stock
49 | execution_date = context['ds']
50 | year, month, day = map(int, execution_date.split('-'))
51 | season_year, season = DateTool.date_to_ex_year_and_season(year, month)
52 | upload_key = {
53 | 'stockCode': code,
54 | 'year': season_year,
55 | 'season': season,
56 | 'yearAndSeason': season_year * 10 + season
57 | }
58 | has_report = stock_db.financialReports.find_one(upload_key)
59 | if has_report:
60 | return 'report_already_in_mongo'
61 | else:
62 | return 'check_report_released'
63 |
64 | check_report_in_mongo_task = BranchPythonOperator(
65 | task_id='check_report_in_mongo',
66 | python_callable=check_report_in_mongo,
67 | op_kwargs={
68 | 'code': stock_code,
69 | },
70 | provide_context=True,
71 | dag=dag,
72 | )
73 |
74 | report_already_in_mongo_task = DummyOperator(
75 | task_id='report_already_in_mongo',
76 | dag=dag
77 | )
78 |
79 | @EnvSetting.append_project_to_path
80 | def check_report_released(code, **context):
81 | import requests
82 | from time import sleep
83 | from datetime import datetime
84 | import pytz
85 |
86 | from airflow.providers.mongo.hooks.mongo import MongoHook
87 | from bs4 import BeautifulSoup
88 |
89 | from toolbox.date_tool import DateTool
90 |
91 | mongo_hook = MongoHook(conn_id='stock_mongo')
92 | stock_db = mongo_hook.get_conn().stock
93 | execution_date = context['ds']
94 | year, month, day = map(int, execution_date.split('-'))
95 | season_year, season = DateTool.date_to_ex_year_and_season(year, month)
96 | tw_year = DateTool.to_tw_year(season_year)
97 |
98 | resp = requests.get(
99 | f'https://doc.twse.com.tw/server-java/t57sb01?step=1&colorchg=1&'
100 | f'co_id={code}&'
101 | f'year={tw_year}&'
102 | f'seamon={season}&'
103 | f'mtype=A')
104 | resp.encoding = 'big5'
105 | soup = BeautifulSoup(resp.text, 'html.parser')
106 |
107 | logging.info(f'sleep 5 seconds.')
108 | sleep(5)
109 |
110 | if soup.h4 and soup.h4.text == '查無所需資料':
111 | return 'the_report_is_not_exist'
112 |
113 | published_date_str = soup.center.table.table.find(attrs={'align': 'cetern'}).text
114 | published_tw_year, *others = published_date_str.split('/')
115 | published_year = DateTool.tw_year_to_year(int(published_tw_year))
116 | tw_date_str = '/'.join([str(published_year)] + others)
117 | published_date = datetime.strptime(tw_date_str, '%Y/%m/%d %H:%M:%S')
118 | timezone = pytz.timezone('Asia/Taipei')
119 | published_date = timezone.localize(published_date)
120 | upload_data = {
121 | 'stockCode': code,
122 | 'year': season_year,
123 | 'season': season,
124 | 'yearAndSeason': season_year * 10 + season,
125 | 'publishedDate': published_date
126 | }
127 | stock_db.financialReports.insert(upload_data)
128 |
129 | return 'load_report_to_mongo'
130 |
131 | check_report_released_task = BranchPythonOperator(
132 | task_id='check_report_released',
133 | python_callable=check_report_released,
134 | op_kwargs={
135 | 'code': stock_code,
136 | },
137 | provide_context=True,
138 | trigger_rule='none_failed_or_skipped',
139 | dag=dag,
140 | )
141 |
142 | the_report_is_not_exist_task = DummyOperator(
143 | task_id='the_report_is_not_exist',
144 | dag=dag
145 | )
146 |
147 | @EnvSetting.append_project_to_path
148 | def load_report_to_mongo_by_stock_code(code, r_type, **context):
149 | from time import sleep
150 |
151 | from reports.financial_reports.financial_report_agent import FinancialReportAgent
152 | from toolbox.date_tool import DateTool
153 | from airflow.providers.mongo.hooks.mongo import MongoHook
154 | mongo_hook = MongoHook(conn_id='stock_mongo')
155 | stock_db = mongo_hook.get_conn().stock
156 | execution_date = context['ds']
157 | year, month, day = map(int, execution_date.split('-'))
158 | season_year, season = DateTool.date_to_ex_year_and_season(year, month)
159 | fn_report_agent = FinancialReportAgent(code, season_year, season, r_type)
160 | upload_key = {
161 | 'stockCode': code,
162 | 'year': season_year,
163 | 'season': season,
164 | 'yearAndSeason': season_year * 10 + season,
165 | }
166 | upload_data = {}
167 |
168 | logging.info(f'sleep 5 seconds.')
169 | sleep(5)
170 |
171 | if not fn_report_agent:
172 | return 'cant_get_the_report'
173 |
174 | ''' Balance Sheet '''
175 | search_balance_sheet_set = {
176 | 'Total assets',
177 | 'Total current assets',
178 | 'Total non-current assets',
179 | 'Total liabilities',
180 | 'Total current liabilities',
181 | 'Total non-current liabilities',
182 | 'Total equity',
183 | 'Ordinary share'
184 | }
185 | balance_sheet_res = fn_report_agent.balance_sheet.parse_items_to_dict(search_balance_sheet_set)
186 | upload_data.update(balance_sheet_res)
187 | # record the unit of Balance Sheet
188 | upload_data.update(
189 | {
190 | 'balanceSheetUnit': fn_report_agent.balance_sheet.dollar_unit
191 | }
192 | )
193 |
194 | ''' Comprehensive Income Sheet '''
195 | search_comprehensive_income_sheet_set = {
196 | 'Total operating revenue',
197 | 'Total operating costs',
198 | 'Total comprehensive income',
199 | 'Total basic earnings per share',
200 | }
201 |
202 | if season == 3:
203 | income_parse_columns = {
204 | 1: '',
205 | 3: 'cumulative'
206 | }
207 | elif season == 4:
208 | income_parse_columns = {
209 | 1: 'cumulative',
210 | }
211 | else:
212 | income_parse_columns = {
213 | 1: '',
214 | }
215 |
216 | income_res = fn_report_agent.comprehensive_income_sheet.parse_items_to_dict(
217 | item_set=search_comprehensive_income_sheet_set,
218 | columns=income_parse_columns
219 | )
220 | upload_data.update(income_res)
221 |
222 | # Record the unit of Comprehensive Income Sheet
223 | upload_data.update(
224 | {
225 | 'comprehensiveIncomeSheetUnit': fn_report_agent.comprehensive_income_sheet.dollar_unit
226 | }
227 | )
228 |
229 | ex_season_report = stock_db.financialReports.find_one({
230 | 'stockCode': code,
231 | 'yearAndSeason': DateTool.season_to_ex_year_and_season_int(season_year * 10 + season),
232 | })
233 |
234 | if ex_season_report:
235 | if season == 4:
236 | print(ex_season_report['yearAndSeason'])
237 | upload_data['totalComprehensiveIncome'] = (
238 | upload_data.get('cumulativeTotalComprehensiveIncome') -
239 | ex_season_report.get('cumulativeTotalComprehensiveIncome'))
240 | print(upload_data['totalComprehensiveIncome'])
241 |
242 | avg_total_asset = (ex_season_report.get('totalAssets', 1) + upload_data.get('totalAssets', 1)) / 2
243 | avg_total_equity = (ex_season_report.get('totalEquity', 1) + upload_data.get('totalEquity', 1)) / 2
244 |
245 | else:
246 | avg_total_asset = upload_data.get('totalAssets', 1)
247 | avg_total_equity = upload_data.get('totalEquity', 1)
248 |
249 | single_season_net_income = upload_data.get('totalComprehensiveIncome', 0)
250 |
251 | ''' compute ROA, ROE and Book Value Per Share '''
252 | roa = round(single_season_net_income / avg_total_asset * 100, 2)
253 | roe = round(single_season_net_income / avg_total_equity * 100, 2)
254 | assets = upload_data.get('totalAssets', 0)
255 | liabilities = upload_data.get('totalLiabilities', 0)
256 | net_worth = assets - liabilities
257 | shares = (upload_data.get('ordinaryShare', 0) / 10)
258 | book_value_per_share = (net_worth / shares) if shares > 0 else 0
259 |
260 | upload_data.update(
261 | {
262 | 'roa': roa,
263 | 'roe': roe,
264 | 'netWorth': net_worth,
265 | 'shares': shares,
266 | 'bookValuePerShare': round(book_value_per_share, 4),
267 | }
268 | )
269 |
270 | stock_db.financialReports.update(
271 | upload_key,
272 | {
273 | "$set": upload_data
274 | },
275 | upsert=True
276 | )
277 |
278 | return 'done'
279 |
280 | load_report_to_mongo_task = BranchPythonOperator(
281 | task_id='load_report_to_mongo',
282 | python_callable=load_report_to_mongo_by_stock_code,
283 | op_kwargs={
284 | 'code': stock_code,
285 | 'r_type': report_type
286 | },
287 | trigger_rule='none_failed_or_skipped',
288 | provide_context=True,
289 | dag=dag,
290 | )
291 |
292 | cant_get_the_report_task = DummyOperator(
293 | task_id='cant_get_the_report',
294 | dag=dag
295 | )
296 |
297 | done_task = DummyOperator(
298 | task_id='done',
299 | dag=dag
300 | )
301 | check_report_in_mongo_task >> [report_already_in_mongo_task, check_report_released_task]
302 | check_report_released_task >> [the_report_is_not_exist_task, load_report_to_mongo_task]
303 | load_report_to_mongo_task >> [cant_get_the_report_task, done_task]
304 |
305 | return dag
306 |
307 |
308 | stock_2633 = init_dag(
309 | 'stock_2633',
310 | stock_code=2633,
311 | report_type='A',
312 | start_date=datetime(year=2019, month=4, day=1),
313 | schedule_interval='1 0 * * *',
314 | )
315 |
316 | stock_5283 = init_dag(
317 | 'stock_5283',
318 | stock_code=5283,
319 | report_type='C',
320 | start_date=datetime(year=2019, month=4, day=1),
321 | schedule_interval='2 0 * * *',
322 | )
323 |
324 | stock_2207 = init_dag(
325 | 'stock_2207',
326 | stock_code=2207,
327 | report_type='C',
328 | start_date=datetime(year=2019, month=4, day=1),
329 | schedule_interval='3 0 * * *',
330 | )
331 |
--------------------------------------------------------------------------------
/lab/experiment1/.ipynb_checkpoints/three_days_strategy-checkpoint.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 2,
6 | "id": "10c819c0",
7 | "metadata": {},
8 | "outputs": [],
9 | "source": [
10 | "from pymongo import MongoClient\n",
11 | "from pymongo import DESCENDING\n",
12 | "\n",
13 | "from urllib.parse import quote_plus"
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": 3,
19 | "id": "a06c39d0",
20 | "metadata": {},
21 | "outputs": [],
22 | "source": [
23 | "uri = \"mongodb://%s:%s@%s/?authSource=stock\" % (\n",
24 | " quote_plus('airflower'), quote_plus('money'), 'localhost')\n",
25 | "client = MongoClient(uri)"
26 | ]
27 | },
28 | {
29 | "cell_type": "code",
30 | "execution_count": 4,
31 | "id": "47d1ac75",
32 | "metadata": {},
33 | "outputs": [],
34 | "source": [
35 | "results = list(client.stock.dailyTransactions.find({'stockCode': '0050'}).sort('intDate', DESCENDING))"
36 | ]
37 | },
38 | {
39 | "cell_type": "code",
40 | "execution_count": 5,
41 | "id": "06d99ba7",
42 | "metadata": {},
43 | "outputs": [
44 | {
45 | "name": "stdout",
46 | "output_type": "stream",
47 | "text": [
48 | "{'_id': ObjectId('6188f926bc1c0ea656d5b1b5'), 'day': 29, 'intDate': 20211029, 'month': 10, 'stockCode': '0050', 'year': 2021, 'amount': 699434063, 'closingDiff': -1.35, 'closingPrice': 135.8, 'highestPrice': 137.05, 'lowestPrice': 135.35, 'openingPrice': 137.05, 'tradeVolume': 5145743, 'transaction': 6484} {'_id': ObjectId('6188f926bc1c0ea656d5b1b3'), 'day': 28, 'intDate': 20211028, 'month': 10, 'stockCode': '0050', 'year': 2021, 'amount': 630055512, 'closingDiff': -0.4, 'closingPrice': 137.15, 'highestPrice': 137.65, 'lowestPrice': 136.6, 'openingPrice': 137.45, 'tradeVolume': 4597622, 'transaction': 5081}\n"
49 | ]
50 | }
51 | ],
52 | "source": [
53 | "print(results[0], results[1])"
54 | ]
55 | },
56 | {
57 | "cell_type": "code",
58 | "execution_count": 23,
59 | "id": "fdca3755",
60 | "metadata": {},
61 | "outputs": [],
62 | "source": [
63 | "def total_rise(days):\n",
64 | " count = 0\n",
65 | " for day in days:\n",
66 | " count += 1 if day['closingDiff'] > 0 else 0\n",
67 | " \n",
68 | " return count\n",
69 | "\n",
70 | "data = [ \n",
71 | " {\n",
72 | " # target\n",
73 | " 'dDayPriseRise': 1 if results[i]['closingDiff'] > 0 else 0,\n",
74 | " 'dDayClosingDiff': results[i]['closingDiff'],\n",
75 | " # summary\n",
76 | " # 'totalRise': total_rise(results[i+1:i+3]),\n",
77 | " # day1 columns\n",
78 | " 'd1TradeVolume': results[i+1]['tradeVolume'],\n",
79 | " 'd1Amount': results[i+1]['amount'],\n",
80 | " 'd1OpeningPrice': results[i+1]['openingPrice'],\n",
81 | " 'd1AgoHighestPrice': results[i+1]['highestPrice'],\n",
82 | " 'd1AgoLowestPrice': results[i+1]['lowestPrice'],\n",
83 | " 'd1AgoClosingPrice': results[i+1]['closingPrice'],\n",
84 | " 'd1AgoClosingDiff': results[i+1]['closingDiff'],\n",
85 | " 'd1AgoTransaction': results[i+1]['transaction'],\n",
86 | " 'd1AgoMaxDiff': round(results[i+1]['highestPrice'] - results[i+1]['lowestPrice'], 2),\n",
87 | " 'd1DayPriseRise': 1 if results[i+1]['closingDiff'] > 0 else 0,\n",
88 | " }\n",
89 | " for i in range(0, len(results)-3)\n",
90 | "]"
91 | ]
92 | },
93 | {
94 | "cell_type": "code",
95 | "execution_count": 24,
96 | "id": "aac0f0c0",
97 | "metadata": {},
98 | "outputs": [],
99 | "source": [
100 | "import pandas as pd"
101 | ]
102 | },
103 | {
104 | "cell_type": "code",
105 | "execution_count": 25,
106 | "id": "28d2f155",
107 | "metadata": {},
108 | "outputs": [],
109 | "source": [
110 | "df = pd.DataFrame(data)"
111 | ]
112 | },
113 | {
114 | "cell_type": "code",
115 | "execution_count": 19,
116 | "id": "ccd6bc37",
117 | "metadata": {},
118 | "outputs": [
119 | {
120 | "data": {
121 | "text/html": [
122 | "\n",
123 | "\n",
136 | "
\n",
137 | " \n",
138 | " \n",
139 | " | \n",
140 | " dDayPriseRise | \n",
141 | " dDayClosingDiff | \n",
142 | " totalRise | \n",
143 | " d1TradeVolume | \n",
144 | " d1Amount | \n",
145 | " d1OpeningPrice | \n",
146 | " d1AgoHighestPrice | \n",
147 | " d1AgoLowestPrice | \n",
148 | " d1AgoClosingPrice | \n",
149 | " d1AgoClosingDiff | \n",
150 | " d1AgoTransaction | \n",
151 | " d1AgoMaxDiff | \n",
152 | " d1DayPriseRise | \n",
153 | "
\n",
154 | " \n",
155 | " \n",
156 | " \n",
157 | " | 0 | \n",
158 | " 0 | \n",
159 | " -1.35 | \n",
160 | " 0 | \n",
161 | " 4597622 | \n",
162 | " 630055512 | \n",
163 | " 137.45 | \n",
164 | " 137.65 | \n",
165 | " 136.60 | \n",
166 | " 137.15 | \n",
167 | " -0.40 | \n",
168 | " 5081 | \n",
169 | " 1.05 | \n",
170 | " 0 | \n",
171 | "
\n",
172 | " \n",
173 | " | 1 | \n",
174 | " 0 | \n",
175 | " -0.40 | \n",
176 | " 1 | \n",
177 | " 7527789 | \n",
178 | " 1031896075 | \n",
179 | " 136.95 | \n",
180 | " 137.55 | \n",
181 | " 136.70 | \n",
182 | " 137.55 | \n",
183 | " 0.00 | \n",
184 | " 5876 | \n",
185 | " 0.85 | \n",
186 | " 0 | \n",
187 | "
\n",
188 | " \n",
189 | " | 2 | \n",
190 | " 0 | \n",
191 | " 0.00 | \n",
192 | " 1 | \n",
193 | " 10797704 | \n",
194 | " 1483480452 | \n",
195 | " 136.65 | \n",
196 | " 137.75 | \n",
197 | " 136.60 | \n",
198 | " 137.55 | \n",
199 | " 1.15 | \n",
200 | " 9789 | \n",
201 | " 1.15 | \n",
202 | " 1 | \n",
203 | "
\n",
204 | " \n",
205 | " | 3 | \n",
206 | " 1 | \n",
207 | " 1.15 | \n",
208 | " 1 | \n",
209 | " 7522325 | \n",
210 | " 1022937288 | \n",
211 | " 136.00 | \n",
212 | " 136.70 | \n",
213 | " 135.20 | \n",
214 | " 136.40 | \n",
215 | " -0.10 | \n",
216 | " 7124 | \n",
217 | " 1.50 | \n",
218 | " 0 | \n",
219 | "
\n",
220 | " \n",
221 | " | 4 | \n",
222 | " 0 | \n",
223 | " -0.10 | \n",
224 | " 1 | \n",
225 | " 5321361 | \n",
226 | " 725081014 | \n",
227 | " 136.25 | \n",
228 | " 136.75 | \n",
229 | " 135.65 | \n",
230 | " 136.50 | \n",
231 | " 0.40 | \n",
232 | " 4657 | \n",
233 | " 1.10 | \n",
234 | " 1 | \n",
235 | "
\n",
236 | " \n",
237 | " | ... | \n",
238 | " ... | \n",
239 | " ... | \n",
240 | " ... | \n",
241 | " ... | \n",
242 | " ... | \n",
243 | " ... | \n",
244 | " ... | \n",
245 | " ... | \n",
246 | " ... | \n",
247 | " ... | \n",
248 | " ... | \n",
249 | " ... | \n",
250 | " ... | \n",
251 | "
\n",
252 | " \n",
253 | " | 700 | \n",
254 | " 1 | \n",
255 | " 1.15 | \n",
256 | " 1 | \n",
257 | " 5316228 | \n",
258 | " 397657901 | \n",
259 | " 74.50 | \n",
260 | " 75.10 | \n",
261 | " 74.45 | \n",
262 | " 75.05 | \n",
263 | " 0.60 | \n",
264 | " 2808 | \n",
265 | " 0.65 | \n",
266 | " 1 | \n",
267 | "
\n",
268 | " \n",
269 | " | 701 | \n",
270 | " 1 | \n",
271 | " 0.60 | \n",
272 | " 1 | \n",
273 | " 13013284 | \n",
274 | " 970567677 | \n",
275 | " 74.50 | \n",
276 | " 74.90 | \n",
277 | " 74.45 | \n",
278 | " 74.45 | \n",
279 | " -1.00 | \n",
280 | " 5810 | \n",
281 | " 0.45 | \n",
282 | " 0 | \n",
283 | "
\n",
284 | " \n",
285 | " | 702 | \n",
286 | " 0 | \n",
287 | " -1.00 | \n",
288 | " 1 | \n",
289 | " 6781008 | \n",
290 | " 512288502 | \n",
291 | " 75.60 | \n",
292 | " 75.75 | \n",
293 | " 75.30 | \n",
294 | " 75.45 | \n",
295 | " 0.35 | \n",
296 | " 4623 | \n",
297 | " 0.45 | \n",
298 | " 1 | \n",
299 | "
\n",
300 | " \n",
301 | " | 703 | \n",
302 | " 1 | \n",
303 | " 0.35 | \n",
304 | " 0 | \n",
305 | " 20347421 | \n",
306 | " 1529965270 | \n",
307 | " 75.85 | \n",
308 | " 75.85 | \n",
309 | " 74.85 | \n",
310 | " 75.10 | \n",
311 | " -1.55 | \n",
312 | " 10519 | \n",
313 | " 1.00 | \n",
314 | " 0 | \n",
315 | "
\n",
316 | " \n",
317 | " | 704 | \n",
318 | " 0 | \n",
319 | " -1.55 | \n",
320 | " 0 | \n",
321 | " 9636366 | \n",
322 | " 740544550 | \n",
323 | " 77.10 | \n",
324 | " 77.20 | \n",
325 | " 76.65 | \n",
326 | " 76.65 | \n",
327 | " -1.60 | \n",
328 | " 3602 | \n",
329 | " 0.55 | \n",
330 | " 0 | \n",
331 | "
\n",
332 | " \n",
333 | "
\n",
334 | "
705 rows × 13 columns
\n",
335 | "
"
336 | ],
337 | "text/plain": [
338 | " dDayPriseRise dDayClosingDiff totalRise d1TradeVolume d1Amount \\\n",
339 | "0 0 -1.35 0 4597622 630055512 \n",
340 | "1 0 -0.40 1 7527789 1031896075 \n",
341 | "2 0 0.00 1 10797704 1483480452 \n",
342 | "3 1 1.15 1 7522325 1022937288 \n",
343 | "4 0 -0.10 1 5321361 725081014 \n",
344 | ".. ... ... ... ... ... \n",
345 | "700 1 1.15 1 5316228 397657901 \n",
346 | "701 1 0.60 1 13013284 970567677 \n",
347 | "702 0 -1.00 1 6781008 512288502 \n",
348 | "703 1 0.35 0 20347421 1529965270 \n",
349 | "704 0 -1.55 0 9636366 740544550 \n",
350 | "\n",
351 | " d1OpeningPrice d1AgoHighestPrice d1AgoLowestPrice d1AgoClosingPrice \\\n",
352 | "0 137.45 137.65 136.60 137.15 \n",
353 | "1 136.95 137.55 136.70 137.55 \n",
354 | "2 136.65 137.75 136.60 137.55 \n",
355 | "3 136.00 136.70 135.20 136.40 \n",
356 | "4 136.25 136.75 135.65 136.50 \n",
357 | ".. ... ... ... ... \n",
358 | "700 74.50 75.10 74.45 75.05 \n",
359 | "701 74.50 74.90 74.45 74.45 \n",
360 | "702 75.60 75.75 75.30 75.45 \n",
361 | "703 75.85 75.85 74.85 75.10 \n",
362 | "704 77.10 77.20 76.65 76.65 \n",
363 | "\n",
364 | " d1AgoClosingDiff d1AgoTransaction d1AgoMaxDiff d1DayPriseRise \n",
365 | "0 -0.40 5081 1.05 0 \n",
366 | "1 0.00 5876 0.85 0 \n",
367 | "2 1.15 9789 1.15 1 \n",
368 | "3 -0.10 7124 1.50 0 \n",
369 | "4 0.40 4657 1.10 1 \n",
370 | ".. ... ... ... ... \n",
371 | "700 0.60 2808 0.65 1 \n",
372 | "701 -1.00 5810 0.45 0 \n",
373 | "702 0.35 4623 0.45 1 \n",
374 | "703 -1.55 10519 1.00 0 \n",
375 | "704 -1.60 3602 0.55 0 \n",
376 | "\n",
377 | "[705 rows x 13 columns]"
378 | ]
379 | },
380 | "execution_count": 19,
381 | "metadata": {},
382 | "output_type": "execute_result"
383 | }
384 | ],
385 | "source": [
386 | "df"
387 | ]
388 | },
389 | {
390 | "cell_type": "code",
391 | "execution_count": 22,
392 | "id": "c452c275",
393 | "metadata": {},
394 | "outputs": [
395 | {
396 | "data": {
397 | "text/html": [
398 | "\n",
399 | "\n",
412 | "
\n",
413 | " \n",
414 | " \n",
415 | " | \n",
416 | " dDayPriseRise | \n",
417 | " dDayClosingDiff | \n",
418 | " totalRise | \n",
419 | " d1TradeVolume | \n",
420 | " d1Amount | \n",
421 | " d1OpeningPrice | \n",
422 | " d1AgoHighestPrice | \n",
423 | " d1AgoLowestPrice | \n",
424 | " d1AgoClosingPrice | \n",
425 | " d1AgoClosingDiff | \n",
426 | " d1AgoTransaction | \n",
427 | " d1AgoMaxDiff | \n",
428 | " d1DayPriseRise | \n",
429 | "
\n",
430 | " \n",
431 | " \n",
432 | " \n",
433 | " | dDayPriseRise | \n",
434 | " 1.000000 | \n",
435 | " 0.690077 | \n",
436 | " 0.017607 | \n",
437 | " -0.055300 | \n",
438 | " -0.056692 | \n",
439 | " -0.051408 | \n",
440 | " -0.050721 | \n",
441 | " -0.049532 | \n",
442 | " -0.050018 | \n",
443 | " 0.020438 | \n",
444 | " -0.029423 | \n",
445 | " -0.053826 | \n",
446 | " 0.021118 | \n",
447 | "
\n",
448 | " \n",
449 | " | dDayClosingDiff | \n",
450 | " 0.690077 | \n",
451 | " 1.000000 | \n",
452 | " 0.021934 | \n",
453 | " -0.045731 | \n",
454 | " -0.033772 | \n",
455 | " -0.008455 | \n",
456 | " -0.007423 | \n",
457 | " -0.007124 | \n",
458 | " -0.008050 | \n",
459 | " 0.012131 | \n",
460 | " -0.004265 | \n",
461 | " -0.011269 | \n",
462 | " 0.022485 | \n",
463 | "
\n",
464 | " \n",
465 | " | totalRise | \n",
466 | " 0.017607 | \n",
467 | " 0.021934 | \n",
468 | " 1.000000 | \n",
469 | " -0.118961 | \n",
470 | " -0.108564 | \n",
471 | " -0.024623 | \n",
472 | " -0.019629 | \n",
473 | " -0.013800 | \n",
474 | " -0.011027 | \n",
475 | " 0.498864 | \n",
476 | " -0.197942 | \n",
477 | " -0.166556 | \n",
478 | " 0.714534 | \n",
479 | "
\n",
480 | " \n",
481 | " | d1TradeVolume | \n",
482 | " -0.055300 | \n",
483 | " -0.045731 | \n",
484 | " -0.118961 | \n",
485 | " 1.000000 | \n",
486 | " 0.916421 | \n",
487 | " -0.052051 | \n",
488 | " -0.045398 | \n",
489 | " -0.064629 | \n",
490 | " -0.055689 | \n",
491 | " -0.187188 | \n",
492 | " 0.723970 | \n",
493 | " 0.502675 | \n",
494 | " -0.075356 | \n",
495 | "
\n",
496 | " \n",
497 | " | d1Amount | \n",
498 | " -0.056692 | \n",
499 | " -0.033772 | \n",
500 | " -0.108564 | \n",
501 | " 0.916421 | \n",
502 | " 1.000000 | \n",
503 | " 0.275417 | \n",
504 | " 0.281788 | \n",
505 | " 0.262572 | \n",
506 | " 0.271583 | \n",
507 | " -0.179960 | \n",
508 | " 0.890879 | \n",
509 | " 0.641260 | \n",
510 | " -0.076290 | \n",
511 | "
\n",
512 | " \n",
513 | " | d1OpeningPrice | \n",
514 | " -0.051408 | \n",
515 | " -0.008455 | \n",
516 | " -0.024623 | \n",
517 | " -0.052051 | \n",
518 | " 0.275417 | \n",
519 | " 1.000000 | \n",
520 | " 0.999710 | \n",
521 | " 0.999510 | \n",
522 | " 0.999325 | \n",
523 | " 0.020781 | \n",
524 | " 0.423086 | \n",
525 | " 0.430105 | \n",
526 | " -0.028490 | \n",
527 | "
\n",
528 | " \n",
529 | " | d1AgoHighestPrice | \n",
530 | " -0.050721 | \n",
531 | " -0.007423 | \n",
532 | " -0.019629 | \n",
533 | " -0.045398 | \n",
534 | " 0.281788 | \n",
535 | " 0.999710 | \n",
536 | " 1.000000 | \n",
537 | " 0.999452 | \n",
538 | " 0.999698 | \n",
539 | " 0.033949 | \n",
540 | " 0.426283 | \n",
541 | " 0.439682 | \n",
542 | " -0.019473 | \n",
543 | "
\n",
544 | " \n",
545 | " | d1AgoLowestPrice | \n",
546 | " -0.049532 | \n",
547 | " -0.007124 | \n",
548 | " -0.013800 | \n",
549 | " -0.064629 | \n",
550 | " 0.262572 | \n",
551 | " 0.999510 | \n",
552 | " 0.999452 | \n",
553 | " 1.000000 | \n",
554 | " 0.999626 | \n",
555 | " 0.038352 | \n",
556 | " 0.408250 | \n",
557 | " 0.409719 | \n",
558 | " -0.016922 | \n",
559 | "
\n",
560 | " \n",
561 | " | d1AgoClosingPrice | \n",
562 | " -0.050018 | \n",
563 | " -0.008050 | \n",
564 | " -0.011027 | \n",
565 | " -0.055689 | \n",
566 | " 0.271583 | \n",
567 | " 0.999325 | \n",
568 | " 0.999698 | \n",
569 | " 0.999626 | \n",
570 | " 1.000000 | \n",
571 | " 0.048075 | \n",
572 | " 0.415308 | \n",
573 | " 0.426655 | \n",
574 | " -0.010142 | \n",
575 | "
\n",
576 | " \n",
577 | " | d1AgoClosingDiff | \n",
578 | " 0.020438 | \n",
579 | " 0.012131 | \n",
580 | " 0.498864 | \n",
581 | " -0.187188 | \n",
582 | " -0.179960 | \n",
583 | " 0.020781 | \n",
584 | " 0.033949 | \n",
585 | " 0.038352 | \n",
586 | " 0.048075 | \n",
587 | " 1.000000 | \n",
588 | " -0.309428 | \n",
589 | " -0.105086 | \n",
590 | " 0.690124 | \n",
591 | "
\n",
592 | " \n",
593 | " | d1AgoTransaction | \n",
594 | " -0.029423 | \n",
595 | " -0.004265 | \n",
596 | " -0.197942 | \n",
597 | " 0.723970 | \n",
598 | " 0.890879 | \n",
599 | " 0.423086 | \n",
600 | " 0.426283 | \n",
601 | " 0.408250 | \n",
602 | " 0.415308 | \n",
603 | " -0.309428 | \n",
604 | " 1.000000 | \n",
605 | " 0.670530 | \n",
606 | " -0.177660 | \n",
607 | "
\n",
608 | " \n",
609 | " | d1AgoMaxDiff | \n",
610 | " -0.053826 | \n",
611 | " -0.011269 | \n",
612 | " -0.166556 | \n",
613 | " 0.502675 | \n",
614 | " 0.641260 | \n",
615 | " 0.430105 | \n",
616 | " 0.439682 | \n",
617 | " 0.409719 | \n",
618 | " 0.426655 | \n",
619 | " -0.105086 | \n",
620 | " 0.670530 | \n",
621 | " 1.000000 | \n",
622 | " -0.077514 | \n",
623 | "
\n",
624 | " \n",
625 | " | d1DayPriseRise | \n",
626 | " 0.021118 | \n",
627 | " 0.022485 | \n",
628 | " 0.714534 | \n",
629 | " -0.075356 | \n",
630 | " -0.076290 | \n",
631 | " -0.028490 | \n",
632 | " -0.019473 | \n",
633 | " -0.016922 | \n",
634 | " -0.010142 | \n",
635 | " 0.690124 | \n",
636 | " -0.177660 | \n",
637 | " -0.077514 | \n",
638 | " 1.000000 | \n",
639 | "
\n",
640 | " \n",
641 | "
\n",
642 | "
"
643 | ],
644 | "text/plain": [
645 | " dDayPriseRise dDayClosingDiff totalRise d1TradeVolume \\\n",
646 | "dDayPriseRise 1.000000 0.690077 0.017607 -0.055300 \n",
647 | "dDayClosingDiff 0.690077 1.000000 0.021934 -0.045731 \n",
648 | "totalRise 0.017607 0.021934 1.000000 -0.118961 \n",
649 | "d1TradeVolume -0.055300 -0.045731 -0.118961 1.000000 \n",
650 | "d1Amount -0.056692 -0.033772 -0.108564 0.916421 \n",
651 | "d1OpeningPrice -0.051408 -0.008455 -0.024623 -0.052051 \n",
652 | "d1AgoHighestPrice -0.050721 -0.007423 -0.019629 -0.045398 \n",
653 | "d1AgoLowestPrice -0.049532 -0.007124 -0.013800 -0.064629 \n",
654 | "d1AgoClosingPrice -0.050018 -0.008050 -0.011027 -0.055689 \n",
655 | "d1AgoClosingDiff 0.020438 0.012131 0.498864 -0.187188 \n",
656 | "d1AgoTransaction -0.029423 -0.004265 -0.197942 0.723970 \n",
657 | "d1AgoMaxDiff -0.053826 -0.011269 -0.166556 0.502675 \n",
658 | "d1DayPriseRise 0.021118 0.022485 0.714534 -0.075356 \n",
659 | "\n",
660 | " d1Amount d1OpeningPrice d1AgoHighestPrice \\\n",
661 | "dDayPriseRise -0.056692 -0.051408 -0.050721 \n",
662 | "dDayClosingDiff -0.033772 -0.008455 -0.007423 \n",
663 | "totalRise -0.108564 -0.024623 -0.019629 \n",
664 | "d1TradeVolume 0.916421 -0.052051 -0.045398 \n",
665 | "d1Amount 1.000000 0.275417 0.281788 \n",
666 | "d1OpeningPrice 0.275417 1.000000 0.999710 \n",
667 | "d1AgoHighestPrice 0.281788 0.999710 1.000000 \n",
668 | "d1AgoLowestPrice 0.262572 0.999510 0.999452 \n",
669 | "d1AgoClosingPrice 0.271583 0.999325 0.999698 \n",
670 | "d1AgoClosingDiff -0.179960 0.020781 0.033949 \n",
671 | "d1AgoTransaction 0.890879 0.423086 0.426283 \n",
672 | "d1AgoMaxDiff 0.641260 0.430105 0.439682 \n",
673 | "d1DayPriseRise -0.076290 -0.028490 -0.019473 \n",
674 | "\n",
675 | " d1AgoLowestPrice d1AgoClosingPrice d1AgoClosingDiff \\\n",
676 | "dDayPriseRise -0.049532 -0.050018 0.020438 \n",
677 | "dDayClosingDiff -0.007124 -0.008050 0.012131 \n",
678 | "totalRise -0.013800 -0.011027 0.498864 \n",
679 | "d1TradeVolume -0.064629 -0.055689 -0.187188 \n",
680 | "d1Amount 0.262572 0.271583 -0.179960 \n",
681 | "d1OpeningPrice 0.999510 0.999325 0.020781 \n",
682 | "d1AgoHighestPrice 0.999452 0.999698 0.033949 \n",
683 | "d1AgoLowestPrice 1.000000 0.999626 0.038352 \n",
684 | "d1AgoClosingPrice 0.999626 1.000000 0.048075 \n",
685 | "d1AgoClosingDiff 0.038352 0.048075 1.000000 \n",
686 | "d1AgoTransaction 0.408250 0.415308 -0.309428 \n",
687 | "d1AgoMaxDiff 0.409719 0.426655 -0.105086 \n",
688 | "d1DayPriseRise -0.016922 -0.010142 0.690124 \n",
689 | "\n",
690 | " d1AgoTransaction d1AgoMaxDiff d1DayPriseRise \n",
691 | "dDayPriseRise -0.029423 -0.053826 0.021118 \n",
692 | "dDayClosingDiff -0.004265 -0.011269 0.022485 \n",
693 | "totalRise -0.197942 -0.166556 0.714534 \n",
694 | "d1TradeVolume 0.723970 0.502675 -0.075356 \n",
695 | "d1Amount 0.890879 0.641260 -0.076290 \n",
696 | "d1OpeningPrice 0.423086 0.430105 -0.028490 \n",
697 | "d1AgoHighestPrice 0.426283 0.439682 -0.019473 \n",
698 | "d1AgoLowestPrice 0.408250 0.409719 -0.016922 \n",
699 | "d1AgoClosingPrice 0.415308 0.426655 -0.010142 \n",
700 | "d1AgoClosingDiff -0.309428 -0.105086 0.690124 \n",
701 | "d1AgoTransaction 1.000000 0.670530 -0.177660 \n",
702 | "d1AgoMaxDiff 0.670530 1.000000 -0.077514 \n",
703 | "d1DayPriseRise -0.177660 -0.077514 1.000000 "
704 | ]
705 | },
706 | "execution_count": 22,
707 | "metadata": {},
708 | "output_type": "execute_result"
709 | }
710 | ],
711 | "source": [
712 | "df.corr()"
713 | ]
714 | },
715 | {
716 | "cell_type": "code",
717 | "execution_count": 20,
718 | "id": "37d35692",
719 | "metadata": {},
720 | "outputs": [
721 | {
722 | "data": {
723 | "text/html": [
724 | "\n",
725 | "\n",
738 | "
\n",
739 | " \n",
740 | " \n",
741 | " | \n",
742 | " d1TradeVolume | \n",
743 | " d1Amount | \n",
744 | " d1OpeningPrice | \n",
745 | " d1AgoHighestPrice | \n",
746 | " d1AgoLowestPrice | \n",
747 | " d1AgoClosingPrice | \n",
748 | " d1AgoClosingDiff | \n",
749 | " d1AgoTransaction | \n",
750 | " d1AgoMaxDiff | \n",
751 | " dDayPriseRise | \n",
752 | "
\n",
753 | " \n",
754 | " \n",
755 | " \n",
756 | " | 0 | \n",
757 | " -0.675245 | \n",
758 | " -0.456382 | \n",
759 | " 1.481273 | \n",
760 | " 1.458394 | \n",
761 | " 1.484518 | \n",
762 | " 1.468681 | \n",
763 | " -0.409883 | \n",
764 | " -0.214823 | \n",
765 | " -0.089481 | \n",
766 | " 0 | \n",
767 | "
\n",
768 | " \n",
769 | " | 1 | \n",
770 | " -0.276832 | \n",
771 | " 0.080338 | \n",
772 | " 1.459991 | \n",
773 | " 1.454164 | \n",
774 | " 1.488814 | \n",
775 | " 1.485714 | \n",
776 | " -0.079304 | \n",
777 | " -0.085389 | \n",
778 | " -0.322696 | \n",
779 | " 0 | \n",
780 | "
\n",
781 | " \n",
782 | " | 2 | \n",
783 | " 0.167777 | \n",
784 | " 0.683499 | \n",
785 | " 1.447221 | \n",
786 | " 1.462624 | \n",
787 | " 1.484518 | \n",
788 | " 1.485714 | \n",
789 | " 0.871111 | \n",
790 | " 0.551687 | \n",
791 | " 0.027126 | \n",
792 | " 0 | \n",
793 | "
\n",
794 | " \n",
795 | " | 3 | \n",
796 | " -0.277575 | \n",
797 | " 0.068372 | \n",
798 | " 1.419553 | \n",
799 | " 1.418209 | \n",
800 | " 1.424370 | \n",
801 | " 1.436745 | \n",
802 | " -0.161949 | \n",
803 | " 0.117798 | \n",
804 | " 0.435250 | \n",
805 | " 1 | \n",
806 | "
\n",
807 | " \n",
808 | " | 4 | \n",
809 | " -0.576839 | \n",
810 | " -0.329460 | \n",
811 | " 1.430195 | \n",
812 | " 1.420324 | \n",
813 | " 1.443703 | \n",
814 | " 1.441003 | \n",
815 | " 0.251275 | \n",
816 | " -0.283855 | \n",
817 | " -0.031178 | \n",
818 | " 0 | \n",
819 | "
\n",
820 | " \n",
821 | " | ... | \n",
822 | " ... | \n",
823 | " ... | \n",
824 | " ... | \n",
825 | " ... | \n",
826 | " ... | \n",
827 | " ... | \n",
828 | " ... | \n",
829 | " ... | \n",
830 | " ... | \n",
831 | " ... | \n",
832 | "
\n",
833 | " \n",
834 | " | 700 | \n",
835 | " -0.577537 | \n",
836 | " -0.766784 | \n",
837 | " -1.198219 | \n",
838 | " -1.187506 | \n",
839 | " -1.185610 | \n",
840 | " -1.175641 | \n",
841 | " 0.416565 | \n",
842 | " -0.584891 | \n",
843 | " -0.555910 | \n",
844 | " 1 | \n",
845 | "
\n",
846 | " \n",
847 | " | 701 | \n",
848 | " 0.469029 | \n",
849 | " -0.001575 | \n",
850 | " -1.198219 | \n",
851 | " -1.195966 | \n",
852 | " -1.185610 | \n",
853 | " -1.201190 | \n",
854 | " -0.905752 | \n",
855 | " -0.096135 | \n",
856 | " -0.789124 | \n",
857 | " 1 | \n",
858 | "
\n",
859 | " \n",
860 | " | 702 | \n",
861 | " -0.378371 | \n",
862 | " -0.613678 | \n",
863 | " -1.151397 | \n",
864 | " -1.160010 | \n",
865 | " -1.149092 | \n",
866 | " -1.158608 | \n",
867 | " 0.209953 | \n",
868 | " -0.289391 | \n",
869 | " -0.789124 | \n",
870 | " 0 | \n",
871 | "
\n",
872 | " \n",
873 | " | 703 | \n",
874 | " 1.466249 | \n",
875 | " 0.745586 | \n",
876 | " -1.140756 | \n",
877 | " -1.155780 | \n",
878 | " -1.168425 | \n",
879 | " -1.173512 | \n",
880 | " -1.360298 | \n",
881 | " 0.670539 | \n",
882 | " -0.147785 | \n",
883 | " 1 | \n",
884 | "
\n",
885 | " \n",
886 | " | 704 | \n",
887 | " 0.009871 | \n",
888 | " -0.308807 | \n",
889 | " -1.087549 | \n",
890 | " -1.098674 | \n",
891 | " -1.091093 | \n",
892 | " -1.107510 | \n",
893 | " -1.401621 | \n",
894 | " -0.455620 | \n",
895 | " -0.672517 | \n",
896 | " 0 | \n",
897 | "
\n",
898 | " \n",
899 | "
\n",
900 | "
705 rows × 10 columns
\n",
901 | "
"
902 | ],
903 | "text/plain": [
904 | " d1TradeVolume d1Amount d1OpeningPrice d1AgoHighestPrice \\\n",
905 | "0 -0.675245 -0.456382 1.481273 1.458394 \n",
906 | "1 -0.276832 0.080338 1.459991 1.454164 \n",
907 | "2 0.167777 0.683499 1.447221 1.462624 \n",
908 | "3 -0.277575 0.068372 1.419553 1.418209 \n",
909 | "4 -0.576839 -0.329460 1.430195 1.420324 \n",
910 | ".. ... ... ... ... \n",
911 | "700 -0.577537 -0.766784 -1.198219 -1.187506 \n",
912 | "701 0.469029 -0.001575 -1.198219 -1.195966 \n",
913 | "702 -0.378371 -0.613678 -1.151397 -1.160010 \n",
914 | "703 1.466249 0.745586 -1.140756 -1.155780 \n",
915 | "704 0.009871 -0.308807 -1.087549 -1.098674 \n",
916 | "\n",
917 | " d1AgoLowestPrice d1AgoClosingPrice d1AgoClosingDiff d1AgoTransaction \\\n",
918 | "0 1.484518 1.468681 -0.409883 -0.214823 \n",
919 | "1 1.488814 1.485714 -0.079304 -0.085389 \n",
920 | "2 1.484518 1.485714 0.871111 0.551687 \n",
921 | "3 1.424370 1.436745 -0.161949 0.117798 \n",
922 | "4 1.443703 1.441003 0.251275 -0.283855 \n",
923 | ".. ... ... ... ... \n",
924 | "700 -1.185610 -1.175641 0.416565 -0.584891 \n",
925 | "701 -1.185610 -1.201190 -0.905752 -0.096135 \n",
926 | "702 -1.149092 -1.158608 0.209953 -0.289391 \n",
927 | "703 -1.168425 -1.173512 -1.360298 0.670539 \n",
928 | "704 -1.091093 -1.107510 -1.401621 -0.455620 \n",
929 | "\n",
930 | " d1AgoMaxDiff dDayPriseRise \n",
931 | "0 -0.089481 0 \n",
932 | "1 -0.322696 0 \n",
933 | "2 0.027126 0 \n",
934 | "3 0.435250 1 \n",
935 | "4 -0.031178 0 \n",
936 | ".. ... ... \n",
937 | "700 -0.555910 1 \n",
938 | "701 -0.789124 1 \n",
939 | "702 -0.789124 0 \n",
940 | "703 -0.147785 1 \n",
941 | "704 -0.672517 0 \n",
942 | "\n",
943 | "[705 rows x 10 columns]"
944 | ]
945 | },
946 | "execution_count": 20,
947 | "metadata": {},
948 | "output_type": "execute_result"
949 | }
950 | ],
951 | "source": [
952 | "from sklearn.preprocessing import StandardScaler\n",
953 | "\n",
954 | "scale = StandardScaler()\n",
955 | "\n",
956 | "scale_target = [\n",
957 | " 'd1TradeVolume',\n",
958 | " 'd1Amount',\n",
959 | " 'd1OpeningPrice',\n",
960 | " 'd1AgoHighestPrice',\n",
961 | " 'd1AgoLowestPrice',\n",
962 | " 'd1AgoClosingPrice',\n",
963 | " 'd1AgoClosingDiff',\n",
964 | " 'd1AgoTransaction',\n",
965 | " 'd1AgoMaxDiff',\n",
966 | "]\n",
967 | "\n",
968 | "scaled = pd.DataFrame(scale.fit_transform(df[scale_target]), columns=scale_target)\n",
969 | "scaled['dDayPriseRise'] = df['dDayPriseRise']\n",
970 | "scaled"
971 | ]
972 | },
973 | {
974 | "cell_type": "code",
975 | "execution_count": 38,
976 | "id": "a5747469",
977 | "metadata": {},
978 | "outputs": [
979 | {
980 | "name": "stdout",
981 | "output_type": "stream",
982 | "text": [
983 | "Number of labeled points out of a total 212 points : 109\n"
984 | ]
985 | }
986 | ],
987 | "source": [
988 | "from sklearn.naive_bayes import GaussianNB\n",
989 | "from sklearn.model_selection import train_test_split\n",
990 | "\n",
991 | "X_train, X_test, y_train, y_test = train_test_split(scaled[scale_target], scaled['dDayPriseRise'], test_size=0.3, random_state=0)\n",
992 | "gnb = GaussianNB()\n",
993 | "y_pred = gnb.fit(X_train, y_train).predict(X_test)\n",
994 | "\n",
995 | "test_count = X_test.shape[0]\n",
996 | "print(\"Number of labeled points out of a total %d points : %d\" % (test_count, (y_test == y_pred).sum()))\n",
997 | "\n",
998 | "from sklearn.metrics import confusion_matrix\n",
999 | "tn, fp, fn, tp = confusion_matrix(y_test, y_pred).ravel()"
1000 | ]
1001 | },
1002 | {
1003 | "cell_type": "code",
1004 | "execution_count": 36,
1005 | "id": "2d823316",
1006 | "metadata": {},
1007 | "outputs": [
1008 | {
1009 | "name": "stdout",
1010 | "output_type": "stream",
1011 | "text": [
1012 | " : pn,pp\n",
1013 | "an: 42, 135\n",
1014 | "ap: 37, 139\n"
1015 | ]
1016 | }
1017 | ],
1018 | "source": [
1019 | "print(f' : pn,pp')\n",
1020 | "print(f'an: {tn}, {fp}')\n",
1021 | "print(f'ap: {fn}, {tp}')"
1022 | ]
1023 | },
1024 | {
1025 | "cell_type": "code",
1026 | "execution_count": null,
1027 | "id": "123ab836",
1028 | "metadata": {},
1029 | "outputs": [],
1030 | "source": []
1031 | }
1032 | ],
1033 | "metadata": {
1034 | "kernelspec": {
1035 | "display_name": "Python 3 (ipykernel)",
1036 | "language": "python",
1037 | "name": "python3"
1038 | },
1039 | "language_info": {
1040 | "codemirror_mode": {
1041 | "name": "ipython",
1042 | "version": 3
1043 | },
1044 | "file_extension": ".py",
1045 | "mimetype": "text/x-python",
1046 | "name": "python",
1047 | "nbconvert_exporter": "python",
1048 | "pygments_lexer": "ipython3",
1049 | "version": "3.8.12"
1050 | }
1051 | },
1052 | "nbformat": 4,
1053 | "nbformat_minor": 5
1054 | }
1055 |
--------------------------------------------------------------------------------
/lab/experiment1/three_days_strategy.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "id": "10c819c0",
7 | "metadata": {},
8 | "outputs": [],
9 | "source": [
10 | "from pymongo import MongoClient\n",
11 | "from pymongo import DESCENDING, ASCENDING\n",
12 | "\n",
13 | "from urllib.parse import quote_plus"
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": 2,
19 | "id": "a06c39d0",
20 | "metadata": {},
21 | "outputs": [],
22 | "source": [
23 | "uri = \"mongodb://%s:%s@%s/?authSource=stock\" % (\n",
24 | " quote_plus('airflower'), quote_plus('money'), 'localhost')\n",
25 | "client = MongoClient(uri)"
26 | ]
27 | },
28 | {
29 | "cell_type": "code",
30 | "execution_count": 3,
31 | "id": "47d1ac75",
32 | "metadata": {},
33 | "outputs": [],
34 | "source": [
35 | "results = list(client.stock.dailyTransactions.find({'stockCode': '0050'}).sort('intDate', DESCENDING))"
36 | ]
37 | },
38 | {
39 | "cell_type": "code",
40 | "execution_count": 4,
41 | "id": "fdca3755",
42 | "metadata": {},
43 | "outputs": [],
44 | "source": [
45 | "def total_rise(days):\n",
46 | " count = 0\n",
47 | " for day in days:\n",
48 | " count += 1 if day['closingDiff'] > 0 else 0\n",
49 | " \n",
50 | " return count\n",
51 | "\n",
52 | "data = [ \n",
53 | " {\n",
54 | " # target\n",
55 | " 'dDayPriseRise': 1 if results[i]['closingDiff'] > 0 else 0,\n",
56 | " 'dDayClosingDiff': results[i]['closingDiff'],\n",
57 | " # summary\n",
58 | " # 'totalRise': total_rise(results[i+1:i+3]),\n",
59 | " # day1 columns\n",
60 | " 'd1TradeVolume': results[i+1]['tradeVolume'],\n",
61 | " 'd1Amount': results[i+1]['amount'],\n",
62 | " 'd1OpeningPrice': results[i+1]['openingPrice'],\n",
63 | " 'd1AgoHighestPrice': results[i+1]['highestPrice'],\n",
64 | " 'd1AgoLowestPrice': results[i+1]['lowestPrice'],\n",
65 | " 'd1AgoClosingPrice': results[i+1]['closingPrice'],\n",
66 | " 'd1AgoClosingDiff': results[i+1]['closingDiff'],\n",
67 | " 'd1AgoTransaction': results[i+1]['transaction'],\n",
68 | " 'd1AgoMaxDiff': round(results[i+1]['highestPrice'] - results[i+1]['lowestPrice'], 2),\n",
69 | " 'd1AgoDayPriseRise': 1 if results[i+1]['closingDiff'] > 0 else 0,\n",
70 | " # day2 columns\n",
71 | " 'd2TradeVolume': results[i+2]['tradeVolume'],\n",
72 | " 'd2Amount': results[i+2]['amount'],\n",
73 | " 'd2OpeningPrice': results[i+2]['openingPrice'],\n",
74 | " 'd2AgoHighestPrice': results[i+2]['highestPrice'],\n",
75 | " 'd2AgoLowestPrice': results[i+2]['lowestPrice'],\n",
76 | " 'd2AgoClosingPrice': results[i+2]['closingPrice'],\n",
77 | " 'd2AgoClosingDiff': results[i+2]['closingDiff'],\n",
78 | " 'd2AgoTransaction': results[i+2]['transaction'],\n",
79 | " 'd2AgoMaxDiff': round(results[i+2]['highestPrice'] - results[i+2]['lowestPrice'], 2),\n",
80 | " 'd2AgoDayPriseRise': 1 if results[i+2]['closingDiff'] > 0 else 0,\n",
81 | " # day3 columns\n",
82 | " 'd3TradeVolume': results[i+3]['tradeVolume'],\n",
83 | " 'd3Amount': results[i+3]['amount'],\n",
84 | " 'd3OpeningPrice': results[i+3]['openingPrice'],\n",
85 | " 'd3AgoHighestPrice': results[i+3]['highestPrice'],\n",
86 | " 'd3AgoLowestPrice': results[i+3]['lowestPrice'],\n",
87 | " 'd3AgoClosingPrice': results[i+3]['closingPrice'],\n",
88 | " 'd3AgoClosingDiff': results[i+3]['closingDiff'],\n",
89 | " 'd3AgoTransaction': results[i+3]['transaction'],\n",
90 | " 'd3AgoMaxDiff': round(results[i+3]['highestPrice'] - results[i+3]['lowestPrice'], 2),\n",
91 | " 'd3AgoDayPriseRise': 1 if results[i+3]['closingDiff'] > 0 else 0,\n",
92 | " # rise\n",
93 | " 'd1AgoTradeVolumeRise': 1 if results[i+1]['tradeVolume'] > results[i+2]['tradeVolume'] else 0,\n",
94 | " 'd1AgoAmountRise': 1 if results[i+1]['amount'] > results[i+2]['amount'] else 0,\n",
95 | " 'd1AgoTransactionRise': 1 if results[i+1]['transaction'] > results[i+2]['transaction'] else 0,\n",
96 | " 'd2AgoTradeVolumeRise': 1 if results[i+2]['tradeVolume'] > results[i+3]['tradeVolume'] else 0,\n",
97 | " 'd2AgoAmountRise': 1 if results[i+2]['amount'] > results[i+3]['amount'] else 0,\n",
98 | " 'd2AgoTransactionRise': 1 if results[i+2]['transaction'] > results[i+3]['transaction'] else 0,\n",
99 | "\n",
100 | " }\n",
101 | " for i in range(0, len(results)-3)\n",
102 | "]"
103 | ]
104 | },
105 | {
106 | "cell_type": "code",
107 | "execution_count": 5,
108 | "id": "28d2f155",
109 | "metadata": {},
110 | "outputs": [],
111 | "source": [
112 | "import pandas as pd\n",
113 | "df = pd.DataFrame(data)"
114 | ]
115 | },
116 | {
117 | "cell_type": "code",
118 | "execution_count": 10,
119 | "id": "d9111ddb",
120 | "metadata": {},
121 | "outputs": [
122 | {
123 | "data": {
124 | "text/html": [
125 | "\n",
126 | "\n",
139 | "
\n",
140 | " \n",
141 | " \n",
142 | " | \n",
143 | " dDayPriseRise | \n",
144 | " dDayClosingDiff | \n",
145 | " d1TradeVolume | \n",
146 | " d1Amount | \n",
147 | " d1OpeningPrice | \n",
148 | " d1AgoHighestPrice | \n",
149 | " d1AgoLowestPrice | \n",
150 | " d1AgoClosingPrice | \n",
151 | " d1AgoClosingDiff | \n",
152 | " d1AgoTransaction | \n",
153 | " ... | \n",
154 | " d3AgoClosingDiff | \n",
155 | " d3AgoTransaction | \n",
156 | " d3AgoMaxDiff | \n",
157 | " d3AgoDayPriseRise | \n",
158 | " d1AgoTradeVolumeRise | \n",
159 | " d1AgoAmountRise | \n",
160 | " d1AgoTransactionRise | \n",
161 | " d2AgoTradeVolumeRise | \n",
162 | " d2AgoAmountRise | \n",
163 | " d2AgoTransactionRise | \n",
164 | "
\n",
165 | " \n",
166 | " \n",
167 | " \n",
168 | " | dDayPriseRise | \n",
169 | " 1.000000 | \n",
170 | " 0.692129 | \n",
171 | " -0.048711 | \n",
172 | " -0.047336 | \n",
173 | " -0.047911 | \n",
174 | " -0.047099 | \n",
175 | " -0.046045 | \n",
176 | " -0.046449 | \n",
177 | " 0.022676 | \n",
178 | " -0.023960 | \n",
179 | " ... | \n",
180 | " -0.042127 | \n",
181 | " -0.045853 | \n",
182 | " -0.031084 | \n",
183 | " -0.060108 | \n",
184 | " 0.068881 | \n",
185 | " 0.056877 | \n",
186 | " 0.043534 | \n",
187 | " -0.008501 | \n",
188 | " 0.007142 | \n",
189 | " -0.011731 | \n",
190 | "
\n",
191 | " \n",
192 | " | dDayClosingDiff | \n",
193 | " 0.692129 | \n",
194 | " 1.000000 | \n",
195 | " -0.040452 | \n",
196 | " -0.026802 | \n",
197 | " -0.008208 | \n",
198 | " -0.007084 | \n",
199 | " -0.006943 | \n",
200 | " -0.007763 | \n",
201 | " 0.015269 | \n",
202 | " -0.000756 | \n",
203 | " ... | \n",
204 | " 0.007302 | \n",
205 | " -0.001950 | \n",
206 | " 0.014466 | \n",
207 | " -0.007133 | \n",
208 | " 0.034718 | \n",
209 | " 0.027194 | \n",
210 | " 0.018125 | \n",
211 | " -0.022222 | \n",
212 | " -0.016792 | \n",
213 | " -0.014523 | \n",
214 | "
\n",
215 | " \n",
216 | " | d1TradeVolume | \n",
217 | " -0.048711 | \n",
218 | " -0.040452 | \n",
219 | " 1.000000 | \n",
220 | " 0.915744 | \n",
221 | " -0.065934 | \n",
222 | " -0.059411 | \n",
223 | " -0.078021 | \n",
224 | " -0.069193 | \n",
225 | " -0.178545 | \n",
226 | " 0.724128 | \n",
227 | " ... | \n",
228 | " -0.136109 | \n",
229 | " 0.359018 | \n",
230 | " 0.269790 | \n",
231 | " -0.084614 | \n",
232 | " 0.296903 | \n",
233 | " 0.298094 | \n",
234 | " 0.271998 | \n",
235 | " 0.041215 | \n",
236 | " 0.042810 | \n",
237 | " 0.064892 | \n",
238 | "
\n",
239 | " \n",
240 | " | d1Amount | \n",
241 | " -0.047336 | \n",
242 | " -0.026802 | \n",
243 | " 0.915744 | \n",
244 | " 1.000000 | \n",
245 | " 0.260799 | \n",
246 | " 0.267092 | \n",
247 | " 0.248472 | \n",
248 | " 0.257456 | \n",
249 | " -0.167800 | \n",
250 | " 0.890393 | \n",
251 | " ... | \n",
252 | " -0.106305 | \n",
253 | " 0.479799 | \n",
254 | " 0.379975 | \n",
255 | " -0.073745 | \n",
256 | " 0.302812 | \n",
257 | " 0.304105 | \n",
258 | " 0.268580 | \n",
259 | " 0.043768 | \n",
260 | " 0.043257 | \n",
261 | " 0.051107 | \n",
262 | "
\n",
263 | " \n",
264 | " | d1OpeningPrice | \n",
265 | " -0.047911 | \n",
266 | " -0.008208 | \n",
267 | " -0.065934 | \n",
268 | " 0.260799 | \n",
269 | " 1.000000 | \n",
270 | " 0.999724 | \n",
271 | " 0.999532 | \n",
272 | " 0.999358 | \n",
273 | " 0.022161 | \n",
274 | " 0.413294 | \n",
275 | " ... | \n",
276 | " 0.051003 | \n",
277 | " 0.405168 | \n",
278 | " 0.401764 | \n",
279 | " -0.001685 | \n",
280 | " 0.017749 | \n",
281 | " 0.019142 | \n",
282 | " -0.010875 | \n",
283 | " 0.022138 | \n",
284 | " 0.023496 | \n",
285 | " -0.008444 | \n",
286 | "
\n",
287 | " \n",
288 | " | d1AgoHighestPrice | \n",
289 | " -0.047099 | \n",
290 | " -0.007084 | \n",
291 | " -0.059411 | \n",
292 | " 0.267092 | \n",
293 | " 0.999724 | \n",
294 | " 1.000000 | \n",
295 | " 0.999473 | \n",
296 | " 0.999712 | \n",
297 | " 0.035027 | \n",
298 | " 0.416553 | \n",
299 | " ... | \n",
300 | " 0.048921 | \n",
301 | " 0.410320 | \n",
302 | " 0.407927 | \n",
303 | " -0.002961 | \n",
304 | " 0.019381 | \n",
305 | " 0.021139 | \n",
306 | " -0.009927 | \n",
307 | " 0.021901 | \n",
308 | " 0.023109 | \n",
309 | " -0.008009 | \n",
310 | "
\n",
311 | " \n",
312 | " | d1AgoLowestPrice | \n",
313 | " -0.046045 | \n",
314 | " -0.006943 | \n",
315 | " -0.078021 | \n",
316 | " 0.248472 | \n",
317 | " 0.999532 | \n",
318 | " 0.999473 | \n",
319 | " 1.000000 | \n",
320 | " 0.999641 | \n",
321 | " 0.039295 | \n",
322 | " 0.398856 | \n",
323 | " ... | \n",
324 | " 0.052826 | \n",
325 | " 0.399828 | \n",
326 | " 0.396589 | \n",
327 | " -0.000219 | \n",
328 | " 0.015962 | \n",
329 | " 0.017204 | \n",
330 | " -0.014368 | \n",
331 | " 0.022114 | \n",
332 | " 0.023378 | \n",
333 | " -0.010058 | \n",
334 | "
\n",
335 | " \n",
336 | " | d1AgoClosingPrice | \n",
337 | " -0.046449 | \n",
338 | " -0.007763 | \n",
339 | " -0.069193 | \n",
340 | " 0.257456 | \n",
341 | " 0.999358 | \n",
342 | " 0.999712 | \n",
343 | " 0.999641 | \n",
344 | " 1.000000 | \n",
345 | " 0.048794 | \n",
346 | " 0.406020 | \n",
347 | " ... | \n",
348 | " 0.050872 | \n",
349 | " 0.405158 | \n",
350 | " 0.401867 | \n",
351 | " -0.001768 | \n",
352 | " 0.017331 | \n",
353 | " 0.018742 | \n",
354 | " -0.013227 | \n",
355 | " 0.022506 | \n",
356 | " 0.023605 | \n",
357 | " -0.008629 | \n",
358 | "
\n",
359 | " \n",
360 | " | d1AgoClosingDiff | \n",
361 | " 0.022676 | \n",
362 | " 0.015269 | \n",
363 | " -0.178545 | \n",
364 | " -0.167800 | \n",
365 | " 0.022161 | \n",
366 | " 0.035027 | \n",
367 | " 0.039295 | \n",
368 | " 0.048794 | \n",
369 | " 1.000000 | \n",
370 | " -0.299492 | \n",
371 | " ... | \n",
372 | " 0.042829 | \n",
373 | " -0.024235 | \n",
374 | " -0.014138 | \n",
375 | " 0.006713 | \n",
376 | " -0.033479 | \n",
377 | " -0.016926 | \n",
378 | " -0.100909 | \n",
379 | " 0.033979 | \n",
380 | " 0.026431 | \n",
381 | " 0.017356 | \n",
382 | "
\n",
383 | " \n",
384 | " | d1AgoTransaction | \n",
385 | " -0.023960 | \n",
386 | " -0.000756 | \n",
387 | " 0.724128 | \n",
388 | " 0.890393 | \n",
389 | " 0.413294 | \n",
390 | " 0.416553 | \n",
391 | " 0.398856 | \n",
392 | " 0.406020 | \n",
393 | " -0.299492 | \n",
394 | " 1.000000 | \n",
395 | " ... | \n",
396 | " -0.138620 | \n",
397 | " 0.553126 | \n",
398 | " 0.431454 | \n",
399 | " -0.106920 | \n",
400 | " 0.238354 | \n",
401 | " 0.238661 | \n",
402 | " 0.250626 | \n",
403 | " 0.023165 | \n",
404 | " 0.021230 | \n",
405 | " 0.016530 | \n",
406 | "
\n",
407 | " \n",
408 | " | d1AgoMaxDiff | \n",
409 | " -0.048395 | \n",
410 | " -0.006778 | \n",
411 | " 0.497370 | \n",
412 | " 0.628576 | \n",
413 | " 0.406225 | \n",
414 | " 0.415737 | \n",
415 | " 0.385983 | \n",
416 | " 0.402825 | \n",
417 | " -0.105481 | \n",
418 | " 0.662672 | \n",
419 | " ... | \n",
420 | " -0.089749 | \n",
421 | " 0.458369 | \n",
422 | " 0.481108 | \n",
423 | " -0.077968 | \n",
424 | " 0.103524 | \n",
425 | " 0.118688 | \n",
426 | " 0.120375 | \n",
427 | " 0.002816 | \n",
428 | " 0.001734 | \n",
429 | " 0.054168 | \n",
430 | "
\n",
431 | " \n",
432 | " | d1AgoDayPriseRise | \n",
433 | " 0.025850 | \n",
434 | " 0.029230 | \n",
435 | " -0.065240 | \n",
436 | " -0.061991 | \n",
437 | " -0.025350 | \n",
438 | " -0.016525 | \n",
439 | " -0.013928 | \n",
440 | " -0.007351 | \n",
441 | " 0.692225 | \n",
442 | " -0.166937 | \n",
443 | " ... | \n",
444 | " 0.024388 | \n",
445 | " -0.072995 | \n",
446 | " -0.043298 | \n",
447 | " 0.006322 | \n",
448 | " 0.002554 | \n",
449 | " 0.023720 | \n",
450 | " -0.055944 | \n",
451 | " 0.068881 | \n",
452 | " 0.056877 | \n",
453 | " 0.043534 | \n",
454 | "
\n",
455 | " \n",
456 | " | d2TradeVolume | \n",
457 | " -0.073006 | \n",
458 | " -0.065481 | \n",
459 | " 0.606350 | \n",
460 | " 0.524134 | \n",
461 | " -0.068497 | \n",
462 | " -0.062375 | \n",
463 | " -0.076997 | \n",
464 | " -0.068852 | \n",
465 | " -0.041671 | \n",
466 | " 0.425635 | \n",
467 | " ... | \n",
468 | " -0.154435 | \n",
469 | " 0.423790 | \n",
470 | " 0.326057 | \n",
471 | " -0.089003 | \n",
472 | " -0.304293 | \n",
473 | " -0.302703 | \n",
474 | " -0.250580 | \n",
475 | " 0.296696 | \n",
476 | " 0.297883 | \n",
477 | " 0.271782 | \n",
478 | "
\n",
479 | " \n",
480 | " | d2Amount | \n",
481 | " -0.074072 | \n",
482 | " -0.048026 | \n",
483 | " 0.532284 | \n",
484 | " 0.593096 | \n",
485 | " 0.258644 | \n",
486 | " 0.264653 | \n",
487 | " 0.249978 | \n",
488 | " 0.258270 | \n",
489 | " -0.027369 | \n",
490 | " 0.555092 | \n",
491 | " ... | \n",
492 | " -0.114338 | \n",
493 | " 0.545839 | \n",
494 | " 0.448161 | \n",
495 | " -0.070167 | \n",
496 | " -0.297051 | \n",
497 | " -0.295771 | \n",
498 | " -0.255804 | \n",
499 | " 0.302871 | \n",
500 | " 0.304166 | \n",
501 | " 0.268642 | \n",
502 | "
\n",
503 | " \n",
504 | " | d2OpeningPrice | \n",
505 | " -0.048322 | \n",
506 | " -0.009232 | \n",
507 | " -0.055731 | \n",
508 | " 0.269984 | \n",
509 | " 0.998670 | \n",
510 | " 0.998502 | \n",
511 | " 0.997960 | \n",
512 | " 0.998063 | \n",
513 | " -0.001945 | \n",
514 | " 0.425951 | \n",
515 | " ... | \n",
516 | " 0.049154 | \n",
517 | " 0.408088 | \n",
518 | " 0.402403 | \n",
519 | " -0.002779 | \n",
520 | " 0.020204 | \n",
521 | " 0.020504 | \n",
522 | " -0.007718 | \n",
523 | " 0.021265 | \n",
524 | " 0.022718 | \n",
525 | " -0.007355 | \n",
526 | "
\n",
527 | " \n",
528 | " | d2AgoHighestPrice | \n",
529 | " -0.048904 | \n",
530 | " -0.009287 | \n",
531 | " -0.052268 | \n",
532 | " 0.273613 | \n",
533 | " 0.999062 | \n",
534 | " 0.998935 | \n",
535 | " 0.998302 | \n",
536 | " 0.998420 | \n",
537 | " -0.000826 | \n",
538 | " 0.428568 | \n",
539 | " ... | \n",
540 | " 0.046009 | \n",
541 | " 0.413808 | \n",
542 | " 0.410018 | \n",
543 | " -0.004605 | \n",
544 | " 0.017024 | \n",
545 | " 0.017532 | \n",
546 | " -0.010146 | \n",
547 | " 0.022900 | \n",
548 | " 0.024718 | \n",
549 | " -0.006404 | \n",
550 | "
\n",
551 | " \n",
552 | " | d2AgoLowestPrice | \n",
553 | " -0.048072 | \n",
554 | " -0.008937 | \n",
555 | " -0.064686 | \n",
556 | " 0.261520 | \n",
557 | " 0.999087 | \n",
558 | " 0.998685 | \n",
559 | " 0.998575 | \n",
560 | " 0.998411 | \n",
561 | " -0.000629 | \n",
562 | " 0.417210 | \n",
563 | " ... | \n",
564 | " 0.053940 | \n",
565 | " 0.398951 | \n",
566 | " 0.395160 | \n",
567 | " 0.001118 | \n",
568 | " 0.022240 | \n",
569 | " 0.022675 | \n",
570 | " -0.004780 | \n",
571 | " 0.019501 | \n",
572 | " 0.020803 | \n",
573 | " -0.010827 | \n",
574 | "
\n",
575 | " \n",
576 | " | d2AgoClosingPrice | \n",
577 | " -0.048331 | \n",
578 | " -0.009209 | \n",
579 | " -0.059581 | \n",
580 | " 0.267126 | \n",
581 | " 0.999402 | \n",
582 | " 0.999099 | \n",
583 | " 0.998785 | \n",
584 | " 0.998682 | \n",
585 | " -0.001482 | \n",
586 | " 0.422522 | \n",
587 | " ... | \n",
588 | " 0.048758 | \n",
589 | " 0.407657 | \n",
590 | " 0.403072 | \n",
591 | " -0.001654 | \n",
592 | " 0.019008 | \n",
593 | " 0.019580 | \n",
594 | " -0.007908 | \n",
595 | " 0.020859 | \n",
596 | " 0.022331 | \n",
597 | " -0.009695 | \n",
598 | "
\n",
599 | " \n",
600 | " | d2AgoClosingDiff | \n",
601 | " 0.027643 | \n",
602 | " 0.047588 | \n",
603 | " -0.152251 | \n",
604 | " -0.111946 | \n",
605 | " 0.050302 | \n",
606 | " 0.047203 | \n",
607 | " 0.055077 | \n",
608 | " 0.049934 | \n",
609 | " 0.015998 | \n",
610 | " -0.127842 | \n",
611 | " ... | \n",
612 | " 0.014669 | \n",
613 | " -0.000457 | \n",
614 | " -0.005939 | \n",
615 | " 0.027539 | \n",
616 | " -0.002629 | \n",
617 | " 0.006240 | \n",
618 | " 0.025145 | \n",
619 | " -0.032911 | \n",
620 | " -0.016352 | \n",
621 | " -0.100324 | \n",
622 | "
\n",
623 | " \n",
624 | " | d2AgoTransaction | \n",
625 | " -0.072474 | \n",
626 | " -0.023369 | \n",
627 | " 0.424101 | \n",
628 | " 0.546289 | \n",
629 | " 0.407626 | \n",
630 | " 0.413370 | \n",
631 | " 0.398479 | \n",
632 | " 0.407206 | \n",
633 | " -0.000292 | \n",
634 | " 0.580575 | \n",
635 | " ... | \n",
636 | " -0.129519 | \n",
637 | " 0.580140 | \n",
638 | " 0.490051 | \n",
639 | " -0.097677 | \n",
640 | " -0.218559 | \n",
641 | " -0.217779 | \n",
642 | " -0.250190 | \n",
643 | " 0.238803 | \n",
644 | " 0.239118 | \n",
645 | " 0.251075 | \n",
646 | "
\n",
647 | " \n",
648 | " | d2AgoMaxDiff | \n",
649 | " -0.042953 | \n",
650 | " -0.013545 | \n",
651 | " 0.326256 | \n",
652 | " 0.448457 | \n",
653 | " 0.401877 | \n",
654 | " 0.409511 | \n",
655 | " 0.394623 | \n",
656 | " 0.402555 | \n",
657 | " -0.005847 | \n",
658 | " 0.490350 | \n",
659 | " ... | \n",
660 | " -0.203291 | \n",
661 | " 0.582251 | \n",
662 | " 0.580766 | \n",
663 | " -0.161927 | \n",
664 | " -0.139007 | \n",
665 | " -0.136794 | \n",
666 | " -0.154156 | \n",
667 | " 0.104274 | \n",
668 | " 0.119444 | \n",
669 | " 0.121124 | \n",
670 | "
\n",
671 | " \n",
672 | " | d2AgoDayPriseRise | \n",
673 | " 0.009245 | \n",
674 | " 0.011447 | \n",
675 | " -0.086643 | \n",
676 | " -0.067858 | \n",
677 | " -0.003661 | \n",
678 | " -0.005444 | \n",
679 | " 0.000208 | \n",
680 | " -0.002520 | \n",
681 | " 0.028420 | \n",
682 | " -0.096225 | \n",
683 | " ... | \n",
684 | " 0.020030 | \n",
685 | " -0.023915 | \n",
686 | " -0.047858 | \n",
687 | " 0.022930 | \n",
688 | " -0.030610 | \n",
689 | " -0.037067 | \n",
690 | " -0.028311 | \n",
691 | " 0.002554 | \n",
692 | " 0.023720 | \n",
693 | " -0.055944 | \n",
694 | "
\n",
695 | " \n",
696 | " | d3TradeVolume | \n",
697 | " -0.036086 | \n",
698 | " 0.003284 | \n",
699 | " 0.513658 | \n",
700 | " 0.431778 | \n",
701 | " -0.071059 | \n",
702 | " -0.065690 | \n",
703 | " -0.077706 | \n",
704 | " -0.072132 | \n",
705 | " -0.069101 | \n",
706 | " 0.363142 | \n",
707 | " ... | \n",
708 | " -0.177289 | \n",
709 | " 0.724512 | \n",
710 | " 0.497825 | \n",
711 | " -0.066060 | \n",
712 | " -0.057756 | \n",
713 | " -0.060395 | \n",
714 | " -0.083526 | \n",
715 | " -0.306334 | \n",
716 | " -0.304776 | \n",
717 | " -0.252622 | \n",
718 | "
\n",
719 | " \n",
720 | " | d3Amount | \n",
721 | " -0.052464 | \n",
722 | " -0.005365 | \n",
723 | " 0.445219 | \n",
724 | " 0.500609 | \n",
725 | " 0.256522 | \n",
726 | " 0.261882 | \n",
727 | " 0.250139 | \n",
728 | " 0.255870 | \n",
729 | " -0.050311 | \n",
730 | " 0.492699 | \n",
731 | " ... | \n",
732 | " -0.167241 | \n",
733 | " 0.890712 | \n",
734 | " 0.629058 | \n",
735 | " -0.062735 | \n",
736 | " -0.052066 | \n",
737 | " -0.053862 | \n",
738 | " -0.092361 | \n",
739 | " -0.298288 | \n",
740 | " -0.297028 | \n",
741 | " -0.257038 | \n",
742 | "
\n",
743 | " \n",
744 | " | d3OpeningPrice | \n",
745 | " -0.049109 | \n",
746 | " -0.012837 | \n",
747 | " -0.050098 | \n",
748 | " 0.274739 | \n",
749 | " 0.997457 | \n",
750 | " 0.997337 | \n",
751 | " 0.996492 | \n",
752 | " 0.996713 | \n",
753 | " -0.002841 | \n",
754 | " 0.432810 | \n",
755 | " ... | \n",
756 | " 0.022058 | \n",
757 | " 0.415823 | \n",
758 | " 0.408731 | \n",
759 | " -0.020716 | \n",
760 | " 0.017951 | \n",
761 | " 0.018266 | \n",
762 | " -0.011708 | \n",
763 | " 0.023797 | \n",
764 | " 0.024157 | \n",
765 | " -0.004121 | \n",
766 | "
\n",
767 | " \n",
768 | " | d3AgoHighestPrice | \n",
769 | " -0.049489 | \n",
770 | " -0.011762 | \n",
771 | " -0.045899 | \n",
772 | " 0.278672 | \n",
773 | " 0.997775 | \n",
774 | " 0.997737 | \n",
775 | " 0.996760 | \n",
776 | " 0.997052 | \n",
777 | " -0.003038 | \n",
778 | " 0.435525 | \n",
779 | " ... | \n",
780 | " 0.034980 | \n",
781 | " 0.419070 | \n",
782 | " 0.418240 | \n",
783 | " -0.011870 | \n",
784 | " 0.017938 | \n",
785 | " 0.018304 | \n",
786 | " -0.010873 | \n",
787 | " 0.020531 | \n",
788 | " 0.021097 | \n",
789 | " -0.006634 | \n",
790 | "
\n",
791 | " \n",
792 | " | d3AgoLowestPrice | \n",
793 | " -0.049091 | \n",
794 | " -0.012449 | \n",
795 | " -0.056217 | \n",
796 | " 0.269097 | \n",
797 | " 0.997804 | \n",
798 | " 0.997545 | \n",
799 | " 0.996959 | \n",
800 | " 0.997067 | \n",
801 | " -0.002576 | \n",
802 | " 0.426373 | \n",
803 | " ... | \n",
804 | " 0.039227 | \n",
805 | " 0.401397 | \n",
806 | " 0.388492 | \n",
807 | " -0.009230 | \n",
808 | " 0.019511 | \n",
809 | " 0.019571 | \n",
810 | " -0.010221 | \n",
811 | " 0.025814 | \n",
812 | " 0.026309 | \n",
813 | " -0.001202 | \n",
814 | "
\n",
815 | " \n",
816 | " | d3AgoClosingPrice | \n",
817 | " -0.049797 | \n",
818 | " -0.012175 | \n",
819 | " -0.051694 | \n",
820 | " 0.273427 | \n",
821 | " 0.998048 | \n",
822 | " 0.997890 | \n",
823 | " 0.997157 | \n",
824 | " 0.997323 | \n",
825 | " -0.002961 | \n",
826 | " 0.429827 | \n",
827 | " ... | \n",
828 | " 0.048765 | \n",
829 | " 0.408546 | \n",
830 | " 0.405333 | \n",
831 | " -0.002653 | \n",
832 | " 0.018663 | \n",
833 | " 0.018781 | \n",
834 | " -0.009679 | \n",
835 | " 0.022513 | \n",
836 | " 0.023144 | \n",
837 | " -0.004397 | \n",
838 | "
\n",
839 | " \n",
840 | " | d3AgoClosingDiff | \n",
841 | " -0.042127 | \n",
842 | " 0.007302 | \n",
843 | " -0.136109 | \n",
844 | " -0.106305 | \n",
845 | " 0.051003 | \n",
846 | " 0.048921 | \n",
847 | " 0.052826 | \n",
848 | " 0.050872 | \n",
849 | " 0.042829 | \n",
850 | " -0.138620 | \n",
851 | " ... | \n",
852 | " 1.000000 | \n",
853 | " -0.298125 | \n",
854 | " -0.104569 | \n",
855 | " 0.692979 | \n",
856 | " -0.024608 | \n",
857 | " -0.021523 | \n",
858 | " 0.066537 | \n",
859 | " -0.005597 | \n",
860 | " 0.003209 | \n",
861 | " 0.022108 | \n",
862 | "
\n",
863 | " \n",
864 | " | d3AgoTransaction | \n",
865 | " -0.045853 | \n",
866 | " -0.001950 | \n",
867 | " 0.359018 | \n",
868 | " 0.479799 | \n",
869 | " 0.405168 | \n",
870 | " 0.410320 | \n",
871 | " 0.399828 | \n",
872 | " 0.405158 | \n",
873 | " -0.024235 | \n",
874 | " 0.553126 | \n",
875 | " ... | \n",
876 | " -0.298125 | \n",
877 | " 1.000000 | \n",
878 | " 0.662909 | \n",
879 | " -0.166374 | \n",
880 | " -0.023891 | \n",
881 | " -0.026534 | \n",
882 | " -0.084802 | \n",
883 | " -0.219041 | \n",
884 | " -0.218269 | \n",
885 | " -0.250675 | \n",
886 | "
\n",
887 | " \n",
888 | " | d3AgoMaxDiff | \n",
889 | " -0.031084 | \n",
890 | " 0.014466 | \n",
891 | " 0.269790 | \n",
892 | " 0.379975 | \n",
893 | " 0.401764 | \n",
894 | " 0.407927 | \n",
895 | " 0.396589 | \n",
896 | " 0.401867 | \n",
897 | " -0.014138 | \n",
898 | " 0.431454 | \n",
899 | " ... | \n",
900 | " -0.104569 | \n",
901 | " 0.662909 | \n",
902 | " 1.000000 | \n",
903 | " -0.078556 | \n",
904 | " -0.036712 | \n",
905 | " -0.028022 | \n",
906 | " -0.022610 | \n",
907 | " -0.139327 | \n",
908 | " -0.137119 | \n",
909 | " -0.154478 | \n",
910 | "
\n",
911 | " \n",
912 | " | d3AgoDayPriseRise | \n",
913 | " -0.060108 | \n",
914 | " -0.007133 | \n",
915 | " -0.084614 | \n",
916 | " -0.073745 | \n",
917 | " -0.001685 | \n",
918 | " -0.002961 | \n",
919 | " -0.000219 | \n",
920 | " -0.001768 | \n",
921 | " 0.006713 | \n",
922 | " -0.106920 | \n",
923 | " ... | \n",
924 | " 0.692979 | \n",
925 | " -0.166374 | \n",
926 | " -0.078556 | \n",
927 | " 1.000000 | \n",
928 | " -0.038850 | \n",
929 | " -0.039825 | \n",
930 | " 0.024229 | \n",
931 | " -0.033321 | \n",
932 | " -0.039825 | \n",
933 | " -0.031045 | \n",
934 | "
\n",
935 | " \n",
936 | " | d1AgoTradeVolumeRise | \n",
937 | " 0.068881 | \n",
938 | " 0.034718 | \n",
939 | " 0.296903 | \n",
940 | " 0.302812 | \n",
941 | " 0.017749 | \n",
942 | " 0.019381 | \n",
943 | " 0.015962 | \n",
944 | " 0.017331 | \n",
945 | " -0.033479 | \n",
946 | " 0.238354 | \n",
947 | " ... | \n",
948 | " -0.024608 | \n",
949 | " -0.023891 | \n",
950 | " -0.036712 | \n",
951 | " -0.038850 | \n",
952 | " 1.000000 | \n",
953 | " 0.978063 | \n",
954 | " 0.688219 | \n",
955 | " -0.280548 | \n",
956 | " -0.274630 | \n",
957 | " -0.227909 | \n",
958 | "
\n",
959 | " \n",
960 | " | d1AgoAmountRise | \n",
961 | " 0.056877 | \n",
962 | " 0.027194 | \n",
963 | " 0.298094 | \n",
964 | " 0.304105 | \n",
965 | " 0.019142 | \n",
966 | " 0.021139 | \n",
967 | " 0.017204 | \n",
968 | " 0.018742 | \n",
969 | " -0.016926 | \n",
970 | " 0.238661 | \n",
971 | " ... | \n",
972 | " -0.021523 | \n",
973 | " -0.026534 | \n",
974 | " -0.028022 | \n",
975 | " -0.039825 | \n",
976 | " 0.978063 | \n",
977 | " 1.000000 | \n",
978 | " 0.693801 | \n",
979 | " -0.274630 | \n",
980 | " -0.268987 | \n",
981 | " -0.222139 | \n",
982 | "
\n",
983 | " \n",
984 | " | d1AgoTransactionRise | \n",
985 | " 0.043534 | \n",
986 | " 0.018125 | \n",
987 | " 0.271998 | \n",
988 | " 0.268580 | \n",
989 | " -0.010875 | \n",
990 | " -0.009927 | \n",
991 | " -0.014368 | \n",
992 | " -0.013227 | \n",
993 | " -0.100909 | \n",
994 | " 0.250626 | \n",
995 | " ... | \n",
996 | " 0.066537 | \n",
997 | " -0.084802 | \n",
998 | " -0.022610 | \n",
999 | " 0.024229 | \n",
1000 | " 0.688219 | \n",
1001 | " 0.693801 | \n",
1002 | " 1.000000 | \n",
1003 | " -0.238947 | \n",
1004 | " -0.238692 | \n",
1005 | " -0.269161 | \n",
1006 | "
\n",
1007 | " \n",
1008 | " | d2AgoTradeVolumeRise | \n",
1009 | " -0.008501 | \n",
1010 | " -0.022222 | \n",
1011 | " 0.041215 | \n",
1012 | " 0.043768 | \n",
1013 | " 0.022138 | \n",
1014 | " 0.021901 | \n",
1015 | " 0.022114 | \n",
1016 | " 0.022506 | \n",
1017 | " 0.033979 | \n",
1018 | " 0.023165 | \n",
1019 | " ... | \n",
1020 | " -0.005597 | \n",
1021 | " -0.219041 | \n",
1022 | " -0.139327 | \n",
1023 | " -0.033321 | \n",
1024 | " -0.280548 | \n",
1025 | " -0.274630 | \n",
1026 | " -0.238947 | \n",
1027 | " 1.000000 | \n",
1028 | " 0.978063 | \n",
1029 | " 0.688219 | \n",
1030 | "
\n",
1031 | " \n",
1032 | " | d2AgoAmountRise | \n",
1033 | " 0.007142 | \n",
1034 | " -0.016792 | \n",
1035 | " 0.042810 | \n",
1036 | " 0.043257 | \n",
1037 | " 0.023496 | \n",
1038 | " 0.023109 | \n",
1039 | " 0.023378 | \n",
1040 | " 0.023605 | \n",
1041 | " 0.026431 | \n",
1042 | " 0.021230 | \n",
1043 | " ... | \n",
1044 | " 0.003209 | \n",
1045 | " -0.218269 | \n",
1046 | " -0.137119 | \n",
1047 | " -0.039825 | \n",
1048 | " -0.274630 | \n",
1049 | " -0.268987 | \n",
1050 | " -0.238692 | \n",
1051 | " 0.978063 | \n",
1052 | " 1.000000 | \n",
1053 | " 0.693801 | \n",
1054 | "
\n",
1055 | " \n",
1056 | " | d2AgoTransactionRise | \n",
1057 | " -0.011731 | \n",
1058 | " -0.014523 | \n",
1059 | " 0.064892 | \n",
1060 | " 0.051107 | \n",
1061 | " -0.008444 | \n",
1062 | " -0.008009 | \n",
1063 | " -0.010058 | \n",
1064 | " -0.008629 | \n",
1065 | " 0.017356 | \n",
1066 | " 0.016530 | \n",
1067 | " ... | \n",
1068 | " 0.022108 | \n",
1069 | " -0.250675 | \n",
1070 | " -0.154478 | \n",
1071 | " -0.031045 | \n",
1072 | " -0.227909 | \n",
1073 | " -0.222139 | \n",
1074 | " -0.269161 | \n",
1075 | " 0.688219 | \n",
1076 | " 0.693801 | \n",
1077 | " 1.000000 | \n",
1078 | "
\n",
1079 | " \n",
1080 | "
\n",
1081 | "
38 rows × 38 columns
\n",
1082 | "
"
1083 | ],
1084 | "text/plain": [
1085 | " dDayPriseRise dDayClosingDiff d1TradeVolume d1Amount \\\n",
1086 | "dDayPriseRise 1.000000 0.692129 -0.048711 -0.047336 \n",
1087 | "dDayClosingDiff 0.692129 1.000000 -0.040452 -0.026802 \n",
1088 | "d1TradeVolume -0.048711 -0.040452 1.000000 0.915744 \n",
1089 | "d1Amount -0.047336 -0.026802 0.915744 1.000000 \n",
1090 | "d1OpeningPrice -0.047911 -0.008208 -0.065934 0.260799 \n",
1091 | "d1AgoHighestPrice -0.047099 -0.007084 -0.059411 0.267092 \n",
1092 | "d1AgoLowestPrice -0.046045 -0.006943 -0.078021 0.248472 \n",
1093 | "d1AgoClosingPrice -0.046449 -0.007763 -0.069193 0.257456 \n",
1094 | "d1AgoClosingDiff 0.022676 0.015269 -0.178545 -0.167800 \n",
1095 | "d1AgoTransaction -0.023960 -0.000756 0.724128 0.890393 \n",
1096 | "d1AgoMaxDiff -0.048395 -0.006778 0.497370 0.628576 \n",
1097 | "d1AgoDayPriseRise 0.025850 0.029230 -0.065240 -0.061991 \n",
1098 | "d2TradeVolume -0.073006 -0.065481 0.606350 0.524134 \n",
1099 | "d2Amount -0.074072 -0.048026 0.532284 0.593096 \n",
1100 | "d2OpeningPrice -0.048322 -0.009232 -0.055731 0.269984 \n",
1101 | "d2AgoHighestPrice -0.048904 -0.009287 -0.052268 0.273613 \n",
1102 | "d2AgoLowestPrice -0.048072 -0.008937 -0.064686 0.261520 \n",
1103 | "d2AgoClosingPrice -0.048331 -0.009209 -0.059581 0.267126 \n",
1104 | "d2AgoClosingDiff 0.027643 0.047588 -0.152251 -0.111946 \n",
1105 | "d2AgoTransaction -0.072474 -0.023369 0.424101 0.546289 \n",
1106 | "d2AgoMaxDiff -0.042953 -0.013545 0.326256 0.448457 \n",
1107 | "d2AgoDayPriseRise 0.009245 0.011447 -0.086643 -0.067858 \n",
1108 | "d3TradeVolume -0.036086 0.003284 0.513658 0.431778 \n",
1109 | "d3Amount -0.052464 -0.005365 0.445219 0.500609 \n",
1110 | "d3OpeningPrice -0.049109 -0.012837 -0.050098 0.274739 \n",
1111 | "d3AgoHighestPrice -0.049489 -0.011762 -0.045899 0.278672 \n",
1112 | "d3AgoLowestPrice -0.049091 -0.012449 -0.056217 0.269097 \n",
1113 | "d3AgoClosingPrice -0.049797 -0.012175 -0.051694 0.273427 \n",
1114 | "d3AgoClosingDiff -0.042127 0.007302 -0.136109 -0.106305 \n",
1115 | "d3AgoTransaction -0.045853 -0.001950 0.359018 0.479799 \n",
1116 | "d3AgoMaxDiff -0.031084 0.014466 0.269790 0.379975 \n",
1117 | "d3AgoDayPriseRise -0.060108 -0.007133 -0.084614 -0.073745 \n",
1118 | "d1AgoTradeVolumeRise 0.068881 0.034718 0.296903 0.302812 \n",
1119 | "d1AgoAmountRise 0.056877 0.027194 0.298094 0.304105 \n",
1120 | "d1AgoTransactionRise 0.043534 0.018125 0.271998 0.268580 \n",
1121 | "d2AgoTradeVolumeRise -0.008501 -0.022222 0.041215 0.043768 \n",
1122 | "d2AgoAmountRise 0.007142 -0.016792 0.042810 0.043257 \n",
1123 | "d2AgoTransactionRise -0.011731 -0.014523 0.064892 0.051107 \n",
1124 | "\n",
1125 | " d1OpeningPrice d1AgoHighestPrice d1AgoLowestPrice \\\n",
1126 | "dDayPriseRise -0.047911 -0.047099 -0.046045 \n",
1127 | "dDayClosingDiff -0.008208 -0.007084 -0.006943 \n",
1128 | "d1TradeVolume -0.065934 -0.059411 -0.078021 \n",
1129 | "d1Amount 0.260799 0.267092 0.248472 \n",
1130 | "d1OpeningPrice 1.000000 0.999724 0.999532 \n",
1131 | "d1AgoHighestPrice 0.999724 1.000000 0.999473 \n",
1132 | "d1AgoLowestPrice 0.999532 0.999473 1.000000 \n",
1133 | "d1AgoClosingPrice 0.999358 0.999712 0.999641 \n",
1134 | "d1AgoClosingDiff 0.022161 0.035027 0.039295 \n",
1135 | "d1AgoTransaction 0.413294 0.416553 0.398856 \n",
1136 | "d1AgoMaxDiff 0.406225 0.415737 0.385983 \n",
1137 | "d1AgoDayPriseRise -0.025350 -0.016525 -0.013928 \n",
1138 | "d2TradeVolume -0.068497 -0.062375 -0.076997 \n",
1139 | "d2Amount 0.258644 0.264653 0.249978 \n",
1140 | "d2OpeningPrice 0.998670 0.998502 0.997960 \n",
1141 | "d2AgoHighestPrice 0.999062 0.998935 0.998302 \n",
1142 | "d2AgoLowestPrice 0.999087 0.998685 0.998575 \n",
1143 | "d2AgoClosingPrice 0.999402 0.999099 0.998785 \n",
1144 | "d2AgoClosingDiff 0.050302 0.047203 0.055077 \n",
1145 | "d2AgoTransaction 0.407626 0.413370 0.398479 \n",
1146 | "d2AgoMaxDiff 0.401877 0.409511 0.394623 \n",
1147 | "d2AgoDayPriseRise -0.003661 -0.005444 0.000208 \n",
1148 | "d3TradeVolume -0.071059 -0.065690 -0.077706 \n",
1149 | "d3Amount 0.256522 0.261882 0.250139 \n",
1150 | "d3OpeningPrice 0.997457 0.997337 0.996492 \n",
1151 | "d3AgoHighestPrice 0.997775 0.997737 0.996760 \n",
1152 | "d3AgoLowestPrice 0.997804 0.997545 0.996959 \n",
1153 | "d3AgoClosingPrice 0.998048 0.997890 0.997157 \n",
1154 | "d3AgoClosingDiff 0.051003 0.048921 0.052826 \n",
1155 | "d3AgoTransaction 0.405168 0.410320 0.399828 \n",
1156 | "d3AgoMaxDiff 0.401764 0.407927 0.396589 \n",
1157 | "d3AgoDayPriseRise -0.001685 -0.002961 -0.000219 \n",
1158 | "d1AgoTradeVolumeRise 0.017749 0.019381 0.015962 \n",
1159 | "d1AgoAmountRise 0.019142 0.021139 0.017204 \n",
1160 | "d1AgoTransactionRise -0.010875 -0.009927 -0.014368 \n",
1161 | "d2AgoTradeVolumeRise 0.022138 0.021901 0.022114 \n",
1162 | "d2AgoAmountRise 0.023496 0.023109 0.023378 \n",
1163 | "d2AgoTransactionRise -0.008444 -0.008009 -0.010058 \n",
1164 | "\n",
1165 | " d1AgoClosingPrice d1AgoClosingDiff d1AgoTransaction \\\n",
1166 | "dDayPriseRise -0.046449 0.022676 -0.023960 \n",
1167 | "dDayClosingDiff -0.007763 0.015269 -0.000756 \n",
1168 | "d1TradeVolume -0.069193 -0.178545 0.724128 \n",
1169 | "d1Amount 0.257456 -0.167800 0.890393 \n",
1170 | "d1OpeningPrice 0.999358 0.022161 0.413294 \n",
1171 | "d1AgoHighestPrice 0.999712 0.035027 0.416553 \n",
1172 | "d1AgoLowestPrice 0.999641 0.039295 0.398856 \n",
1173 | "d1AgoClosingPrice 1.000000 0.048794 0.406020 \n",
1174 | "d1AgoClosingDiff 0.048794 1.000000 -0.299492 \n",
1175 | "d1AgoTransaction 0.406020 -0.299492 1.000000 \n",
1176 | "d1AgoMaxDiff 0.402825 -0.105481 0.662672 \n",
1177 | "d1AgoDayPriseRise -0.007351 0.692225 -0.166937 \n",
1178 | "d2TradeVolume -0.068852 -0.041671 0.425635 \n",
1179 | "d2Amount 0.258270 -0.027369 0.555092 \n",
1180 | "d2OpeningPrice 0.998063 -0.001945 0.425951 \n",
1181 | "d2AgoHighestPrice 0.998420 -0.000826 0.428568 \n",
1182 | "d2AgoLowestPrice 0.998411 -0.000629 0.417210 \n",
1183 | "d2AgoClosingPrice 0.998682 -0.001482 0.422522 \n",
1184 | "d2AgoClosingDiff 0.049934 0.015998 -0.127842 \n",
1185 | "d2AgoTransaction 0.407206 -0.000292 0.580575 \n",
1186 | "d2AgoMaxDiff 0.402555 -0.005847 0.490350 \n",
1187 | "d2AgoDayPriseRise -0.002520 0.028420 -0.096225 \n",
1188 | "d3TradeVolume -0.072132 -0.069101 0.363142 \n",
1189 | "d3Amount 0.255870 -0.050311 0.492699 \n",
1190 | "d3OpeningPrice 0.996713 -0.002841 0.432810 \n",
1191 | "d3AgoHighestPrice 0.997052 -0.003038 0.435525 \n",
1192 | "d3AgoLowestPrice 0.997067 -0.002576 0.426373 \n",
1193 | "d3AgoClosingPrice 0.997323 -0.002961 0.429827 \n",
1194 | "d3AgoClosingDiff 0.050872 0.042829 -0.138620 \n",
1195 | "d3AgoTransaction 0.405158 -0.024235 0.553126 \n",
1196 | "d3AgoMaxDiff 0.401867 -0.014138 0.431454 \n",
1197 | "d3AgoDayPriseRise -0.001768 0.006713 -0.106920 \n",
1198 | "d1AgoTradeVolumeRise 0.017331 -0.033479 0.238354 \n",
1199 | "d1AgoAmountRise 0.018742 -0.016926 0.238661 \n",
1200 | "d1AgoTransactionRise -0.013227 -0.100909 0.250626 \n",
1201 | "d2AgoTradeVolumeRise 0.022506 0.033979 0.023165 \n",
1202 | "d2AgoAmountRise 0.023605 0.026431 0.021230 \n",
1203 | "d2AgoTransactionRise -0.008629 0.017356 0.016530 \n",
1204 | "\n",
1205 | " ... d3AgoClosingDiff d3AgoTransaction d3AgoMaxDiff \\\n",
1206 | "dDayPriseRise ... -0.042127 -0.045853 -0.031084 \n",
1207 | "dDayClosingDiff ... 0.007302 -0.001950 0.014466 \n",
1208 | "d1TradeVolume ... -0.136109 0.359018 0.269790 \n",
1209 | "d1Amount ... -0.106305 0.479799 0.379975 \n",
1210 | "d1OpeningPrice ... 0.051003 0.405168 0.401764 \n",
1211 | "d1AgoHighestPrice ... 0.048921 0.410320 0.407927 \n",
1212 | "d1AgoLowestPrice ... 0.052826 0.399828 0.396589 \n",
1213 | "d1AgoClosingPrice ... 0.050872 0.405158 0.401867 \n",
1214 | "d1AgoClosingDiff ... 0.042829 -0.024235 -0.014138 \n",
1215 | "d1AgoTransaction ... -0.138620 0.553126 0.431454 \n",
1216 | "d1AgoMaxDiff ... -0.089749 0.458369 0.481108 \n",
1217 | "d1AgoDayPriseRise ... 0.024388 -0.072995 -0.043298 \n",
1218 | "d2TradeVolume ... -0.154435 0.423790 0.326057 \n",
1219 | "d2Amount ... -0.114338 0.545839 0.448161 \n",
1220 | "d2OpeningPrice ... 0.049154 0.408088 0.402403 \n",
1221 | "d2AgoHighestPrice ... 0.046009 0.413808 0.410018 \n",
1222 | "d2AgoLowestPrice ... 0.053940 0.398951 0.395160 \n",
1223 | "d2AgoClosingPrice ... 0.048758 0.407657 0.403072 \n",
1224 | "d2AgoClosingDiff ... 0.014669 -0.000457 -0.005939 \n",
1225 | "d2AgoTransaction ... -0.129519 0.580140 0.490051 \n",
1226 | "d2AgoMaxDiff ... -0.203291 0.582251 0.580766 \n",
1227 | "d2AgoDayPriseRise ... 0.020030 -0.023915 -0.047858 \n",
1228 | "d3TradeVolume ... -0.177289 0.724512 0.497825 \n",
1229 | "d3Amount ... -0.167241 0.890712 0.629058 \n",
1230 | "d3OpeningPrice ... 0.022058 0.415823 0.408731 \n",
1231 | "d3AgoHighestPrice ... 0.034980 0.419070 0.418240 \n",
1232 | "d3AgoLowestPrice ... 0.039227 0.401397 0.388492 \n",
1233 | "d3AgoClosingPrice ... 0.048765 0.408546 0.405333 \n",
1234 | "d3AgoClosingDiff ... 1.000000 -0.298125 -0.104569 \n",
1235 | "d3AgoTransaction ... -0.298125 1.000000 0.662909 \n",
1236 | "d3AgoMaxDiff ... -0.104569 0.662909 1.000000 \n",
1237 | "d3AgoDayPriseRise ... 0.692979 -0.166374 -0.078556 \n",
1238 | "d1AgoTradeVolumeRise ... -0.024608 -0.023891 -0.036712 \n",
1239 | "d1AgoAmountRise ... -0.021523 -0.026534 -0.028022 \n",
1240 | "d1AgoTransactionRise ... 0.066537 -0.084802 -0.022610 \n",
1241 | "d2AgoTradeVolumeRise ... -0.005597 -0.219041 -0.139327 \n",
1242 | "d2AgoAmountRise ... 0.003209 -0.218269 -0.137119 \n",
1243 | "d2AgoTransactionRise ... 0.022108 -0.250675 -0.154478 \n",
1244 | "\n",
1245 | " d3AgoDayPriseRise d1AgoTradeVolumeRise \\\n",
1246 | "dDayPriseRise -0.060108 0.068881 \n",
1247 | "dDayClosingDiff -0.007133 0.034718 \n",
1248 | "d1TradeVolume -0.084614 0.296903 \n",
1249 | "d1Amount -0.073745 0.302812 \n",
1250 | "d1OpeningPrice -0.001685 0.017749 \n",
1251 | "d1AgoHighestPrice -0.002961 0.019381 \n",
1252 | "d1AgoLowestPrice -0.000219 0.015962 \n",
1253 | "d1AgoClosingPrice -0.001768 0.017331 \n",
1254 | "d1AgoClosingDiff 0.006713 -0.033479 \n",
1255 | "d1AgoTransaction -0.106920 0.238354 \n",
1256 | "d1AgoMaxDiff -0.077968 0.103524 \n",
1257 | "d1AgoDayPriseRise 0.006322 0.002554 \n",
1258 | "d2TradeVolume -0.089003 -0.304293 \n",
1259 | "d2Amount -0.070167 -0.297051 \n",
1260 | "d2OpeningPrice -0.002779 0.020204 \n",
1261 | "d2AgoHighestPrice -0.004605 0.017024 \n",
1262 | "d2AgoLowestPrice 0.001118 0.022240 \n",
1263 | "d2AgoClosingPrice -0.001654 0.019008 \n",
1264 | "d2AgoClosingDiff 0.027539 -0.002629 \n",
1265 | "d2AgoTransaction -0.097677 -0.218559 \n",
1266 | "d2AgoMaxDiff -0.161927 -0.139007 \n",
1267 | "d2AgoDayPriseRise 0.022930 -0.030610 \n",
1268 | "d3TradeVolume -0.066060 -0.057756 \n",
1269 | "d3Amount -0.062735 -0.052066 \n",
1270 | "d3OpeningPrice -0.020716 0.017951 \n",
1271 | "d3AgoHighestPrice -0.011870 0.017938 \n",
1272 | "d3AgoLowestPrice -0.009230 0.019511 \n",
1273 | "d3AgoClosingPrice -0.002653 0.018663 \n",
1274 | "d3AgoClosingDiff 0.692979 -0.024608 \n",
1275 | "d3AgoTransaction -0.166374 -0.023891 \n",
1276 | "d3AgoMaxDiff -0.078556 -0.036712 \n",
1277 | "d3AgoDayPriseRise 1.000000 -0.038850 \n",
1278 | "d1AgoTradeVolumeRise -0.038850 1.000000 \n",
1279 | "d1AgoAmountRise -0.039825 0.978063 \n",
1280 | "d1AgoTransactionRise 0.024229 0.688219 \n",
1281 | "d2AgoTradeVolumeRise -0.033321 -0.280548 \n",
1282 | "d2AgoAmountRise -0.039825 -0.274630 \n",
1283 | "d2AgoTransactionRise -0.031045 -0.227909 \n",
1284 | "\n",
1285 | " d1AgoAmountRise d1AgoTransactionRise \\\n",
1286 | "dDayPriseRise 0.056877 0.043534 \n",
1287 | "dDayClosingDiff 0.027194 0.018125 \n",
1288 | "d1TradeVolume 0.298094 0.271998 \n",
1289 | "d1Amount 0.304105 0.268580 \n",
1290 | "d1OpeningPrice 0.019142 -0.010875 \n",
1291 | "d1AgoHighestPrice 0.021139 -0.009927 \n",
1292 | "d1AgoLowestPrice 0.017204 -0.014368 \n",
1293 | "d1AgoClosingPrice 0.018742 -0.013227 \n",
1294 | "d1AgoClosingDiff -0.016926 -0.100909 \n",
1295 | "d1AgoTransaction 0.238661 0.250626 \n",
1296 | "d1AgoMaxDiff 0.118688 0.120375 \n",
1297 | "d1AgoDayPriseRise 0.023720 -0.055944 \n",
1298 | "d2TradeVolume -0.302703 -0.250580 \n",
1299 | "d2Amount -0.295771 -0.255804 \n",
1300 | "d2OpeningPrice 0.020504 -0.007718 \n",
1301 | "d2AgoHighestPrice 0.017532 -0.010146 \n",
1302 | "d2AgoLowestPrice 0.022675 -0.004780 \n",
1303 | "d2AgoClosingPrice 0.019580 -0.007908 \n",
1304 | "d2AgoClosingDiff 0.006240 0.025145 \n",
1305 | "d2AgoTransaction -0.217779 -0.250190 \n",
1306 | "d2AgoMaxDiff -0.136794 -0.154156 \n",
1307 | "d2AgoDayPriseRise -0.037067 -0.028311 \n",
1308 | "d3TradeVolume -0.060395 -0.083526 \n",
1309 | "d3Amount -0.053862 -0.092361 \n",
1310 | "d3OpeningPrice 0.018266 -0.011708 \n",
1311 | "d3AgoHighestPrice 0.018304 -0.010873 \n",
1312 | "d3AgoLowestPrice 0.019571 -0.010221 \n",
1313 | "d3AgoClosingPrice 0.018781 -0.009679 \n",
1314 | "d3AgoClosingDiff -0.021523 0.066537 \n",
1315 | "d3AgoTransaction -0.026534 -0.084802 \n",
1316 | "d3AgoMaxDiff -0.028022 -0.022610 \n",
1317 | "d3AgoDayPriseRise -0.039825 0.024229 \n",
1318 | "d1AgoTradeVolumeRise 0.978063 0.688219 \n",
1319 | "d1AgoAmountRise 1.000000 0.693801 \n",
1320 | "d1AgoTransactionRise 0.693801 1.000000 \n",
1321 | "d2AgoTradeVolumeRise -0.274630 -0.238947 \n",
1322 | "d2AgoAmountRise -0.268987 -0.238692 \n",
1323 | "d2AgoTransactionRise -0.222139 -0.269161 \n",
1324 | "\n",
1325 | " d2AgoTradeVolumeRise d2AgoAmountRise \\\n",
1326 | "dDayPriseRise -0.008501 0.007142 \n",
1327 | "dDayClosingDiff -0.022222 -0.016792 \n",
1328 | "d1TradeVolume 0.041215 0.042810 \n",
1329 | "d1Amount 0.043768 0.043257 \n",
1330 | "d1OpeningPrice 0.022138 0.023496 \n",
1331 | "d1AgoHighestPrice 0.021901 0.023109 \n",
1332 | "d1AgoLowestPrice 0.022114 0.023378 \n",
1333 | "d1AgoClosingPrice 0.022506 0.023605 \n",
1334 | "d1AgoClosingDiff 0.033979 0.026431 \n",
1335 | "d1AgoTransaction 0.023165 0.021230 \n",
1336 | "d1AgoMaxDiff 0.002816 0.001734 \n",
1337 | "d1AgoDayPriseRise 0.068881 0.056877 \n",
1338 | "d2TradeVolume 0.296696 0.297883 \n",
1339 | "d2Amount 0.302871 0.304166 \n",
1340 | "d2OpeningPrice 0.021265 0.022718 \n",
1341 | "d2AgoHighestPrice 0.022900 0.024718 \n",
1342 | "d2AgoLowestPrice 0.019501 0.020803 \n",
1343 | "d2AgoClosingPrice 0.020859 0.022331 \n",
1344 | "d2AgoClosingDiff -0.032911 -0.016352 \n",
1345 | "d2AgoTransaction 0.238803 0.239118 \n",
1346 | "d2AgoMaxDiff 0.104274 0.119444 \n",
1347 | "d2AgoDayPriseRise 0.002554 0.023720 \n",
1348 | "d3TradeVolume -0.306334 -0.304776 \n",
1349 | "d3Amount -0.298288 -0.297028 \n",
1350 | "d3OpeningPrice 0.023797 0.024157 \n",
1351 | "d3AgoHighestPrice 0.020531 0.021097 \n",
1352 | "d3AgoLowestPrice 0.025814 0.026309 \n",
1353 | "d3AgoClosingPrice 0.022513 0.023144 \n",
1354 | "d3AgoClosingDiff -0.005597 0.003209 \n",
1355 | "d3AgoTransaction -0.219041 -0.218269 \n",
1356 | "d3AgoMaxDiff -0.139327 -0.137119 \n",
1357 | "d3AgoDayPriseRise -0.033321 -0.039825 \n",
1358 | "d1AgoTradeVolumeRise -0.280548 -0.274630 \n",
1359 | "d1AgoAmountRise -0.274630 -0.268987 \n",
1360 | "d1AgoTransactionRise -0.238947 -0.238692 \n",
1361 | "d2AgoTradeVolumeRise 1.000000 0.978063 \n",
1362 | "d2AgoAmountRise 0.978063 1.000000 \n",
1363 | "d2AgoTransactionRise 0.688219 0.693801 \n",
1364 | "\n",
1365 | " d2AgoTransactionRise \n",
1366 | "dDayPriseRise -0.011731 \n",
1367 | "dDayClosingDiff -0.014523 \n",
1368 | "d1TradeVolume 0.064892 \n",
1369 | "d1Amount 0.051107 \n",
1370 | "d1OpeningPrice -0.008444 \n",
1371 | "d1AgoHighestPrice -0.008009 \n",
1372 | "d1AgoLowestPrice -0.010058 \n",
1373 | "d1AgoClosingPrice -0.008629 \n",
1374 | "d1AgoClosingDiff 0.017356 \n",
1375 | "d1AgoTransaction 0.016530 \n",
1376 | "d1AgoMaxDiff 0.054168 \n",
1377 | "d1AgoDayPriseRise 0.043534 \n",
1378 | "d2TradeVolume 0.271782 \n",
1379 | "d2Amount 0.268642 \n",
1380 | "d2OpeningPrice -0.007355 \n",
1381 | "d2AgoHighestPrice -0.006404 \n",
1382 | "d2AgoLowestPrice -0.010827 \n",
1383 | "d2AgoClosingPrice -0.009695 \n",
1384 | "d2AgoClosingDiff -0.100324 \n",
1385 | "d2AgoTransaction 0.251075 \n",
1386 | "d2AgoMaxDiff 0.121124 \n",
1387 | "d2AgoDayPriseRise -0.055944 \n",
1388 | "d3TradeVolume -0.252622 \n",
1389 | "d3Amount -0.257038 \n",
1390 | "d3OpeningPrice -0.004121 \n",
1391 | "d3AgoHighestPrice -0.006634 \n",
1392 | "d3AgoLowestPrice -0.001202 \n",
1393 | "d3AgoClosingPrice -0.004397 \n",
1394 | "d3AgoClosingDiff 0.022108 \n",
1395 | "d3AgoTransaction -0.250675 \n",
1396 | "d3AgoMaxDiff -0.154478 \n",
1397 | "d3AgoDayPriseRise -0.031045 \n",
1398 | "d1AgoTradeVolumeRise -0.227909 \n",
1399 | "d1AgoAmountRise -0.222139 \n",
1400 | "d1AgoTransactionRise -0.269161 \n",
1401 | "d2AgoTradeVolumeRise 0.688219 \n",
1402 | "d2AgoAmountRise 0.693801 \n",
1403 | "d2AgoTransactionRise 1.000000 \n",
1404 | "\n",
1405 | "[38 rows x 38 columns]"
1406 | ]
1407 | },
1408 | "execution_count": 10,
1409 | "metadata": {},
1410 | "output_type": "execute_result"
1411 | }
1412 | ],
1413 | "source": [
1414 | "df.corr()"
1415 | ]
1416 | },
1417 | {
1418 | "cell_type": "code",
1419 | "execution_count": 34,
1420 | "id": "e3dbc69a",
1421 | "metadata": {},
1422 | "outputs": [],
1423 | "source": [
1424 | "trainings = []\n",
1425 | "tests = []\n",
1426 | "\n",
1427 | "for i in range(0, df.count()[0]-151):\n",
1428 | " trainings.append(df[i+1:i+151])\n",
1429 | " tests.append(df[i:i+1])\n",
1430 | " "
1431 | ]
1432 | },
1433 | {
1434 | "cell_type": "code",
1435 | "execution_count": null,
1436 | "id": "234105dc",
1437 | "metadata": {},
1438 | "outputs": [],
1439 | "source": [
1440 | "from sklearn.naive_bayes import GaussianNB\n",
1441 | "from sklearn.linear_model import LogisticRegression\n",
1442 | "from sklearn.model_selection import train_test_split\n",
1443 | "from sklearn.preprocessing import StandardScaler\n",
1444 | "from sklearn.ensemble import RandomForestClassifier\n",
1445 | "\n",
1446 | "# X_train, X_test, y_train, y_test = train_test_split(scaled[train_target], scaled['dDayPriseRise'], test_size=0.6, random_state=0, stratify=scaled['dDayPriseRise'])\n",
1447 | "gnb = GaussianNB()\n",
1448 | "lgr = LogisticRegression()\n",
1449 | "clf = RandomForestClassifier(max_depth=2, n_estimators=100, random_state=0)\n",
1450 | "trainings_len = len(trainings)\n",
1451 | "true_positive = 0\n",
1452 | "false_positive = 0\n",
1453 | "true_negative = 0\n",
1454 | "false_negative = 0\n",
1455 | "true_count = 0\n",
1456 | "\n",
1457 | "scale_target = [\n",
1458 | " # day1\n",
1459 | " 'd1TradeVolume',\n",
1460 | " 'd1Amount',\n",
1461 | " 'd1OpeningPrice',\n",
1462 | " 'd1AgoHighestPrice',\n",
1463 | " 'd1AgoLowestPrice',\n",
1464 | " 'd1AgoClosingPrice',\n",
1465 | " 'd1AgoClosingDiff',\n",
1466 | " 'd1AgoTransaction',\n",
1467 | " 'd1AgoMaxDiff',\n",
1468 | " # day2\n",
1469 | " 'd2TradeVolume',\n",
1470 | " 'd2Amount',\n",
1471 | " 'd2OpeningPrice',\n",
1472 | " 'd2AgoHighestPrice',\n",
1473 | " 'd2AgoLowestPrice',\n",
1474 | " 'd2AgoClosingPrice',\n",
1475 | " 'd2AgoClosingDiff',\n",
1476 | " 'd2AgoTransaction',\n",
1477 | " 'd2AgoMaxDiff',\n",
1478 | " # day3\n",
1479 | " 'd3TradeVolume',\n",
1480 | " 'd3Amount',\n",
1481 | " 'd3OpeningPrice',\n",
1482 | " 'd3AgoHighestPrice',\n",
1483 | " 'd3AgoLowestPrice',\n",
1484 | " 'd3AgoClosingPrice',\n",
1485 | " 'd3AgoClosingDiff',\n",
1486 | " 'd3AgoTransaction',\n",
1487 | " 'd3AgoMaxDiff',\n",
1488 | "]\n",
1489 | "\n",
1490 | "train_target = [\n",
1491 | "# # day1\n",
1492 | "# 'd1TradeVolume',\n",
1493 | "# 'd1Amount',\n",
1494 | "# 'd1OpeningPrice',\n",
1495 | "# 'd1AgoHighestPrice',\n",
1496 | "# 'd1AgoLowestPrice',\n",
1497 | "# 'd1AgoClosingPrice',\n",
1498 | "# 'd1AgoClosingDiff',\n",
1499 | "# 'd1AgoTransaction',\n",
1500 | "# 'd1AgoMaxDiff',\n",
1501 | "# 'd1AgoDayPriseRise',\n",
1502 | "# # day2\n",
1503 | "# 'd2TradeVolume',\n",
1504 | "# 'd2Amount',\n",
1505 | "# 'd2OpeningPrice',\n",
1506 | "# 'd2AgoHighestPrice',\n",
1507 | "# 'd2AgoLowestPrice',\n",
1508 | "# 'd2AgoClosingPrice',\n",
1509 | "# 'd2AgoClosingDiff',\n",
1510 | "# 'd2AgoTransaction',\n",
1511 | "# 'd2AgoMaxDiff',\n",
1512 | "# 'd2AgoDayPriseRise',\n",
1513 | "# # day3\n",
1514 | "# 'd3TradeVolume',\n",
1515 | "# 'd3Amount',\n",
1516 | "# 'd3OpeningPrice',\n",
1517 | "# 'd3AgoHighestPrice',\n",
1518 | "# 'd3AgoLowestPrice',\n",
1519 | "# 'd3AgoClosingPrice',\n",
1520 | "# 'd3AgoClosingDiff',\n",
1521 | "# 'd3AgoTransaction',\n",
1522 | "# 'd3AgoMaxDiff',\n",
1523 | "# 'd3AgoDayPriseRise',\n",
1524 | " # rise\n",
1525 | " 'd1AgoTradeVolumeRise',\n",
1526 | "# 'd1AgoAmountRise',\n",
1527 | "# 'd1AgoTransactionRise'\n",
1528 | "]\n",
1529 | "\n",
1530 | "for i in range(0, trainings_len):\n",
1531 | "# for i in range(0, 1):\n",
1532 | " training = trainings[i]\n",
1533 | " test = tests[i]\n",
1534 | " scale = StandardScaler()\n",
1535 | " \n",
1536 | " train_scaled = pd.DataFrame(scale.fit_transform(training[scale_target]), columns=scale_target, index=training.index)\n",
1537 | " train_scaled['dDayPriseRise'] = training['dDayPriseRise']\n",
1538 | " train_scaled['d1AgoDayPriseRise'] = training['d1AgoDayPriseRise']\n",
1539 | " train_scaled['d1AgoTradeVolumeRise'] = training['d1AgoTradeVolumeRise']\n",
1540 | " train_scaled['d1AgoAmountRise'] = training['d1AgoAmountRise']\n",
1541 | " train_scaled['d1AgoTransactionRise'] = training['d1AgoTransactionRise']\n",
1542 | " train_scaled['d2AgoDayPriseRise'] = training['d2AgoDayPriseRise']\n",
1543 | " train_scaled['d3AgoDayPriseRise'] = training['d3AgoDayPriseRise']\n",
1544 | "\n",
1545 | "\n",
1546 | " test_scaled = pd.DataFrame(scale.transform(test[scale_target]), columns=scale_target, index=test.index)\n",
1547 | " test_scaled['dDayPriseRise'] = test['dDayPriseRise']\n",
1548 | " test_scaled['d1AgoDayPriseRise'] = test['d1AgoDayPriseRise']\n",
1549 | " test_scaled['d1AgoTradeVolumeRise'] = test['d1AgoTradeVolumeRise']\n",
1550 | " test_scaled['d1AgoAmountRise'] = test['d1AgoAmountRise']\n",
1551 | " test_scaled['d1AgoTransactionRise'] = test['d1AgoTransactionRise']\n",
1552 | " test_scaled['d2AgoDayPriseRise'] = test['d2AgoDayPriseRise']\n",
1553 | " test_scaled['d3AgoDayPriseRise'] = test['d3AgoDayPriseRise']\n",
1554 | "\n",
1555 | "\n",
1556 | " \n",
1557 | " \n",
1558 | " y_test = test_scaled[[\"dDayPriseRise\"]].values[0][0]\n",
1559 | "\n",
1560 | " y_pred = clf.fit(train_scaled[train_target], train_scaled['dDayPriseRise']).predict(test_scaled[train_target])\n",
1561 | " \n",
1562 | " if y_pred == 1:\n",
1563 | " true_positive += 1 if y_test == y_pred else 0\n",
1564 | " false_positive += 1 if y_test != y_pred else 0\n",
1565 | " else:\n",
1566 | " true_negative += 1 if y_test == y_pred else 0\n",
1567 | " false_negative += 1 if y_test != y_pred else 0\n",
1568 | " \n",
1569 | "\n",
1570 | "positive_count = true_positive + false_positive\n",
1571 | "negative_count = true_negative + false_negative\n",
1572 | "\n",
1573 | "\n",
1574 | "print(f'count: {len(trainings)}, accuracy: {(true_positive + true_negative) / trainings_len}')\n",
1575 | "print(f'true_positive: {true_positive}, false_positive: {false_positive}')\n",
1576 | "print(f'true_negative: {true_negative}, false_negative: {false_negative}')\n",
1577 | "\n",
1578 | "print(f'true_positive_rate: {(true_positive/positive_count)}, false_positive_rate: {(false_positive/positive_count)}')\n",
1579 | "print(f'true_positive_rate: {(true_negative/negative_count)}, false_positive_rate: {(false_negative/positive_count)}')\n",
1580 | "\n",
1581 | "\n",
1582 | "\n",
1583 | "# test_count = X_test.shape[0]\n",
1584 | "# print(\"Number of labeled points out of a total %d points : %d\" % (test_count, (y_test == y_pred).sum()))\n",
1585 | "\n",
1586 | "# from sklearn.metrics import confusion_matrix \n",
1587 | "# tn, fp, fn, tp = confusion_matrix(y_test, y_pred).ravel()\n"
1588 | ]
1589 | },
1590 | {
1591 | "cell_type": "markdown",
1592 | "id": "1ebd8df4",
1593 | "metadata": {},
1594 | "source": [
1595 | "150\n",
1596 | "2 only day1 d1AgoTradeVolumeRise\n",
1597 | "\n",
1598 | "\n",
1599 | "2\n",
1600 | "count: 574, accuracy: 0.5348432055749129\n",
1601 | "true_positive: 200, false_positive: 159\n",
1602 | "true_negative: 107, false_negative: 108\n",
1603 | "true_positive_rate: 0.5571030640668524, false_positive_rate: 0.4428969359331476\n",
1604 | "true_positive_rate: 0.49767441860465117, false_positive_rate: 0.3008356545961003\n",
1605 | "\n",
1606 | "\n",
1607 | "3\n",
1608 | "count: 574, accuracy: 0.5087108013937283\n",
1609 | "true_positive: 175, false_positive: 149\n",
1610 | "true_negative: 117, false_negative: 133\n",
1611 | "true_positive_rate: 0.5401234567901234, false_positive_rate: 0.45987654320987653\n",
1612 | "true_positive_rate: 0.468, false_positive_rate: 0.4104938271604938\n",
1613 | "\n",
1614 | "5\n",
1615 | "count: 574, accuracy: 0.5069686411149826\n",
1616 | "true_positive: 170, false_positive: 145\n",
1617 | "true_negative: 121, false_negative: 138\n",
1618 | "true_positive_rate: 0.5396825396825397, false_positive_rate: 0.4603174603174603\n",
1619 | "true_positive_rate: 0.4671814671814672, false_positive_rate: 0.4380952380952381\n",
1620 | "\n",
1621 | "\n",
1622 | "zzzzzzzzzzzz\n",
1623 | "100day clf, dep=2, day2, trade, amount accuracy: 0.5512820512820513\n",
1624 | "count: 624, \n",
1625 | "true_positive: 232, false_positive: 181\n",
1626 | "true_negative: 112, false_negative: 99\n",
1627 | "true_positive_rate: 0.5617433414043583, false_positive_rate: 0.43825665859564167\n",
1628 | "true_positive_rate: 0.5308056872037915, false_positive_rate: 0.2397094430992736\n",
1629 | "\n",
1630 | "100day, day2 clf\n",
1631 | "count: 624\n",
1632 | "true_positive: 186, false_positive: 148\n",
1633 | "true_negative: 145, false_negative: 145\n",
1634 | "true_positive_rate: 0.5568862275449101, false_positive_rate: 0.4431137724550898\n",
1635 | "true_positive_rate: 0.5, false_positive_rate: 0.4341317365269461\n",
1636 | "\n",
1637 | "100day, day2, trade, amount accuracy: 0.5368589743589743\n",
1638 | "clf\n",
1639 | "count: 624\n",
1640 | "true_positive: 220, false_positive: 178\n",
1641 | "true_negative: 115, false_negative: 111\n",
1642 | "true_positive_rate: 0.5527638190954773, false_positive_rate: 0.4472361809045226\n",
1643 | "true_positive_rate: 0.5088495575221239, false_positive_rate: 0.27889447236180903\n",
1644 | "\n"
1645 | ]
1646 | },
1647 | {
1648 | "cell_type": "code",
1649 | "execution_count": 40,
1650 | "id": "abd0b573",
1651 | "metadata": {},
1652 | "outputs": [
1653 | {
1654 | "data": {
1655 | "text/plain": [
1656 | "1"
1657 | ]
1658 | },
1659 | "execution_count": 40,
1660 | "metadata": {},
1661 | "output_type": "execute_result"
1662 | }
1663 | ],
1664 | "source": [
1665 | "y_test"
1666 | ]
1667 | },
1668 | {
1669 | "cell_type": "code",
1670 | "execution_count": 14,
1671 | "id": "8595eb11",
1672 | "metadata": {},
1673 | "outputs": [
1674 | {
1675 | "name": "stdout",
1676 | "output_type": "stream",
1677 | "text": [
1678 | " : pn,pp\n",
1679 | "an: 43, 6\n",
1680 | "ap: 12, 1\n"
1681 | ]
1682 | }
1683 | ],
1684 | "source": [
1685 | "print(f' : pn,pp')\n",
1686 | "print(f'an: {tn}, {fp}')\n",
1687 | "print(f'ap: {fn}, {tp}')"
1688 | ]
1689 | },
1690 | {
1691 | "cell_type": "code",
1692 | "execution_count": 21,
1693 | "id": "20e52c03",
1694 | "metadata": {},
1695 | "outputs": [],
1696 | "source": [
1697 | "from sklearn.model_selection import cross_val_score\n",
1698 | "scores = cross_val_score(lgr, scaled[train_target], scaled['dDayPriseRise'], cv=4, scoring='roc_auc')"
1699 | ]
1700 | },
1701 | {
1702 | "cell_type": "code",
1703 | "execution_count": 22,
1704 | "id": "cd224d5c",
1705 | "metadata": {},
1706 | "outputs": [
1707 | {
1708 | "data": {
1709 | "text/plain": [
1710 | "array([0.59047619, 0.41904762, 0.60833333, 0.73 ])"
1711 | ]
1712 | },
1713 | "execution_count": 22,
1714 | "metadata": {},
1715 | "output_type": "execute_result"
1716 | }
1717 | ],
1718 | "source": [
1719 | "scores"
1720 | ]
1721 | },
1722 | {
1723 | "cell_type": "code",
1724 | "execution_count": null,
1725 | "id": "b9f96d45",
1726 | "metadata": {},
1727 | "outputs": [],
1728 | "source": []
1729 | }
1730 | ],
1731 | "metadata": {
1732 | "kernelspec": {
1733 | "display_name": "Python 3 (ipykernel)",
1734 | "language": "python",
1735 | "name": "python3"
1736 | },
1737 | "language_info": {
1738 | "codemirror_mode": {
1739 | "name": "ipython",
1740 | "version": 3
1741 | },
1742 | "file_extension": ".py",
1743 | "mimetype": "text/x-python",
1744 | "name": "python",
1745 | "nbconvert_exporter": "python",
1746 | "pygments_lexer": "ipython3",
1747 | "version": "3.8.12"
1748 | }
1749 | },
1750 | "nbformat": 4,
1751 | "nbformat_minor": 5
1752 | }
1753 |
--------------------------------------------------------------------------------