Showing
39 changed files
with
728 additions
and
0 deletions
code/stock_pbr_test/.idea/.gitignore
0 → 100644
code/stock_pbr_test/.idea/encodings.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<project version="4"> | ||
3 | + <component name="Encoding"> | ||
4 | + <file url="file://$PROJECT_DIR$/result_kr.csv" charset="x-windows-949" /> | ||
5 | + <file url="file://$PROJECT_DIR$/result_kr1.csv" charset="x-windows-949" /> | ||
6 | + </component> | ||
7 | +</project> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +<component name="InspectionProjectProfileManager"> | ||
2 | + <profile version="1.0"> | ||
3 | + <option name="myName" value="Project Default" /> | ||
4 | + <inspection_tool class="PyChainedComparisonsInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true"> | ||
5 | + <option name="ignoreConstantInTheMiddle" value="true" /> | ||
6 | + </inspection_tool> | ||
7 | + <inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true"> | ||
8 | + <option name="ignoredIdentifiers"> | ||
9 | + <list> | ||
10 | + <option value="str.__setitem__" /> | ||
11 | + <option value="dict.__getitem__" /> | ||
12 | + <option value="list.pop" /> | ||
13 | + <option value="str.__and__" /> | ||
14 | + </list> | ||
15 | + </option> | ||
16 | + </inspection_tool> | ||
17 | + </profile> | ||
18 | +</component> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
code/stock_pbr_test/.idea/misc.xml
0 → 100644
code/stock_pbr_test/.idea/modules.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<project version="4"> | ||
3 | + <component name="ProjectModuleManager"> | ||
4 | + <modules> | ||
5 | + <module fileurl="file://$PROJECT_DIR$/.idea/stock_pbr_test.iml" filepath="$PROJECT_DIR$/.idea/stock_pbr_test.iml" /> | ||
6 | + </modules> | ||
7 | + </component> | ||
8 | +</project> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
code/stock_pbr_test/.idea/stock_pbr_test.iml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<module type="PYTHON_MODULE" version="4"> | ||
3 | + <component name="NewModuleRootManager"> | ||
4 | + <content url="file://$MODULE_DIR$"> | ||
5 | + <excludeFolder url="file://$MODULE_DIR$/venv" /> | ||
6 | + </content> | ||
7 | + <orderEntry type="jdk" jdkName="Python 3.9 (stock_pbr_test)" jdkType="Python SDK" /> | ||
8 | + <orderEntry type="sourceFolder" forTests="false" /> | ||
9 | + </component> | ||
10 | +</module> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
code/stock_pbr_test/.vscode/launch.json
0 → 100644
1 | +{ | ||
2 | + // Use IntelliSense to learn about possible attributes. | ||
3 | + // Hover to view descriptions of existing attributes. | ||
4 | + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
5 | + "version": "0.2.0", | ||
6 | + "configurations": [ | ||
7 | + { | ||
8 | + "name": "Python: Current File", | ||
9 | + "type": "python", | ||
10 | + "request": "launch", | ||
11 | + "program": "${file}", | ||
12 | + "console": "integratedTerminal" | ||
13 | + } | ||
14 | + ] | ||
15 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
code/stock_pbr_test/.vscode/settings.json
0 → 100644
code/stock_pbr_test/DataProvider.py
0 → 100644
1 | +from QuantDB import QuantDB | ||
2 | +from typing import List | ||
3 | + | ||
4 | +class DataProvider: | ||
5 | + DB = None | ||
6 | + | ||
7 | + def __init__(self): | ||
8 | + self.Name = "Default" | ||
9 | + self.DB = QuantDB() | ||
10 | + | ||
11 | + def __repr__(self): | ||
12 | + return self.Name | ||
13 | + | ||
14 | + def initialize(self): | ||
15 | + return self.DB.connect() | ||
16 | + | ||
17 | + def close(self): | ||
18 | + if( self.DB ): | ||
19 | + self.DB.close() | ||
20 | + self.DB = None | ||
21 | + | ||
22 | + def findFS(self, columns: List[str], year: int, quarter: int, div: str): # a: str, b: str, times: int | ||
23 | + if( self.DB ): | ||
24 | + querystring = 'SELECT ' | ||
25 | + for target in columns: | ||
26 | + querystring = querystring + '"' + target + '",' | ||
27 | + querystring = querystring[:-1] | ||
28 | + querystring = querystring + 'from "FinancialStatements" ' + 'WHERE ' + '"Year"=' + str(year) + ' and "Quarter"=' + str(quarter) + ' and "Div"=' + "'" + div + "'" | ||
29 | + return self.DB.searchData(querystring, columns) | ||
30 | + | ||
31 | + def findAllFS(self, columns: List[str], year: int, quarter: int, div: str): | ||
32 | + if( self.DB ): | ||
33 | + querystring = 'SELECT ' | ||
34 | + for target in columns: | ||
35 | + querystring = querystring + '"' + target + '",' | ||
36 | + querystring = querystring[:-1] | ||
37 | + querystring = querystring + 'from "FinancialStatements" ' + 'WHERE ' + '"Year"=' + str(year) + ' and "Quarter"=' + str(quarter) + ' and "Div"=' + "'" + div + "'" | ||
38 | + return self.DB.searchData(querystring, columns) | ||
39 | + | ||
40 | + def findOneFS(self, columns: List[str], stockcode: str, year: int, quarter: int, div: str): | ||
41 | + if( self.DB ): | ||
42 | + querystring = 'SELECT ' | ||
43 | + for target in columns: | ||
44 | + querystring = querystring + '"' + target + '",' | ||
45 | + querystring = querystring[:-1] | ||
46 | + querystring = querystring + 'from "FinancialStatements" ' + 'WHERE ' + '"id"=' + "'" + stockcode + str(year) + str(quarter) + div + "'" | ||
47 | + return self.DB.searchData(querystring, columns) | ||
48 | + | ||
49 | + def findSPbyID(self, columns: List[str], stockcode: str, stockdate: str): | ||
50 | + if( self.DB ): | ||
51 | + querystring = 'SELECT ' | ||
52 | + for target in columns: | ||
53 | + querystring = querystring + '"' + target + '",' | ||
54 | + querystring = querystring[:-1] | ||
55 | + querystring = querystring + 'from "StockPrice" ' + 'WHERE ' + '"id"=' + "'" + stockcode + stockdate + "'" | ||
56 | + return self.DB.searchData(querystring, columns) | ||
57 | + | ||
58 | + def findSP(self, columns: List[str], stockcode: str, stock_startdate: str, stock_enddate: str): | ||
59 | + if( self.DB ): | ||
60 | + querystring = 'SELECT ' | ||
61 | + for target in columns: | ||
62 | + querystring = querystring + '"' + target + '",' | ||
63 | + querystring = querystring[:-1] | ||
64 | + querystring = querystring + 'from "StockPrice" ' + 'WHERE ' + '"StockCode"=' + "'" + stockcode + "'" ' and "StockDate" >= ' + "'" + stock_startdate + "'" + ' and "StockDate" <= ' + "'" + stock_enddate + "' order by id asc" | ||
65 | + return self.DB.searchData(querystring, columns) | ||
66 | + | ||
67 | + def findCompany(self, columns: List[str], stockcode: str): | ||
68 | + if( self.DB ): | ||
69 | + querystring = 'SELECT ' | ||
70 | + for target in columns: | ||
71 | + querystring = querystring + '"' + target + '",' | ||
72 | + querystring = querystring[:-1] | ||
73 | + querystring = querystring + 'from "Company" ' + 'WHERE ' + '"StockCode"=' + "'" + stockcode + "'" | ||
74 | + return self.DB.searchData(querystring, columns) | ||
75 | + | ||
76 | + def findStockName(self, stockcode: str): | ||
77 | + if( self.DB ): | ||
78 | + df_comapanys = self.findCompany(["StockName"], stockcode) | ||
79 | + if df_comapanys is None : | ||
80 | + return '' | ||
81 | + else : | ||
82 | + return df_comapanys["StockName"][0] | ||
83 | + | ||
84 | + | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +from datetime import date | ||
2 | +import pandas as pd | ||
3 | +import sys | ||
4 | +from Investment.Strategy.StrategyBase import StrategyBase | ||
5 | + | ||
6 | + | ||
7 | +class FinancialStatementsStrategyBase(StrategyBase): | ||
8 | + AdditionalFinancialStatementsItem = [] | ||
9 | + FinancialStatementsCondition = '' | ||
10 | + FinancialStatementsYear = 2017 | ||
11 | + FinancialStatementsQuater = 1 | ||
12 | + FinancialStatementsDiv = 'CFS' | ||
13 | + StockDate = date.today() | ||
14 | + DataSearchStartDate = date.today() | ||
15 | + DataSearchEndDate = date.today() | ||
16 | + FinancialStatementsSearchTarget = [] | ||
17 | + StockSearchTarget = [] | ||
18 | + FinancialStatementsOrderBy = [] | ||
19 | + FinancialStatementsOrderMethod = '' | ||
20 | + | ||
21 | + df_fs = None | ||
22 | + df_stock = None | ||
23 | + df_company = None | ||
24 | + | ||
25 | + def __init__(self): | ||
26 | + super().__init__() | ||
27 | + self.Division = "FinancialStatements" | ||
28 | + | ||
29 | + def __repr__(self): | ||
30 | + return self.Name | ||
31 | + | ||
32 | + def setStrategy(self): | ||
33 | + super().setStrategy() | ||
34 | + | ||
35 | + def searchData(self): | ||
36 | + try: | ||
37 | + if self.df_fs is None: | ||
38 | + self.df_fs = self.db.findFS(self.FinancialStatementsSearchTarget, self.FinancialStatementsYear, | ||
39 | + self.FinancialStatementsQuater, self.FinancialStatementsDiv) | ||
40 | + if self.df_fs is None: | ||
41 | + print('db query error') | ||
42 | + sys.exit(1) | ||
43 | + except: | ||
44 | + print("Unexpected error:", sys.exc_info()[0]) | ||
45 | + return False | ||
46 | + return True | ||
47 | + | ||
48 | + def setAdditionalData(self): | ||
49 | + try: | ||
50 | + for item in self.AdditionalFinancialStatementsItem: | ||
51 | + self.df_fs[item] = 0 | ||
52 | + for item in self.StockSearchTarget: | ||
53 | + self.df_fs[item] = 0 | ||
54 | + | ||
55 | + for index, row in self.df_fs.iterrows(): | ||
56 | + self.df_stock = self.db.findSPbyID(self.StockSearchTarget, row['StockCode'], | ||
57 | + self.StockDate.strftime("%Y-%m-%d")) | ||
58 | + if self.df_stock is None: | ||
59 | + print('db query error') | ||
60 | + else: | ||
61 | + if self.df_stock.size < 1: | ||
62 | + continue | ||
63 | + for item in self.StockSearchTarget: | ||
64 | + self.df_fs.loc[index, item] = self.df_stock[item][0] | ||
65 | + | ||
66 | + for item in self.AdditionalFinancialStatementsItem: | ||
67 | + if item == 'PER': | ||
68 | + if row["ProfitLoss"] != 0: | ||
69 | + self.df_fs.loc[index, item] = self.df_fs.loc[index, 'MarketCapitalization'] / row[ | ||
70 | + "ProfitLoss"] | ||
71 | + elif item == 'PBR': | ||
72 | + if row["Equity"] != 0: | ||
73 | + self.df_fs.loc[index, item] = self.df_fs.loc[index, 'MarketCapitalization'] / row[ | ||
74 | + "Equity"] | ||
75 | + elif item == 'ROE': | ||
76 | + if row["Equity"] != 0: | ||
77 | + self.df_fs.loc[index, item] = float(row["ProfitLoss"]) / float( | ||
78 | + row["Equity"]) * 100.00 | ||
79 | + asc = True | ||
80 | + if self.FinancialStatementsOrderMethod == 'asc': | ||
81 | + asc = True | ||
82 | + elif self.FinancialStatementsOrderMethod == 'desc': | ||
83 | + asc = False | ||
84 | + self.df_all = self.df_fs.query(self.FinancialStatementsCondition).sort_values( | ||
85 | + by=self.FinancialStatementsOrderBy, ascending=asc).head(self.NumberOfStocks) | ||
86 | + self.df_all.insert(1, 'StockName', '') | ||
87 | + self.df_all['StockName'] = '' | ||
88 | + | ||
89 | + for index, row in self.df_all.iterrows(): | ||
90 | + self.df_all.loc[index, "StockName"] = self.db.findStockName(row['StockCode']) | ||
91 | + | ||
92 | + except: | ||
93 | + print("Unexpected error:", sys.exc_info()[0]) | ||
94 | + return False | ||
95 | + return True |
1 | +from datetime import date | ||
2 | + | ||
3 | +class StrategyBase: | ||
4 | + Name = '' | ||
5 | + Division = '' | ||
6 | + NumberOfStocks = 0 | ||
7 | + DataSearchStartDate = date.today() | ||
8 | + DataSearchEndDate = date.today() | ||
9 | + | ||
10 | + df_all = None | ||
11 | + db = None | ||
12 | + | ||
13 | + def __init__(self): | ||
14 | + self.Name = 'Base' | ||
15 | + | ||
16 | + def __repr__(self): | ||
17 | + return self.Name | ||
18 | + | ||
19 | + def setStrategy(self): | ||
20 | + print('setStrategy') | ||
21 | + | ||
22 | + def searchData(self): | ||
23 | + print('searchData') | ||
24 | + | ||
25 | + def setAdditionalData(self): | ||
26 | + print('setAdditionalData') | ||
27 | + | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
File mode changed
code/stock_pbr_test/Investment/Strategy/__pycache__/FinancialStatementsStrategyBase.cpython-39.pyc
0 → 100644
No preview for this file type
No preview for this file type
No preview for this file type
1 | +import pandas as pd | ||
2 | + | ||
3 | +class TradingBase: | ||
4 | + Name = '' | ||
5 | + TotalInvestmentAmount = 0 | ||
6 | + Method = "Split evenly" | ||
7 | + BuyingMethod = 1 # 1 : at_once | ||
8 | + BuyingDateTime = [] # datetime | ||
9 | + SellDateTime = [] # datetime | ||
10 | + NumberOfStocks = 10 | ||
11 | + PriceDiv = "Open" | ||
12 | + StockBuyingSearchTarget = [] | ||
13 | + StockSellSearchTarget = [] | ||
14 | + | ||
15 | + df_all = None | ||
16 | + df_stock = None | ||
17 | + db = None | ||
18 | + | ||
19 | + def __init__(self): | ||
20 | + self.Name = 'Base' | ||
21 | + | ||
22 | + def __repr__(self): | ||
23 | + return self.Name | ||
24 | + | ||
25 | + def setTrading(self): | ||
26 | + print("setTrading") | ||
27 | + | ||
28 | + def doTrading(self): | ||
29 | + self.df_all['BuyingPrice'] = 0 | ||
30 | + self.df_all['SellPrice'] = 0 | ||
31 | + self.df_all['BuyingAmount'] = 0 | ||
32 | + | ||
33 | + if self.Method == 1: # "Split evenly" | ||
34 | + if self.BuyingMethod == 1: | ||
35 | + investmentAmount = self.TotalInvestmentAmount / self.NumberOfStocks | ||
36 | + for index, row in self.df_all.iterrows(): | ||
37 | + self.df_stock = self.db.findSPbyID(self.StockBuyingSearchTarget, self.df_all.loc[index, 'StockCode'], self.BuyingDateTime[0].strftime("%Y-%m-%d")) | ||
38 | + if self.df_stock is None : | ||
39 | + print('db query error') | ||
40 | + else: | ||
41 | + if self.df_stock.size < 1 : | ||
42 | + continue | ||
43 | + buyingPrice = self.df_stock[self.StockBuyingSearchTarget[0]][0] | ||
44 | + | ||
45 | + self.df_stock = self.db.findSPbyID(self.StockSellSearchTarget, self.df_all.loc[index, 'StockCode'], self.SellDateTime[0].strftime("%Y-%m-%d")) | ||
46 | + if self.df_stock is None : | ||
47 | + print('db query error') | ||
48 | + else: | ||
49 | + if self.df_stock.size < 1 : | ||
50 | + continue | ||
51 | + sellPrice = self.df_stock[self.StockSellSearchTarget[0]][0] | ||
52 | + | ||
53 | + self.df_all.loc[index, 'BuyingPrice'] = buyingPrice | ||
54 | + self.df_all.loc[index, 'SellPrice'] = sellPrice | ||
55 | + self.df_all.loc[index, 'BuyingAmount'] = int(investmentAmount / buyingPrice) | ||
56 | + | ||
57 | + | ||
58 | + elif self.BuyingMethod == 2: | ||
59 | + print('...') | ||
60 | + else: | ||
61 | + print('...') | ||
62 | + else: | ||
63 | + print('...') | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
File mode changed
No preview for this file type
No preview for this file type
1 | +import pandas as pd | ||
2 | +import json | ||
3 | + | ||
4 | + | ||
5 | +class VerificationBase: | ||
6 | + Name = '' | ||
7 | + TotalInvestmentAmount = 0 | ||
8 | + Balance: int = 0 | ||
9 | + Yield: float = 0 | ||
10 | + | ||
11 | + df_all = None # type: pd | ||
12 | + db = None | ||
13 | + | ||
14 | + def __init__(self): | ||
15 | + self.Name = 'Base' | ||
16 | + | ||
17 | + def __repr__(self): | ||
18 | + return self.Name | ||
19 | + | ||
20 | + def setVerification(self): | ||
21 | + print("setVerification") | ||
22 | + | ||
23 | + def doVerification(self): | ||
24 | + self.df_all['ProfitLossByStock'] = 0 | ||
25 | + self.df_all['InvestmentAmount'] = 0 | ||
26 | + self.df_all['Balance'] = 0 | ||
27 | + self.df_all['Yield'] = 0 | ||
28 | + | ||
29 | + for index, row in self.df_all.iterrows(): | ||
30 | + buyingPrice = self.df_all.loc[index, 'BuyingPrice'] | ||
31 | + sellPrice = self.df_all.loc[index, 'SellPrice'] | ||
32 | + investmentCurrentAmount = self.df_all.loc[index, 'BuyingAmount'] * buyingPrice | ||
33 | + self.df_all.loc[index, 'ProfitLossByStock'] = sellPrice - buyingPrice | ||
34 | + self.df_all.loc[index, 'InvestmentAmount'] = investmentCurrentAmount | ||
35 | + self.df_all.loc[index, 'Balance'] = investmentCurrentAmount + self.df_all.loc[index, 'ProfitLossByStock'] * \ | ||
36 | + self.df_all.loc[index, 'BuyingAmount'] | ||
37 | + self.df_all.loc[index, 'Yield'] = (float(self.df_all.loc[index, 'Balance']) - float( | ||
38 | + investmentCurrentAmount)) / float(investmentCurrentAmount) * 100.00 | ||
39 | + | ||
40 | + self.Balance = self.df_all['Balance'].sum() | ||
41 | + investmentCurrentTotalAmount = self.df_all['InvestmentAmount'].sum() | ||
42 | + self.df_all = self.df_all.append(pd.Series(), ignore_index=True) | ||
43 | + self.df_all.loc[len(self.df_all) - 1, 'Balance'] = self.Balance | ||
44 | + self.Yield = ((float(self.Balance) + float(self.TotalInvestmentAmount - investmentCurrentTotalAmount)) - float( | ||
45 | + self.TotalInvestmentAmount)) / float(self.TotalInvestmentAmount) * 100.00 | ||
46 | + self.df_all.loc[len(self.df_all) - 1, 'Yield'] = self.Yield | ||
47 | + | ||
48 | + def saveResult(self): | ||
49 | + self.df_all.to_csv("result1.csv") | ||
50 | + self.df_all.to_csv("result_kr1.csv", encoding='euc-kr') | ||
51 | + | ||
52 | + def saveResulToJSON(self): | ||
53 | + result = self.df_all.to_json(orient="split") | ||
54 | + parsed = json.loads(result) | ||
55 | + with open("result.json", "w") as text_file: | ||
56 | + text_file.write(json.dumps(parsed, indent=4, ensure_ascii=False)) | ||
57 | + | ||
58 | + def saveSummary(self, record, num): | ||
59 | + self.Yield = round(self.Yield, 5) | ||
60 | + if record[-1] < self.Yield: | ||
61 | + if record[0] == 0: | ||
62 | + record[0] = self.Yield | ||
63 | + else: | ||
64 | + for i in range(5): | ||
65 | + if record[i] == self.Yield: | ||
66 | + return False, 0 | ||
67 | + elif record[i] < self.Yield: | ||
68 | + record.insert(i, self.Yield) | ||
69 | + break | ||
70 | + if len(record) > 5: | ||
71 | + record.pop() | ||
72 | + jsonobj = {"TotalInvestmentAmount": str(self.TotalInvestmentAmount), "Balance": str(self.Balance), | ||
73 | + "Yield": str(self.Yield)} | ||
74 | + with open(f"result_summary{num}.json", "w") as text_file: | ||
75 | + text_file.write(json.dumps(jsonobj, indent=4)) | ||
76 | + return True, self.Yield | ||
77 | + return False, 0 |
File mode changed
No preview for this file type
No preview for this file type
code/stock_pbr_test/Investment/__init__.py
0 → 100644
File mode changed
No preview for this file type
code/stock_pbr_test/QuantDB.py
0 → 100644
1 | +import psycopg2 | ||
2 | +import pandas as pd | ||
3 | +from typing import List | ||
4 | + | ||
5 | +class QuantDB: | ||
6 | + Name = 'Base' | ||
7 | + Conn = None | ||
8 | + ConnectionStr = 'host=aifactory-test.cp90w5j6b2ld.ap-northeast-2.rds.amazonaws.com dbname=QuantDB user=quantdb password=quantdb' | ||
9 | + | ||
10 | + def __init__(self): | ||
11 | + self.Name = "Default" | ||
12 | + | ||
13 | + def __repr__(self): | ||
14 | + return self.Name | ||
15 | + | ||
16 | + def connect(self): | ||
17 | + self.Conn = None | ||
18 | + try: | ||
19 | + self.Conn = psycopg2.connect(self.ConnectionStr) | ||
20 | + except (Exception, psycopg2.DatabaseError) as error: | ||
21 | + print(error) | ||
22 | + return False | ||
23 | + return True | ||
24 | + def searchData(self, query: str, columns: List[str]): | ||
25 | + cursor = self.Conn.cursor() | ||
26 | + try: | ||
27 | + cursor.execute(query) | ||
28 | + except (Exception, psycopg2.DatabaseError) as error: | ||
29 | + print(error) | ||
30 | + cursor.close() | ||
31 | + return None | ||
32 | + tupples = cursor.fetchall() | ||
33 | + cursor.close() | ||
34 | + df = pd.DataFrame(tupples, columns=columns) | ||
35 | + return df | ||
36 | + | ||
37 | + def searchDataOneRow(self, query: str): | ||
38 | + cursor = self.Conn.cursor() | ||
39 | + try: | ||
40 | + cursor.execute(query) | ||
41 | + except (Exception, psycopg2.DatabaseError) as error: | ||
42 | + print(error) | ||
43 | + cursor.close() | ||
44 | + return None | ||
45 | + row = cursor.fetchone() | ||
46 | + cursor.close() | ||
47 | + return row[0] | ||
48 | + | ||
49 | + def close(self): | ||
50 | + self.Conn.close() | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
code/stock_pbr_test/Strategy.py
0 → 100644
1 | +from Investment.Strategy.StrategyBase import StrategyBase | ||
2 | +from Investment.Strategy.FinancialStatementsStrategyBase import FinancialStatementsStrategyBase | ||
3 | +from datetime import date | ||
4 | + | ||
5 | + | ||
6 | +class Strategy(FinancialStatementsStrategyBase): | ||
7 | + def __init__(self): | ||
8 | + super().__init__() | ||
9 | + | ||
10 | + def __repr__(self): | ||
11 | + return self.Name | ||
12 | + | ||
13 | + def setStrategy(self, per=None, pbr_up=None, pbr_down=None, roe=None, order='PER'): | ||
14 | + super().setStrategy() | ||
15 | + self.Name = 'PER_ROE_V1.0' | ||
16 | + self.NumberOfStocks = 10 | ||
17 | + self.AdditionalFinancialStatementsItem = ['PER', 'PBR', 'ROE'] | ||
18 | + # self.FinancialStatementsCondition = '(PER > 6) and (ROE > 10) and (PBR > 0.5) and (PBR < 1)' | ||
19 | + self.setFinancialStatementsCondition(per, pbr_up, pbr_down, roe) | ||
20 | + print(self.FinancialStatementsCondition) | ||
21 | + # self.FinancialStatementsCondition = '(PER > 0) and (PER < 20) and (ROE > 10)' | ||
22 | + # self.FinancialStatementsCondition = '(PBR < 1)' | ||
23 | + self.FinancialStatementsYear = 2016 | ||
24 | + self.FinancialStatementsQuater = 4 | ||
25 | + self.FinancialStatementsDiv = 'CFS' | ||
26 | + self.StockDate = date(2017, 4, 10) | ||
27 | + self.FinancialStatementsSearchTarget = ['StockCode', 'Equity', 'ProfitLoss'] | ||
28 | + self.StockSearchTarget = ['MarketCapitalization'] | ||
29 | + self.FinancialStatementsOrderBy = [order] | ||
30 | + if order == 'PER': | ||
31 | + self.FinancialStatementsOrderMethod = 'asc' | ||
32 | + else: | ||
33 | + self.FinancialStatementsOrderMethod = 'desc' | ||
34 | + # self.FinancialStatementsOrderBy.append('ROE') | ||
35 | + # self.FinancialStatementsOrderMethod = 'desc' | ||
36 | + | ||
37 | + def setFinancialStatementsCondition(self, per, pbr_up, pbr_down, roe): | ||
38 | + self.FinancialStatementsCondition = '' | ||
39 | + if per is not None: | ||
40 | + self.FinancialStatementsCondition += f'(PER > {per})' | ||
41 | + if pbr_up: | ||
42 | + if len(self.FinancialStatementsCondition) == 0: | ||
43 | + self.FinancialStatementsCondition += f'(PBR > {pbr_up})' | ||
44 | + else: | ||
45 | + self.FinancialStatementsCondition += f' and (PBR > {pbr_up})' | ||
46 | + if pbr_down: | ||
47 | + if len(self.FinancialStatementsCondition) == 0: | ||
48 | + self.FinancialStatementsCondition += f'(PBR < {pbr_down})' | ||
49 | + else: | ||
50 | + self.FinancialStatementsCondition += f' and (PBR < {pbr_down})' | ||
51 | + if roe: | ||
52 | + if len(self.FinancialStatementsCondition) == 0: | ||
53 | + self.FinancialStatementsCondition += f'(ROE > {roe})' | ||
54 | + else: | ||
55 | + self.FinancialStatementsCondition += f' and (ROE > {roe})' | ||
56 | + | ||
57 | + def searchData(self): | ||
58 | + return FinancialStatementsStrategyBase.searchData(self) | ||
59 | + | ||
60 | + def setAdditionalData(self): | ||
61 | + return FinancialStatementsStrategyBase.setAdditionalData(self) |
code/stock_pbr_test/Trading.py
0 → 100644
1 | +from Investment.Trading.TradingBase import TradingBase | ||
2 | +from datetime import date | ||
3 | + | ||
4 | +class Trading(TradingBase): | ||
5 | + def __init__(self): | ||
6 | + super().__init__ | ||
7 | + | ||
8 | + def __repr__(self): | ||
9 | + return self.Name | ||
10 | + | ||
11 | + def setTrading(self): | ||
12 | + super().setTrading() | ||
13 | + self.Name = 'Split evenly' | ||
14 | + self.TotalInvestmentAmount = 100000000 | ||
15 | + self.Method = 1 # 1 : "Split evenly", | ||
16 | + self.BuyingMethod = 1 # 1 : at once | ||
17 | + self.BuyingDateTime = [date(2017, 4, 10)] | ||
18 | + self.SellDateTime = [date(2018, 4, 16)] | ||
19 | + self.NumberOfStocks = 10 | ||
20 | + self.PriceDiv = 'Open' | ||
21 | + self.StockBuyingSearchTarget = ['Open'] | ||
22 | + self.StockSellSearchTarget = ['Open'] | ||
23 | + | ||
24 | + def doTrading(self): | ||
25 | + return super().doTrading() | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
code/stock_pbr_test/Verification.py
0 → 100644
1 | +from Investment.Verification.VerificationBase import VerificationBase | ||
2 | +from datetime import date | ||
3 | + | ||
4 | + | ||
5 | +class Verification(VerificationBase): | ||
6 | + def __init__(self): | ||
7 | + super().__init__ | ||
8 | + | ||
9 | + def __repr__(self): | ||
10 | + return self.Name | ||
11 | + | ||
12 | + def setVerification(self): | ||
13 | + super().setVerification() | ||
14 | + | ||
15 | + def doVerification(self): | ||
16 | + return super().doVerification() | ||
17 | + | ||
18 | + def saveResult(self): | ||
19 | + return super().saveResult() | ||
20 | + | ||
21 | + def saveResulToJSON(self): | ||
22 | + return super().saveResulToJSON() | ||
23 | + | ||
24 | + def saveSummary(self, record, num): | ||
25 | + return super().saveSummary(record, num) |
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
code/stock_pbr_test/main.py
0 → 100644
1 | +import datetime | ||
2 | +import Strategy | ||
3 | +import Trading | ||
4 | +import Verification | ||
5 | +import sys | ||
6 | +import DataProvider | ||
7 | + | ||
8 | + | ||
9 | +def single(): | ||
10 | + record = [0] | ||
11 | + # record = [18.91309, 17.8967, 17.14154, 16.07653, 16.03074] | ||
12 | + strategy_record = [[3, 0.7000000000000001, 10, 18.91309], [3, 0.7000000000000001, 11, 17.8967], | ||
13 | + [3, 0.8, 11, 17.14154], [4, 0.7000000000000001, 11, 16.07653], | ||
14 | + [3, 0.7000000000000001, 5, 16.03074]] | ||
15 | + st = Strategy.Strategy() | ||
16 | + tr = Trading.Trading() | ||
17 | + ve = Verification.Verification() | ||
18 | + db = DataProvider.DataProvider() | ||
19 | + if db.initialize(): | ||
20 | + print('db connection') | ||
21 | + # print(db.findSP(['StockDate','Open'], '004990', '2019-04-11', '2019-12-31')) | ||
22 | + st.db = db | ||
23 | + st.setStrategy(10, 0, 1.5, 0) | ||
24 | + if (st.searchData() == False): | ||
25 | + print("st.searchData error") | ||
26 | + sys.exit(-1) | ||
27 | + if (st.setAdditionalData() == False): | ||
28 | + print("st.setAdditionalData error") | ||
29 | + sys.exit(-1) | ||
30 | + | ||
31 | + tr.df_all = st.df_all | ||
32 | + tr.db = db | ||
33 | + tr.setTrading() | ||
34 | + if (tr.doTrading() == False): | ||
35 | + print("tr.doTrading error") | ||
36 | + sys.exit(-1) | ||
37 | + | ||
38 | + ve.TotalInvestmentAmount = tr.TotalInvestmentAmount | ||
39 | + ve.df_all = tr.df_all | ||
40 | + | ||
41 | + ve.setVerification() | ||
42 | + ve.doVerification() | ||
43 | + ve.saveResult() | ||
44 | + # ve.saveResulToJSON() | ||
45 | + r, Yield = ve.saveSummary(record, 0) | ||
46 | + else: | ||
47 | + print("db error") | ||
48 | + db.close() | ||
49 | + | ||
50 | + | ||
51 | +def multi(): | ||
52 | + start = datetime.datetime.now() | ||
53 | + record = [0] | ||
54 | + strategy_record = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] | ||
55 | + num = 0 | ||
56 | + st = Strategy.Strategy() | ||
57 | + tr = Trading.Trading() | ||
58 | + ve = Verification.Verification() | ||
59 | + db = DataProvider.DataProvider() | ||
60 | + for per in range(8): | ||
61 | + pbr = 1 | ||
62 | + while pbr > 0.3: | ||
63 | + for roe in range(10, 20): | ||
64 | + if db.initialize(): | ||
65 | + print('db connection') | ||
66 | + # print(db.findSP(['StockDate','Open'], '004990', '2019-04-11', '2019-12-31')) | ||
67 | + st.db = db | ||
68 | + else: | ||
69 | + print("db error") | ||
70 | + st.setStrategy(per, pbr, 1.2, roe) | ||
71 | + if (st.searchData() == False): | ||
72 | + print("st.searchData error") | ||
73 | + sys.exit(-1) | ||
74 | + if (st.setAdditionalData() == False): | ||
75 | + print("st.setAdditionalData error") | ||
76 | + sys.exit(-1) | ||
77 | + | ||
78 | + tr.df_all = st.df_all | ||
79 | + tr.db = db | ||
80 | + tr.setTrading() | ||
81 | + if (tr.doTrading() == False): | ||
82 | + print("tr.doTrading error") | ||
83 | + sys.exit(-1) | ||
84 | + | ||
85 | + ve.TotalInvestmentAmount = tr.TotalInvestmentAmount | ||
86 | + ve.df_all = tr.df_all | ||
87 | + ve.setVerification() | ||
88 | + ve.doVerification() | ||
89 | + ve.saveResult() | ||
90 | + # ve.saveResulToJSON() | ||
91 | + r, Yield = ve.saveSummary(record, num) | ||
92 | + if r: | ||
93 | + for i in range(5): | ||
94 | + if strategy_record[i][3] < Yield: | ||
95 | + strategy_record.insert(i, [per, pbr, roe, Yield]) | ||
96 | + break | ||
97 | + strategy_record.pop() | ||
98 | + print(record, strategy_record) | ||
99 | + num += 1 | ||
100 | + pbr -= 0.1 | ||
101 | + db.close() | ||
102 | + end = datetime.datetime.now() | ||
103 | + print('time: ', end - start) | ||
104 | + print(strategy_record) | ||
105 | + | ||
106 | + | ||
107 | +if __name__ == '__main__': | ||
108 | + single() | ||
109 | + # multi() |
code/stock_pbr_test/result.csv
0 → 100644
1 | +,StockCode,StockName,Equity,ProfitLoss,PER,MarketCapitalization,PBR,BuyingPrice,SellPrice,BuyingAmount,ProfitLossByStock,InvestmentAmount,Balance,Yield | ||
2 | +0,002030,아세아,1225090202229.0,67565442549.0,3.171475522336699,214282147200.0,0.17491132229294026,97800.0,125000.0,102.0,27200.0,9975600.0,12750000.0,27.811860940695297 | ||
3 | +1,058650,세아홀딩스,2924149208280.0,161892654956.0,3.1872971639154417,516000000000.0,0.17646158360828446,126000.0,133500.0,79.0,7500.0,9954000.0,10546500.0,5.952380952380952 | ||
4 | +2,001940,KISCO홀딩스,1273968329992.0,77864434261.0,2.956621941518533,230215694800.0,0.18070754930104554,63000.0,65300.0,158.0,2300.0,9954000.0,10317400.0,3.650793650793651 | ||
5 | +3,000880,한화,14227936000000.0,1288691000000.0,2.0445549284118534,2634799535250.0,0.1851849442709048,35700.0,38350.0,280.0,2650.0,9996000.0,10738000.0,7.42296918767507 | ||
6 | +4,007860,서연,1072030023657.0,132366474007.0,1.7827205413624674,235972432200.0,0.22011737264132844,10150.0,6480.0,985.0,-3670.0,9997750.0,6382800.0,-36.1576354679803 | ||
7 | +5,019010,베뉴지,236756098347.0,12783309005.0,4.769735283419287,60973000000.0,0.25753507692391236,12850.0,12800.0,778.0,-50.0,9997300.0,9958400.0,-0.38910505836575876 | ||
8 | +6,092230,KPX홀딩스,936238978408.0,53425479418.0,4.894772873332309,261505587400.0,0.2793149969516004,63000.0,63000.0,158.0,0.0,9954000.0,9954000.0,0.0 | ||
9 | +7,023600,삼보판지,329937058742.0,40288485800.0,2.380332695452158,95900000000.0,0.29066149878904834,6860.0,9790.0,1457.0,2930.0,9995020.0,14264030.0,42.711370262390666 | ||
10 | +8,033160,엠케이전자,593852198159.0,74507668124.0,2.391281644105155,178168819130.0,0.30002215986122605,8360.0,10250.0,1196.0,1890.0,9998560.0,12259000.0,22.607655502392344 | ||
11 | +9,021820,세원정공,569620475934.0,56809840064.0,3.309285852384124,188000000000.0,0.3300443153693494,18350.0,13700.0,544.0,-4650.0,9982400.0,7452800.0,-25.340599455040874 | ||
12 | +10,,,,,,,,,,,,,104622930.0,4.8183 |
code/stock_pbr_test/result_kr.csv
0 → 100644
1 | +,StockCode,StockName,Equity,ProfitLoss,PER,MarketCapitalization,PBR,ROE,BuyingPrice,SellPrice,BuyingAmount,ProfitLossByStock,InvestmentAmount,Balance,Yield | ||
2 | +0,008370,원풍,75070172618.0,5235935528.0,10.049779971240318,52620000000.0,0.7009441721648979,6.974721577694294,4505.0,4050.0,2219.0,-455.0,9996595.0,8986950.0,-10.099889012208656 | ||
3 | +1,119860,다나와,65170505380.0,8935066130.0,10.052978437217229,89824027140.0,1.378292628179708,13.71029130110453,6930.0,17950.0,1443.0,11020.0,9999990.0,25901850.0,159.01875901875903 | ||
4 | +2,014970,삼륭물산,65649138867.0,9219435245.0,10.073013968004718,92867500000.0,1.4146034754262697,14.043497605776448,6470.0,5500.0,1545.0,-970.0,9996150.0,8497500.0,-14.992272024729521 | ||
5 | +3,004430,송원산업,354189000000.0,42244000000.0,10.084272322696714,426000000000.0,1.2027476855577106,11.926965546643178,18500.0,29150.0,540.0,10650.0,9990000.0,15741000.0,57.567567567567565 | ||
6 | +4,017040,광명전기,98063359627.0,11593891042.0,10.111208407111059,117228248575.0,1.1954337381555842,11.822857269115863,2800.0,3620.0,3571.0,820.0,9998800.0,12927020.0,29.28571428571429 | ||
7 | +5,027710,팜스토리,166916854808.0,12896142588.0,10.173269575747343,131195935035.0,0.7859957293462735,7.726087699671845,1515.0,1300.0,6600.0,-215.0,9999000.0,8580000.0,-14.19141914191419 | ||
8 | +6,069510,에스텍,124146823459.0,14748421661.0,10.208414395835193,150558000000.0,1.2127414605152778,11.879822012418003,14150.0,10800.0,706.0,-3350.0,9989900.0,7624800.0,-23.674911660777383 | ||
9 | +7,012200,계양전기,179133111299.0,17233731189.0,10.214851216454122,176040000000.0,0.9827328890981124,9.620628516988308,5500.0,4140.0,1818.0,-1360.0,9999000.0,7526520.0,-24.727272727272727 | ||
10 | +8,204320,만도,1515053750297.0,210079641643.0,10.237241834478636,2150636096000.0,1.4195114170559329,13.866151059117046,231500.0,231000.0,43.0,-500.0,9954500.0,9933000.0,-0.21598272138228944 | ||
11 | +9,098660,에스티오,33858491829.0,3213669838.0,10.254857832723014,32955727310.0,0.9733371313890958,9.491473672927961,3865.0,2820.0,2587.0,-1045.0,9998755.0,7295340.0,-27.037516170763258 | ||
12 | +10,,,,,,,,,,,,,,113013980.0,13.09129 |
-
Please register or login to post a comment