├── 01_Stock_Investment
├── ch01_01_SamsungElectronics.py
└── imgs
│ ├── BerkshireHathaway.png
│ ├── Figure_1.png
│ ├── Kyungsung_exchange.jpg
│ ├── SamsungElectronics.jpg
│ ├── Screenshot20171121.png
│ ├── TheIntelligentInvestor.jpg
│ ├── VOC.PNG
│ └── ecos_kospi.png
├── 02_Python_Programming
├── ch02_01_ImageProcessing.py
├── imgs
│ ├── ImageProcessing.jpg
│ ├── PillowShow.jpg
│ ├── ch02_Anaconda.jpg
│ ├── ch02_HelloWorld.jpg
│ ├── ch02_IDLE.jpg
│ ├── ch02_PyPI.jpg
│ ├── ch02_PythonInstallation1.jpg
│ ├── ch02_PythonInstallation2.jpg
│ ├── ch02_PythonInstallation3.jpg
│ ├── ch02_PythonInstallation4.jpg
│ ├── ch02_PythonPath1.jpg
│ ├── ch02_PythonPath2.jpg
│ ├── ch02_PythonPath3.jpg
│ ├── ch02_PythonPath4.jpg
│ ├── ch02_PythonPath5.jpg
│ ├── ch02_PythonPath6.jpg
│ ├── ch02_Requests.jpg
│ ├── ch02_VEnv1.jpg
│ ├── ch02_VEnv2.jpg
│ ├── ch02_VEnv3.jpg
│ ├── ch02_VEnv4.jpg
│ ├── ch02_VEnv5.jpg
│ ├── ch02_VEnv6.jpg
│ ├── ch02_VEnv7.jpg
│ ├── ch02_pycache.jpg
│ ├── dst.png
│ ├── pycache.png
│ └── src.png
└── requirements.txt
├── 03_NumPy_and_Pandas
├── ch03_00_CumulativeProduct.py
├── ch03_01_KOSPI_MDD.py
├── ch03_02_DowKospi_Scatter.py
├── ch03_03_DowKospi_Regression.py
└── imgs
│ ├── ElliottWave.jpg
│ ├── InnerProduct.jpg
│ ├── SecHist.jpg
│ ├── kospi_dow.jpg
│ ├── kospi_dow_indexation.jpg
│ ├── kospi_dow_regr.jpg
│ ├── kospi_dow_scatter.jpg
│ ├── kospi_tlt_regr.jpg
│ ├── max_dd.jpg
│ └── pandas.png
├── 04_Web_Scraping
├── HtmlSample.htm
├── ch04_01_Celltrion_PlotChart.py
├── ch04_02_Celltrion_CandleChart_OldSchool.py
├── ch04_03_Celltrion_CandleChart_NewSchool.py
└── imgs
│ ├── CandleChart.jpg
│ ├── CelltrionURL.jpg
│ ├── Celltrion_CandleChart_NewSchool.jpg
│ ├── Celltrion_CandleStickChart_OldSchool.jpg
│ ├── Celltrion_CustomizedCandleChart_NewSchool.jpg
│ ├── Celltrion_OhlcChart_NewSchool.jpg
│ ├── Celltrion_close.jpg
│ ├── HtmlSample.jpg
│ ├── OhlcCandleChart.jpg
│ ├── bs4.jpg
│ ├── kind.jpg
│ ├── kind_excel.jpg
│ ├── kind_notepad.jpg
│ ├── sise1.jpg
│ └── sise2.jpg
├── 05_Stock_Price_API
├── Investar
│ ├── Analyzer.py
│ ├── DBUpdater.py
│ ├── DBUpdaterEx.py
│ └── MarketDB.py
├── ch05_01_YahooFinance_SEC.py
├── ch05_02_NaverDatabase_SEC.py
├── ch05_03_SelectVersion.py
├── ch05_04_CreateTable.sql
└── imgs
│ ├── API_Client1.jpg
│ ├── API_Client2.jpg
│ ├── API_ConfigJson.jpg
│ ├── API_ConfigMy.jpg
│ ├── API_DBUpdater.jpg
│ ├── API_DBUpdater1.jpg
│ ├── API_DBUpdater2.jpg
│ ├── API_Download2.jpg
│ ├── API_GetDailyPrice.jpg
│ ├── API_HeidiSQL1.jpg
│ ├── API_HeidiSQL2.jpg
│ ├── API_HeidiSQL3.jpg
│ ├── API_HeidiSQL4.jpg
│ ├── API_HeidiSQL5.jpg
│ ├── API_Installer.jpg
│ ├── API_Installer2.jpg
│ ├── API_Installer3.jpg
│ ├── API_RunRegistry.jpg
│ ├── DBUpdaterEx.jpg
│ ├── DBUpdaterEx2024-03-03.png
│ ├── DBUpdaterEx_2024-06-30.jpg
│ ├── ExceptionOccured_2024-06-30.jpg
│ ├── GetDailyPrice.png
│ ├── HeidiSQL.png
│ ├── MTV2.png
│ ├── MariaDB_Download.jpg
│ ├── MariaDB_DownloadPage.jpg
│ └── MariaDB_IndexPage.jpg
├── 06_Trading_Strategy
├── ch06_01_EfficientFrontier.py
├── ch06_02_PortfolioOptimization.py
├── ch06_03_BollingerBand.py
├── ch06_04_BollingerBand_PercentB.py
├── ch06_05_BollingerBand_BandWidth.py
├── ch06_06_BollingerBand_TrendFollowing.py
├── ch06_07_BollingerBand_IIP21.py
├── ch06_08_BollingerBand_Reversals.py
├── ch06_09_FirstScreen.py
├── ch06_09_FirstScreenEx.py
├── ch06_10_SecondScreen.py
├── ch06_11_TripleScreen.py
├── ch06_12_DualMomentum.py
└── imgs
│ ├── AbsoluteMomentum.jpg
│ ├── BollingerBand.jpg
│ ├── BollingerBand_BandWidth.jpg
│ ├── BollingerBand_IIP21.jpg
│ ├── BollingerBand_MFI.jpg
│ ├── BollingerBand_PercentB.jpg
│ ├── BollingerBand_Reversals.jpg
│ ├── BollingerBand_TrendFollowing.jpg
│ ├── BollingerBand_TrendFollowing_Naver.jpg
│ ├── BollingerOnBollingerBands.jpg
│ ├── DualMomentum.jpg
│ ├── DualMomentumInvesting.jpg
│ ├── FirstScreen.jpg
│ ├── Long-TermSecretsToShort-TermTrading.jpg
│ ├── Portpolio_optimization.jpg
│ ├── RelativeMomentum.jpg
│ ├── SecondScreen.jpg
│ ├── TheNewTradingForALiving.jpg
│ ├── TripleScreen.jpg
│ ├── ch06_EfficientFrontierLine.jpg
│ └── efficient_frontier.jpg
├── 07_Django_and_Automation
├── ch07_01_index.html
├── ch07_02_index.html
├── ch07_03_style.css
├── ch07_04_balance_views.py
├── ch07_05_balance.html
├── ch07_06_b_style.css
├── ch07_07_Slack_SendMessage.py
├── ch07_08_Backtrader_RSI.py
├── ch07_09_Backtrader_RSI_SMA.py
└── imgs
│ ├── BackTrader_PlotRSISMA.jpg
│ ├── Backtrader_Homepage.jpg
│ ├── Backtrader_PlotRSI.jpg
│ ├── Balance_Naver.jpg
│ ├── Balance_Sample2.jpg
│ ├── Django_AdminLogin.jpg
│ ├── Django_AdminPage.jpg
│ ├── Django_Hello.jpg
│ ├── Django_Homepage.jpg
│ ├── Django_IndexPage.jpg
│ ├── Django_IndexTree.jpg
│ ├── Django_Logo.jpg
│ ├── Django_PIP.jpg
│ ├── Django_Python.jpg
│ ├── Django_Rocket.jpg
│ ├── Django_StaticImage.jpg
│ ├── Django_Superuser.jpg
│ ├── Django_Tree.jpg
│ ├── Slack_Bots.jpg
│ ├── Slack_CreateApp.jpg
│ ├── Slack_Scopes.jpg
│ ├── Slack_SmartPhone.png
│ └── Slack_mySlackBot.jpg
├── 08_Volatility_Breakout
├── ch08_01_AutoConnect.py
├── ch08_02_DynamicPageScraping_NaverETF.py
├── ch08_03_EtfAlgoTrader.py
└── imgs
│ ├── NaverFinance_Naver.jpg
│ ├── VB_ConfirmOrder.jpg
│ ├── VB_CreonBalance.jpg
│ ├── VB_CreonDownload.jpg
│ ├── VB_CreonPlusTray.jpg
│ ├── VB_CreonPlustLogin.jpg
│ ├── VB_CurrentPrice.jpg
│ ├── VB_EtfAlogTraderLog.jpg
│ ├── VB_EtfSise.jpg
│ ├── VB_HeadlessChrome.jpg
│ ├── VB_IdleAdmin.jpg
│ ├── VB_JobExecute.jpg
│ ├── VB_JobName.jpg
│ ├── VB_JobOperation.jpg
│ ├── VB_JobScheduler.jpg
│ ├── VB_JobTrigger.jpg
│ ├── VB_OHLC.jpg
│ ├── VB_PythonAdmin.jpg
│ ├── VB_PythonwAdmin.jpg
│ ├── VB_SlackMessage.jpg
│ ├── VB_TigerHoga.jpg
│ ├── VB_TigerSise.jpg
│ ├── VB_Trigger.jpg
│ ├── VB_VolatilityBreakout.jpg
│ ├── VB_WinSearch.jpg
│ ├── VolatilityBreakout.jpg
│ └── yahoo_finance.jpg
├── 09_Deep_Learning_Prediction
├── ch09_01_StepFunction.py
├── ch09_02_SigmoidFunction.py
├── ch09_03_TanhFunction.py
├── ch09_04_ReLUFunction.py
├── ch09_05_SoftmaxFunction.py
├── ch09_06_MLP_HiddenLayer.py
├── ch09_07_MLP_OutputLayer.py
├── ch09_08_LinearRegression.py
├── ch09_09_RNN_StockPrediction.py
└── imgs
│ ├── AI_Difference.jpg
│ ├── AI_LR_Step1.jpg
│ ├── AI_LR_Step2.jpg
│ ├── AI_LR_Step3.jpg
│ ├── AI_LR_Step4.jpg
│ ├── AI_LR_Step5.jpg
│ ├── AI_LR_Step6.jpg
│ ├── AI_LTSM1.jpg
│ ├── AI_LTSM2.jpg
│ ├── AI_MLP.jpg
│ ├── AI_PerceptronImage.jpg
│ ├── AI_RNN.jpg
│ ├── AI_ReLUFunc.jpg
│ ├── AI_SigmoidFunc.jpg
│ ├── AI_StepFunc.jpg
│ ├── AI_StockPricePrediction.jpg
│ ├── AI_StockPricePrediction_Cmd.jpg
│ └── AI_TanhFunc.jpg
├── 10_Appendix_(Python_Built-in_Functions_and_AES-256_Encryption).pdf
├── PowerPoint_Materials.pptx
└── README.md
/01_Stock_Investment/ch01_01_SamsungElectronics.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | from Investar import Analyzer
3 |
4 | mk = Analyzer.MarketDB()
5 | df = mk.get_daily_price('삼성전자', '1998-04-27', '2018-04-27')
6 | """
7 | >>> df
8 | code date open ... volume MA20 MA200
9 | date ...
10 | 1998-04-27 005930 1998-04-27 66800 ... 187010 NaN NaN
11 | 1998-04-28 005930 1998-04-28 65000 ... 174220 NaN NaN
12 | 1998-04-29 005930 1998-04-29 66900 ... 238910 NaN NaN
13 | 1998-04-30 005930 1998-04-30 70500 ... 616240 NaN NaN
14 | 1998-05-02 005930 1998-05-02 72000 ... 236600 NaN NaN
15 | ... ... ... ... ... ... ... ...
16 | 2018-04-23 005930 2018-04-23 2550000 ... 232380 2478450.0 2513175.0
17 | 2018-04-24 005930 2018-04-24 2592000 ... 315406 2479650.0 2513805.0
18 | 2018-04-25 005930 2018-04-25 2461000 ... 332292 2483900.0 2514520.0
19 | 2018-04-26 005930 2018-04-26 2521000 ... 360931 2491650.0 2515750.0
20 | 2018-04-27 005930 2018-04-27 2669000 ... 606216 2501100.0 2517250.0
21 |
22 | [4967 rows x 10 columns]
23 | """
24 | df['MA20'] = df['close'].rolling(window=20).mean()
25 | df['MA200'] = df['close'].rolling(window=200).mean()
26 |
27 | plt.figure(figsize=(9, 7))
28 | plt.plot(df.index, df['close'], color='cyan', label='Close')
29 | plt.plot(df.index, df['MA20'], 'm--', label='MA20')
30 | plt.plot(df.index, df['MA200'], 'r--', label='MA200')
31 | plt.legend(loc='best')
32 | plt.title('Samsung Electronics')
33 | plt.grid(color='gray', linestyle='--')
34 | plt.yticks([65300, 500000, 1000000, 1500000, 2000000, 2500000, 2650000])
35 | plt.xticks(['1998-04-27', '2002-04-27', '2006-04-27', '2010-04-27', '2014-04-27', '2018-04-27'])
36 | plt.show()
37 |
--------------------------------------------------------------------------------
/01_Stock_Investment/imgs/BerkshireHathaway.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/01_Stock_Investment/imgs/BerkshireHathaway.png
--------------------------------------------------------------------------------
/01_Stock_Investment/imgs/Figure_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/01_Stock_Investment/imgs/Figure_1.png
--------------------------------------------------------------------------------
/01_Stock_Investment/imgs/Kyungsung_exchange.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/01_Stock_Investment/imgs/Kyungsung_exchange.jpg
--------------------------------------------------------------------------------
/01_Stock_Investment/imgs/SamsungElectronics.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/01_Stock_Investment/imgs/SamsungElectronics.jpg
--------------------------------------------------------------------------------
/01_Stock_Investment/imgs/Screenshot20171121.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/01_Stock_Investment/imgs/Screenshot20171121.png
--------------------------------------------------------------------------------
/01_Stock_Investment/imgs/TheIntelligentInvestor.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/01_Stock_Investment/imgs/TheIntelligentInvestor.jpg
--------------------------------------------------------------------------------
/01_Stock_Investment/imgs/VOC.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/01_Stock_Investment/imgs/VOC.PNG
--------------------------------------------------------------------------------
/01_Stock_Investment/imgs/ecos_kospi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/01_Stock_Investment/imgs/ecos_kospi.png
--------------------------------------------------------------------------------
/02_Python_Programming/ch02_01_ImageProcessing.py:
--------------------------------------------------------------------------------
1 | import requests
2 | from PIL import Image
3 | import hashlib
4 | import matplotlib.pyplot as plt
5 | import matplotlib.image as mpimg
6 |
7 | # 2.8.1 리퀘스트로 인터넷에서 이미지 파일 가져오기
8 | # url = 'http://bit.ly/2JnsHnT'
9 | url = 'http://bit.ly/3ZZyeXQ'
10 | r = requests.get(url, stream=True).raw
11 |
12 | # 2.8.2 필로우로 이미지 보여주기
13 | img = Image.open(r)
14 | print("img : ", img.get_format_mimetype)
15 | img.show()
16 | img.save('src.png')
17 |
18 | # 2.8.3 'with ~ as 파일 객체:'로 이미지 파일 복사
19 | BUF_SIZE = 1024
20 | with open('src.png', 'rb') as sf, open('dst.png', 'wb') as df:
21 | while True:
22 | data = sf.read(BUF_SIZE)
23 | if not data:
24 | break
25 | df.write(data)
26 |
27 | # 2.8.4 SHA-256으로 파일 복사 검증하기
28 | sha_src = hashlib.sha256()
29 | sha_dst = hashlib.sha256()
30 |
31 | with open('src.png', 'rb') as sf, open('dst.png', 'rb') as df:
32 | sha_src.update(sf.read())
33 | sha_dst.update(df.read())
34 |
35 | print("src.png's hash : {}".format(sha_src.hexdigest()))
36 | print("dsc.png's hash : {}".format(sha_dst.hexdigest()))
37 |
38 | # 2.8.5 맷플롯립으로 이미지 가공하기
39 | plt.suptitle('Image Processing', fontsize=18)
40 | plt.subplot(1, 2, 1) # 1행 2열의 영역에서 첫 번째 영역으로 지정
41 | plt.title('Original Image')
42 | plt.imshow(mpimg.imread('src.png')) # 원본 파일을 읽어서 이미지로 표시
43 |
44 | plt.subplot(122) # 1행 2열의 영역에서 두 번째 영역으로 지정
45 | plt.title('Pseudocolor Image')
46 | dst_img = mpimg.imread('dst.png')
47 | pseudo_img = dst_img [:, :, 0] # 의사 색상 적용
48 | plt.imshow(pseudo_img)
49 | plt.show()
50 |
51 |
52 |
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ImageProcessing.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ImageProcessing.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/PillowShow.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/PillowShow.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_Anaconda.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_Anaconda.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_HelloWorld.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_HelloWorld.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_IDLE.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_IDLE.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_PyPI.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_PyPI.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_PythonInstallation1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_PythonInstallation1.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_PythonInstallation2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_PythonInstallation2.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_PythonInstallation3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_PythonInstallation3.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_PythonInstallation4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_PythonInstallation4.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_PythonPath1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_PythonPath1.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_PythonPath2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_PythonPath2.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_PythonPath3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_PythonPath3.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_PythonPath4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_PythonPath4.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_PythonPath5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_PythonPath5.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_PythonPath6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_PythonPath6.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_Requests.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_Requests.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_VEnv1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_VEnv1.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_VEnv2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_VEnv2.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_VEnv3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_VEnv3.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_VEnv4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_VEnv4.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_VEnv5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_VEnv5.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_VEnv6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_VEnv6.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_VEnv7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_VEnv7.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/ch02_pycache.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/ch02_pycache.jpg
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/dst.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/dst.png
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/pycache.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/pycache.png
--------------------------------------------------------------------------------
/02_Python_Programming/imgs/src.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/02_Python_Programming/imgs/src.png
--------------------------------------------------------------------------------
/02_Python_Programming/requirements.txt:
--------------------------------------------------------------------------------
1 | absl-py==0.9.0
2 | asgiref==3.2.7
3 | astunparse==1.6.3
4 | backtrader==1.9.74.123
5 | beautifulsoup4==4.8.2
6 | bs4==0.0.1
7 | cachetools==4.1.0
8 | certifi==2019.11.28
9 | chardet==3.0.4
10 | cycler==0.10.0
11 | Django==3.0.2
12 | gast==0.3.3
13 | google-auth==1.13.1
14 | google-auth-oauthlib==0.4.1
15 | google-pasta==0.2.0
16 | grpcio==1.28.1
17 | h5py==2.10.0
18 | idna==2.8
19 | Keras-Preprocessing==1.1.0
20 | kiwisolver==1.1.0
21 | lxml==4.4.2
22 | Markdown==3.2.1
23 | matplotlib==3.1.2
24 | mplfinance==0.12.3a3
25 | multitasking==0.0.9
26 | numpy==1.17.4
27 | oauthlib==3.1.0
28 | opt-einsum==3.2.0
29 | pandas==1.0.1
30 | pandas-datareader==0.8.1
31 | Pillow==7.0.0
32 | protobuf==3.11.3
33 | pyasn1==0.4.8
34 | pyasn1-modules==0.2.8
35 | PyMySQL==0.9.3
36 | pyparsing==2.4.5
37 | python-dateutil==2.8.1
38 | pytz==2019.3
39 | requests==2.22.0
40 | requests-oauthlib==1.3.0
41 | rsa==4.0
42 | scipy==1.4.1
43 | selenium==3.141.0
44 | six==1.13.0
45 | slacker==0.13.0
46 | soupsieve==1.9.5
47 | sqlparse==0.3.0
48 | tensorboard==2.2.0
49 | tensorboard-plugin-wit==1.6.0.post3
50 | tensorflow==2.2.0
51 | tensorflow-estimator==2.2.0
52 | termcolor==1.1.0
53 | urllib3==1.25.7
54 | Werkzeug==1.0.1
55 | wrapt==1.12.1
56 | yfinance==0.1.54
57 |
--------------------------------------------------------------------------------
/03_NumPy_and_Pandas/ch03_00_CumulativeProduct.py:
--------------------------------------------------------------------------------
1 | from pandas_datareader import data as pdr
2 | import yfinance as yf
3 | yf.pdr_override()
4 |
5 | sec = pdr.get_data_yahoo('005930.KS', start='2018-05-04')
6 | sec_dpc = (sec['Close']-sec['Close'].shift(1)) / sec['Close'].shift(1) * 100
7 | sec_dpc.iloc[0] = 0 # 일간 변동률의 첫 번째 값인 NaN을 0으로 변경한다.
8 | sec_dpc_cp = ((100+sec_dpc)/100).cumprod()*100-100 # 일간 변동률 누적곱 계산
9 |
10 | msft = pdr.get_data_yahoo('MSFT', start='2018-05-04')
11 | msft_dpc = (msft['Close'] / msft['Close'].shift(1) -1) * 100
12 | msft_dpc.iloc[0] = 0
13 | msft_dpc_cp = ((100+msft_dpc)/100).cumprod()*100-100
14 |
15 | import matplotlib.pyplot as plt
16 | plt.plot(sec.index, sec_dpc_cp, 'b', label='Samsung Electronics')
17 | plt.plot(msft.index, msft_dpc_cp, 'r--', label='Microsoft')
18 | plt.ylabel('Change %')
19 | plt.grid(True)
20 | plt.legend(loc='best')
21 | plt.show()
22 |
--------------------------------------------------------------------------------
/03_NumPy_and_Pandas/ch03_01_KOSPI_MDD.py:
--------------------------------------------------------------------------------
1 | from pandas_datareader import data as pdr
2 | import yfinance as yf
3 | yf.pdr_override()
4 | import matplotlib.pyplot as plt
5 |
6 | kospi = pdr.get_data_yahoo('^KS11', '2004-01-04')
7 |
8 | window = 252
9 | peak = kospi['Adj Close'].rolling(window, min_periods=1).max()
10 | drawdown = kospi['Adj Close']/peak - 1.0
11 | max_dd = drawdown.rolling(window, min_periods=1).min()
12 |
13 | plt.figure(figsize=(9, 7))
14 | plt.subplot(211)
15 | kospi['Close'].plot(label='KOSPI', title='KOSPI MDD', grid=True, legend=True)
16 | plt.subplot(212)
17 | drawdown.plot(c='blue', label='KOSPI DD', grid=True, legend=True)
18 | max_dd.plot(c='red', label='KOSPI MDD', grid=True, legend=True)
19 | plt.show()
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/03_NumPy_and_Pandas/ch03_02_DowKospi_Scatter.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | from pandas_datareader import data as pdr
3 | import yfinance as yf
4 | yf.pdr_override()
5 |
6 | dow = pdr.get_data_yahoo('^DJI', '2000-01-04')
7 | kospi = pdr.get_data_yahoo('^KS11', '2000-01-04')
8 |
9 | df = pd.DataFrame({'DOW': dow['Close'], 'KOSPI': kospi['Close']})
10 | df = df.fillna(method='bfill')
11 | df = df.fillna(method='ffill')
12 |
13 | import matplotlib.pyplot as plt
14 | plt.figure(figsize=(7, 7))
15 | plt.scatter(df['DOW'], df['KOSPI'], marker='.')
16 | plt.xlabel('Dow Jones Industrial Average')
17 | plt.ylabel('KOSPI')
18 | plt.show()
19 |
--------------------------------------------------------------------------------
/03_NumPy_and_Pandas/ch03_03_DowKospi_Regression.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | from pandas_datareader import data as pdr
3 | import yfinance as yf
4 | yf.pdr_override()
5 | from scipy import stats
6 | import matplotlib.pylab as plt
7 |
8 | dow = pdr.get_data_yahoo('^DJI', '2000-01-04')
9 | kospi = pdr.get_data_yahoo('^KS11', '2000-01-04')
10 |
11 | df = pd.DataFrame({'X':dow['Close'], 'Y':kospi['Close']})
12 | df = df.fillna(method='bfill')
13 | df = df.fillna(method='ffill')
14 |
15 | regr = stats.linregress(df.X, df.Y)
16 | regr_line = f'Y = {regr.slope:2f} X + {regr.intercept:2f}'
17 |
18 | plt.figure(figsize=(7, 7))
19 | plt.plot(df.X, df.Y, '.')
20 | plt.plot(df.X, regr.slope * df.X + regr.intercept, 'r')
21 | plt.legend(['DOW x KOSPI', regr_line])
22 | plt.title(f'DOW x KOSPI (R = {regr.rvalue:2f})')
23 | plt.xlabel('Dow Jones Industrial Average')
24 | plt.ylabel('KOSPI')
25 | plt.show()
26 |
--------------------------------------------------------------------------------
/03_NumPy_and_Pandas/imgs/ElliottWave.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/03_NumPy_and_Pandas/imgs/ElliottWave.jpg
--------------------------------------------------------------------------------
/03_NumPy_and_Pandas/imgs/InnerProduct.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/03_NumPy_and_Pandas/imgs/InnerProduct.jpg
--------------------------------------------------------------------------------
/03_NumPy_and_Pandas/imgs/SecHist.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/03_NumPy_and_Pandas/imgs/SecHist.jpg
--------------------------------------------------------------------------------
/03_NumPy_and_Pandas/imgs/kospi_dow.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/03_NumPy_and_Pandas/imgs/kospi_dow.jpg
--------------------------------------------------------------------------------
/03_NumPy_and_Pandas/imgs/kospi_dow_indexation.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/03_NumPy_and_Pandas/imgs/kospi_dow_indexation.jpg
--------------------------------------------------------------------------------
/03_NumPy_and_Pandas/imgs/kospi_dow_regr.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/03_NumPy_and_Pandas/imgs/kospi_dow_regr.jpg
--------------------------------------------------------------------------------
/03_NumPy_and_Pandas/imgs/kospi_dow_scatter.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/03_NumPy_and_Pandas/imgs/kospi_dow_scatter.jpg
--------------------------------------------------------------------------------
/03_NumPy_and_Pandas/imgs/kospi_tlt_regr.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/03_NumPy_and_Pandas/imgs/kospi_tlt_regr.jpg
--------------------------------------------------------------------------------
/03_NumPy_and_Pandas/imgs/max_dd.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/03_NumPy_and_Pandas/imgs/max_dd.jpg
--------------------------------------------------------------------------------
/03_NumPy_and_Pandas/imgs/pandas.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/03_NumPy_and_Pandas/imgs/pandas.png
--------------------------------------------------------------------------------
/04_Web_Scraping/HtmlSample.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 | This is title.
4 |
5 |
6 | This is heading1 text.
7 | This is heading2 text.
8 | This is heading3 text.
9 | This is a paragraph.
10 | This is plain text.
11 | This is bold text.
12 | This is Italic text.
13 | This is strike text.
14 |
15 | - the first orderd list
16 | - the second orderd list
17 | - the third orderd list
18 |
19 |
20 | - unorderd list
21 | - unorderd list
22 | - unorderd list
23 |
24 |
25 |
26 | table header 1 |
27 | table header 2 |
28 | table header 3 |
29 |
30 |
31 | table data 4 |
32 | table data 5 |
33 | table data 6 |
34 |
35 |
36 | table data 7 |
37 | table data 8 |
38 | table data 9 |
39 |
40 |
41 |
42 | Visit Python homepage!
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/04_Web_Scraping/ch04_01_Celltrion_PlotChart.py:
--------------------------------------------------------------------------------
1 | # ch04_01_Celltrion_PlotChart.py
2 | import pandas as pd
3 | import requests
4 | from bs4 import BeautifulSoup
5 | from matplotlib import pyplot as plt
6 |
7 | # 4.4.3 맨 뒤 페이지 숫자 구하기
8 | url = 'https://finance.naver.com/item/sise_day.nhn?code=068270&page=1'
9 | html = requests.get(url, headers={'User-agent': 'Mozilla/5.0'}).text
10 | bs = BeautifulSoup(html, 'lxml')
11 | pgrr = bs.find('td', class_='pgRR')
12 | s = str(pgrr.a['href']).split('=')
13 | last_page = s[-1]
14 |
15 | # 4.4.4 전체 페이지 읽어오기
16 | df = pd.DataFrame()
17 | sise_url = 'https://finance.naver.com/item/sise_day.nhn?code=068270'
18 | for page in range(1, int(last_page)+1):
19 | url = '{}&page={}'.format(sise_url, page)
20 | html = requests.get(url, headers={'User-agent': 'Mozilla/5.0'}).text
21 | df = df.append(pd.read_html(html, header=0)[0])
22 |
23 | # 차트 출력을 위해 데이터프레임 가공하기
24 | df = df.dropna()
25 | df = df.iloc[0:30] # ①
26 | df = df.sort_values(by='날짜') # ②
27 |
28 | # 날짜, 종가 컬럼으로 차트 그리기
29 | plt.title('Celltrion (close)')
30 | plt.xticks(rotation=45) # ③
31 | plt.plot(df['날짜'], df['종가'], 'co-') # ④
32 | plt.grid(color='gray', linestyle='--')
33 | plt.show()
34 |
--------------------------------------------------------------------------------
/04_Web_Scraping/ch04_02_Celltrion_CandleChart_OldSchool.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | from urllib.request import urlopen
3 | from bs4 import BeautifulSoup
4 | from matplotlib import pyplot as plt
5 | from matplotlib import dates as mdates
6 | from mpl_finance import candlestick_ohlc
7 | #from mplfinance.original_flavor import candlestick_ohlc
8 | from datetime import datetime
9 |
10 | url = 'https://finance.naver.com/item/sise_day.nhn?code=068270&page=1'
11 | with urlopen(url) as doc:
12 | html = BeautifulSoup(doc, 'lxml')
13 | pgrr = html.find('td', class_='pgRR')
14 | s = str(pgrr.a['href']).split('=')
15 | last_page = s[-1]
16 |
17 | df = pd.DataFrame()
18 | sise_url = 'https://finance.naver.com/item/sise_day.nhn?code=068270'
19 | for page in range(1, int(last_page)+1):
20 | page_url = '{}&page={}'.format(sise_url, page)
21 | df = df.append(pd.read_html(page_url, header=0)[0])
22 |
23 | df = df.dropna()
24 | df = df.iloc[0:30]
25 | df = df.sort_values(by='날짜')
26 | for idx in range(0, len(df)):
27 | dt = datetime.strptime(df['날짜'].values[idx], '%Y.%m.%d').date()
28 | df['날짜'].values[idx] = mdates.date2num(dt)
29 | ohlc = df[['날짜','시가','고가','저가','종가']]
30 |
31 | plt.figure(figsize=(9, 6))
32 | ax = plt.subplot(1, 1, 1)
33 | plt.title('Celltrion (mpl_finance candle stick)')
34 | candlestick_ohlc(ax, ohlc.values, width=0.7, colorup='red', colordown='blue')
35 | ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
36 | plt.xticks(rotation=45)
37 | plt.grid(color='gray', linestyle='--')
38 | plt.show()
39 |
--------------------------------------------------------------------------------
/04_Web_Scraping/ch04_03_Celltrion_CandleChart_NewSchool.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | from urllib.request import urlopen
3 | from bs4 import BeautifulSoup
4 | import mplfinance as mpf
5 |
6 | url = 'https://finance.naver.com/item/sise_day.nhn?code=068270&page=1'
7 | with urlopen(url) as doc:
8 | html = BeautifulSoup(doc, 'lxml')
9 | pgrr = html.find('td', class_='pgRR')
10 | s = str(pgrr.a['href']).split('=')
11 | last_page = s[-1]
12 |
13 | df = pd.DataFrame()
14 | sise_url = 'https://finance.naver.com/item/sise_day.nhn?code=068270'
15 | for page in range(1, int(last_page)+1):
16 | page_url = '{}&page={}'.format(sise_url, page)
17 | df = df.append(pd.read_html(page_url, header=0)[0])
18 |
19 | df = df.dropna()
20 | df = df.iloc[0:30]
21 | df = df.rename(columns={'날짜':'Date', '시가':'Open', '고가':'High', '저가':'Low', '종가':'Close', '거래량':'Volume'})
22 | df = df.sort_values(by='Date')
23 | df.index = pd.to_datetime(df.Date)
24 | df = df[['Open', 'High', 'Low', 'Close', 'Volume']]
25 |
26 | mpf.plot(df, title='Celltrion candle chart', type='candle')
27 |
28 | mpf.plot(df, title='Celltrion ohlc chart', type='ohlc')
29 |
30 | kwargs = dict(title='Celltrion customized chart', type='candle',
31 | mav=(2, 4, 6), volume=True, ylabel='ohlc candles')
32 | mc = mpf.make_marketcolors(up='r', down='b', inherit=True)
33 | s = mpf.make_mpf_style(marketcolors=mc)
34 | mpf.plot(df, **kwargs, style=s)
35 |
36 |
37 |
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/CandleChart.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/CandleChart.jpg
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/CelltrionURL.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/CelltrionURL.jpg
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/Celltrion_CandleChart_NewSchool.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/Celltrion_CandleChart_NewSchool.jpg
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/Celltrion_CandleStickChart_OldSchool.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/Celltrion_CandleStickChart_OldSchool.jpg
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/Celltrion_CustomizedCandleChart_NewSchool.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/Celltrion_CustomizedCandleChart_NewSchool.jpg
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/Celltrion_OhlcChart_NewSchool.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/Celltrion_OhlcChart_NewSchool.jpg
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/Celltrion_close.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/Celltrion_close.jpg
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/HtmlSample.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/HtmlSample.jpg
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/OhlcCandleChart.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/OhlcCandleChart.jpg
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/bs4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/bs4.jpg
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/kind.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/kind.jpg
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/kind_excel.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/kind_excel.jpg
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/kind_notepad.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/kind_notepad.jpg
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/sise1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/sise1.jpg
--------------------------------------------------------------------------------
/04_Web_Scraping/imgs/sise2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/04_Web_Scraping/imgs/sise2.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/Investar/Analyzer.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import pymysql
3 | from datetime import datetime
4 | from datetime import timedelta
5 | import re
6 |
7 | class MarketDB:
8 | def __init__(self):
9 | """생성자: MariaDB 연결 및 종목코드 딕셔너리 생성"""
10 | self.conn = pymysql.connect(host='localhost', user='root',
11 | password='myPa$$word', db='INVESTAR', charset='utf8')
12 | self.codes = {}
13 | self.get_comp_info()
14 |
15 | def __del__(self):
16 | """소멸자: MariaDB 연결 해제"""
17 | self.conn.close()
18 |
19 | def get_comp_info(self):
20 | """company_info 테이블에서 읽어와서 codes에 저장"""
21 | sql = "SELECT * FROM company_info"
22 | krx = pd.read_sql(sql, self.conn)
23 | for idx in range(len(krx)):
24 | self.codes[krx['code'].values[idx]] = krx['company'].values[idx]
25 |
26 | def get_daily_price(self, code, start_date=None, end_date=None):
27 | """KRX 종목의 일별 시세를 데이터프레임 형태로 반환
28 | - code : KRX 종목코드('005930') 또는 상장기업명('삼성전자')
29 | - start_date : 조회 시작일('2020-01-01'), 미입력 시 1년 전 오늘
30 | - end_date : 조회 종료일('2020-12-31'), 미입력 시 오늘 날짜
31 | """
32 | if start_date is None:
33 | one_year_ago = datetime.today() - timedelta(days=365)
34 | start_date = one_year_ago.strftime('%Y-%m-%d')
35 | print("start_date is initialized to '{}'".format(start_date))
36 | else:
37 | start_lst = re.split('\D+', start_date)
38 | if start_lst[0] == '':
39 | start_lst = start_lst[1:]
40 | start_year = int(start_lst[0])
41 | start_month = int(start_lst[1])
42 | start_day = int(start_lst[2])
43 | if start_year < 1900 or start_year > 2200:
44 | print(f"ValueError: start_year({start_year:d}) is wrong.")
45 | return
46 | if start_month < 1 or start_month > 12:
47 | print(f"ValueError: start_month({start_month:d}) is wrong.")
48 | return
49 | if start_day < 1 or start_day > 31:
50 | print(f"ValueError: start_day({start_day:d}) is wrong.")
51 | return
52 | start_date=f"{start_year:04d}-{start_month:02d}-{start_day:02d}"
53 |
54 | if end_date is None:
55 | end_date = datetime.today().strftime('%Y-%m-%d')
56 | print("end_date is initialized to '{}'".format(end_date))
57 | else:
58 | end_lst = re.split('\D+', end_date)
59 | if end_lst[0] == '':
60 | end_lst = end_lst[1:]
61 | end_year = int(end_lst[0])
62 | end_month = int(end_lst[1])
63 | end_day = int(end_lst[2])
64 | if end_year < 1800 or end_year > 2200:
65 | print(f"ValueError: end_year({end_year:d}) is wrong.")
66 | return
67 | if end_month < 1 or end_month > 12:
68 | print(f"ValueError: end_month({end_month:d}) is wrong.")
69 | return
70 | if end_day < 1 or end_day > 31:
71 | print(f"ValueError: end_day({end_day:d}) is wrong.")
72 | return
73 | end_date = f"{end_year:04d}-{end_month:02d}-{end_day:02d}"
74 |
75 | codes_keys = list(self.codes.keys())
76 | codes_values = list(self.codes.values())
77 |
78 | if code in codes_keys:
79 | pass
80 | elif code in codes_values:
81 | idx = codes_values.index(code)
82 | code = codes_keys[idx]
83 | else:
84 | print(f"ValueError: Code({code}) doesn't exist.")
85 | sql = f"SELECT * FROM daily_price WHERE code = '{code}'"\
86 | f" and date >= '{start_date}' and date <= '{end_date}'"
87 | df = pd.read_sql(sql, self.conn)
88 | df.index = df['date']
89 | return df
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/05_Stock_Price_API/Investar/DBUpdater.py:
--------------------------------------------------------------------------------
1 |
2 | import pandas as pd
3 | from bs4 import BeautifulSoup
4 | import urllib, pymysql, calendar, time, json
5 | from urllib.request import urlopen
6 | from datetime import datetime
7 | from threading import Timer
8 |
9 | class DBUpdater:
10 | def __init__(self):
11 | """생성자: MariaDB 연결 및 종목코드 딕셔너리 생성"""
12 | self.conn = pymysql.connect(host='localhost', user='root',
13 | password='myPa$$word', db='INVESTAR', charset='utf8')
14 |
15 | with self.conn.cursor() as curs:
16 | sql = """
17 | CREATE TABLE IF NOT EXISTS company_info (
18 | code VARCHAR(20),
19 | company VARCHAR(40),
20 | last_update DATE,
21 | PRIMARY KEY (code))
22 | """
23 | curs.execute(sql)
24 | sql = """
25 | CREATE TABLE IF NOT EXISTS daily_price (
26 | code VARCHAR(20),
27 | date DATE,
28 | open BIGINT(20),
29 | high BIGINT(20),
30 | low BIGINT(20),
31 | close BIGINT(20),
32 | diff BIGINT(20),
33 | volume BIGINT(20),
34 | PRIMARY KEY (code, date))
35 | """
36 | curs.execute(sql)
37 | self.conn.commit()
38 | self.codes = dict()
39 |
40 | def __del__(self):
41 | """소멸자: MariaDB 연결 해제"""
42 | self.conn.close()
43 |
44 | def read_krx_code(self):
45 | """KRX로부터 상장기업 목록 파일을 읽어와서 데이터프레임으로 반환"""
46 | url = 'http://kind.krx.co.kr/corpgeneral/corpList.do?method='\
47 | 'download&searchType=13'
48 | krx = pd.read_html(url, header=0)[0]
49 | krx = krx[['종목코드', '회사명']]
50 | krx = krx.rename(columns={'종목코드': 'code', '회사명': 'company'})
51 | krx.code = krx.code.map('{:06d}'.format)
52 | return krx
53 |
54 | def update_comp_info(self):
55 | """종목코드를 company_info 테이블에 업데이트 한 후 딕셔너리에 저장"""
56 | sql = "SELECT * FROM company_info"
57 | df = pd.read_sql(sql, self.conn)
58 | for idx in range(len(df)):
59 | self.codes[df['code'].values[idx]] = df['company'].values[idx]
60 |
61 | with self.conn.cursor() as curs:
62 | sql = "SELECT max(last_update) FROM company_info"
63 | curs.execute(sql)
64 | rs = curs.fetchone()
65 | today = datetime.today().strftime('%Y-%m-%d')
66 | if rs[0] == None or rs[0].strftime('%Y-%m-%d') < today:
67 | krx = self.read_krx_code()
68 | for idx in range(len(krx)):
69 | code = krx.code.values[idx]
70 | company = krx.company.values[idx]
71 | sql = f"REPLACE INTO company_info (code, company, last"\
72 | f"_update) VALUES ('{code}', '{company}', '{today}')"
73 | curs.execute(sql)
74 | self.codes[code] = company
75 | tmnow = datetime.now().strftime('%Y-%m-%d %H:%M')
76 | print(f"[{tmnow}] #{idx+1:04d} REPLACE INTO company_info "\
77 | f"VALUES ({code}, {company}, {today})")
78 | self.conn.commit()
79 | print('')
80 |
81 | def read_naver(self, code, company, pages_to_fetch):
82 | """네이버에서 주식 시세를 읽어서 데이터프레임으로 반환"""
83 | try:
84 | url = f"http://finance.naver.com/item/sise_day.nhn?code={code}"
85 | with urlopen(url) as doc:
86 | if doc is None:
87 | return None
88 | html = BeautifulSoup(doc, "lxml")
89 | pgrr = html.find("td", class_="pgRR")
90 | if pgrr is None:
91 | return None
92 | s = str(pgrr.a["href"]).split('=')
93 | lastpage = s[-1]
94 | df = pd.DataFrame()
95 | pages = min(int(lastpage), pages_to_fetch)
96 | for page in range(1, pages + 1):
97 | pg_url = '{}&page={}'.format(url, page)
98 | df = df.append(pd.read_html(pg_url, header=0)[0])
99 | tmnow = datetime.now().strftime('%Y-%m-%d %H:%M')
100 | print('[{}] {} ({}) : {:04d}/{:04d} pages are downloading...'.
101 | format(tmnow, company, code, page, pages), end="\r")
102 | df = df.rename(columns={'날짜':'date','종가':'close','전일비':'diff'
103 | ,'시가':'open','고가':'high','저가':'low','거래량':'volume'})
104 | df['date'] = df['date'].replace('.', '-')
105 | df = df.dropna()
106 | df[['close', 'diff', 'open', 'high', 'low', 'volume']] = df[['close',
107 | 'diff', 'open', 'high', 'low', 'volume']].astype(int)
108 | df = df[['date', 'open', 'high', 'low', 'close', 'diff', 'volume']]
109 | except Exception as e:
110 | print('Exception occured :', str(e))
111 | return None
112 | return df
113 |
114 | def replace_into_db(self, df, num, code, company):
115 | """네이버에서 읽어온 주식 시세를 DB에 REPLACE"""
116 | with self.conn.cursor() as curs:
117 | for r in df.itertuples():
118 | sql = f"REPLACE INTO daily_price VALUES ('{code}', "\
119 | f"'{r.date}', {r.open}, {r.high}, {r.low}, {r.close}, "\
120 | f"{r.diff}, {r.volume})"
121 | curs.execute(sql)
122 | self.conn.commit()
123 | print('[{}] #{:04d} {} ({}) : {} rows > REPLACE INTO daily_'\
124 | 'price [OK]'.format(datetime.now().strftime('%Y-%m-%d'\
125 | ' %H:%M'), num+1, company, code, len(df)))
126 |
127 | def update_daily_price(self, pages_to_fetch):
128 | """KRX 상장법인의 주식 시세를 네이버로부터 읽어서 DB에 업데이트"""
129 | for idx, code in enumerate(self.codes):
130 | df = self.read_naver(code, self.codes[code], pages_to_fetch)
131 | if df is None:
132 | continue
133 | self.replace_into_db(df, idx, code, self.codes[code])
134 |
135 | def execute_daily(self):
136 | """실행 즉시 및 매일 오후 다섯시에 daily_price 테이블 업데이트"""
137 | self.update_comp_info()
138 |
139 | try:
140 | with open('config.json', 'r') as in_file:
141 | config = json.load(in_file)
142 | pages_to_fetch = config['pages_to_fetch']
143 | except FileNotFoundError:
144 | with open('config.json', 'w') as out_file:
145 | pages_to_fetch = 100
146 | config = {'pages_to_fetch': 1}
147 | json.dump(config, out_file)
148 | self.update_daily_price(pages_to_fetch)
149 |
150 | tmnow = datetime.now()
151 | lastday = calendar.monthrange(tmnow.year, tmnow.month)[1]
152 | if tmnow.month == 12 and tmnow.day == lastday:
153 | tmnext = tmnow.replace(year=tmnow.year+1, month=1, day=1,
154 | hour=17, minute=0, second=0)
155 | elif tmnow.day == lastday:
156 | tmnext = tmnow.replace(month=tmnow.month+1, day=1, hour=17,
157 | minute=0, second=0)
158 | else:
159 | tmnext = tmnow.replace(day=tmnow.day+1, hour=17, minute=0,
160 | second=0)
161 | tmdiff = tmnext - tmnow
162 | secs = tmdiff.seconds
163 | t = Timer(secs, self.execute_daily)
164 | print("Waiting for next update ({}) ... ".format(tmnext.strftime
165 | ('%Y-%m-%d %H:%M')))
166 | t.start()
167 |
168 | if __name__ == '__main__':
169 | dbu = DBUpdater()
170 | dbu.execute_daily()
171 |
--------------------------------------------------------------------------------
/05_Stock_Price_API/Investar/DBUpdaterEx.py:
--------------------------------------------------------------------------------
1 |
2 | import pandas as pd
3 | from bs4 import BeautifulSoup
4 | import pymysql, calendar, time, json
5 | import requests
6 | from datetime import datetime
7 | from threading import Timer
8 |
9 | class DBUpdater:
10 | def __init__(self):
11 | """생성자: MariaDB 연결 및 종목코드 딕셔너리 생성"""
12 | self.conn = pymysql.connect(host='localhost', user='root',
13 | password='myPa$$word', db='INVESTAR', charset='utf8')
14 |
15 | with self.conn.cursor() as curs:
16 | sql = """
17 | CREATE TABLE IF NOT EXISTS company_info (
18 | code VARCHAR(20),
19 | company VARCHAR(40),
20 | last_update DATE,
21 | PRIMARY KEY (code))
22 | """
23 | curs.execute(sql)
24 | sql = """
25 | CREATE TABLE IF NOT EXISTS daily_price (
26 | code VARCHAR(20),
27 | date DATE,
28 | open BIGINT(20),
29 | high BIGINT(20),
30 | low BIGINT(20),
31 | close BIGINT(20),
32 | diff BIGINT(20),
33 | volume BIGINT(20),
34 | PRIMARY KEY (code, date))
35 | """
36 | curs.execute(sql)
37 | self.conn.commit()
38 | self.codes = dict()
39 |
40 | def __del__(self):
41 | """소멸자: MariaDB 연결 해제"""
42 | self.conn.close()
43 |
44 | def read_krx_code(self):
45 | """KRX로부터 상장기업 목록 파일을 읽어와서 데이터프레임으로 반환"""
46 | url = 'http://kind.krx.co.kr/corpgeneral/corpList.do?method='\
47 | 'download&searchType=13'
48 | krx = pd.read_html(url, header=0)[0]
49 | krx = krx[['종목코드', '회사명']]
50 | krx = krx.rename(columns={'종목코드': 'code', '회사명': 'company'})
51 | krx.code = krx.code.map('{:06d}'.format)
52 | return krx
53 |
54 | def update_comp_info(self):
55 | """종목코드를 company_info 테이블에 업데이트 한 후 딕셔너리에 저장"""
56 | sql = "SELECT * FROM company_info"
57 | df = pd.read_sql(sql, self.conn)
58 | for idx in range(len(df)):
59 | self.codes[df['code'].values[idx]] = df['company'].values[idx]
60 |
61 | with self.conn.cursor() as curs:
62 | sql = "SELECT max(last_update) FROM company_info"
63 | curs.execute(sql)
64 | rs = curs.fetchone()
65 | today = datetime.today().strftime('%Y-%m-%d')
66 | if rs[0] == None or rs[0].strftime('%Y-%m-%d') < today:
67 | krx = self.read_krx_code()
68 | for idx in range(len(krx)):
69 | code = krx.code.values[idx]
70 | company = krx.company.values[idx]
71 | sql = f"REPLACE INTO company_info (code, company, last"\
72 | f"_update) VALUES ('{code}', '{company}', '{today}')"
73 | curs.execute(sql)
74 | self.codes[code] = company
75 | tmnow = datetime.now().strftime('%Y-%m-%d %H:%M')
76 | print(f"[{tmnow}] #{idx+1:04d} REPLACE INTO company_info "\
77 | f"VALUES ({code}, {company}, {today})")
78 | self.conn.commit()
79 | print('')
80 |
81 | def read_naver(self, code, company, pages_to_fetch):
82 | """네이버에서 주식 시세를 읽어서 데이터프레임으로 반환"""
83 | try:
84 | url = f"http://finance.naver.com/item/sise_day.nhn?code={code}"
85 | html = BeautifulSoup(requests.get(url,
86 | headers={'User-agent': 'Mozilla/5.0'}).text, "lxml")
87 | pgrr = html.find("td", class_="pgRR")
88 | if pgrr is None:
89 | return None
90 | s = str(pgrr.a["href"]).split('=')
91 | lastpage = s[-1]
92 | df = pd.DataFrame()
93 | pages = min(int(lastpage), pages_to_fetch)
94 | for page in range(1, pages + 1):
95 | pg_url = '{}&page={}'.format(url, page)
96 | df = df.append(pd.read_html(requests.get(pg_url,
97 | headers={'User-agent': 'Mozilla/5.0'}).text)[0])
98 | tmnow = datetime.now().strftime('%Y-%m-%d %H:%M')
99 | print('[{}] {} ({}) : {:04d}/{:04d} pages are downloading...'.
100 | format(tmnow, company, code, page, pages), end="\r")
101 | df = df.rename(columns={'날짜':'date','종가':'close','전일비':'diff'
102 | ,'시가':'open','고가':'high','저가':'low','거래량':'volume'})
103 | df['date'] = df['date'].replace('.', '-')
104 | df['diff'] = df['diff'].str.extract(r'(\d+)')
105 | df = df.dropna()
106 | df[['close', 'diff', 'open', 'high', 'low', 'volume']] = df[['close',
107 | 'diff', 'open', 'high', 'low', 'volume']].astype(int)
108 | df = df[['date', 'open', 'high', 'low', 'close', 'diff', 'volume']]
109 | except Exception as e:
110 | print('Exception occured :', str(e))
111 | return None
112 | return df
113 |
114 | def replace_into_db(self, df, num, code, company):
115 | """네이버에서 읽어온 주식 시세를 DB에 REPLACE"""
116 | with self.conn.cursor() as curs:
117 | for r in df.itertuples():
118 | sql = f"REPLACE INTO daily_price VALUES ('{code}', "\
119 | f"'{r.date}', {r.open}, {r.high}, {r.low}, {r.close}, "\
120 | f"{r.diff}, {r.volume})"
121 | curs.execute(sql)
122 | self.conn.commit()
123 | print('[{}] #{:04d} {} ({}) : {} rows > REPLACE INTO daily_'\
124 | 'price [OK]'.format(datetime.now().strftime('%Y-%m-%d'\
125 | ' %H:%M'), num+1, company, code, len(df)))
126 |
127 | def update_daily_price(self, pages_to_fetch):
128 | """KRX 상장법인의 주식 시세를 네이버로부터 읽어서 DB에 업데이트"""
129 | for idx, code in enumerate(self.codes):
130 | df = self.read_naver(code, self.codes[code], pages_to_fetch)
131 | if df is None:
132 | continue
133 | self.replace_into_db(df, idx, code, self.codes[code])
134 |
135 | def execute_daily(self):
136 | """실행 즉시 및 매일 오후 다섯시에 daily_price 테이블 업데이트"""
137 | self.update_comp_info()
138 |
139 | try:
140 | with open('config.json', 'r') as in_file:
141 | config = json.load(in_file)
142 | pages_to_fetch = config['pages_to_fetch']
143 | except FileNotFoundError:
144 | with open('config.json', 'w') as out_file:
145 | pages_to_fetch = 100
146 | config = {'pages_to_fetch': 1}
147 | json.dump(config, out_file)
148 | self.update_daily_price(pages_to_fetch)
149 |
150 | tmnow = datetime.now()
151 | lastday = calendar.monthrange(tmnow.year, tmnow.month)[1]
152 | if tmnow.month == 12 and tmnow.day == lastday:
153 | tmnext = tmnow.replace(year=tmnow.year+1, month=1, day=1,
154 | hour=17, minute=0, second=0)
155 | elif tmnow.day == lastday:
156 | tmnext = tmnow.replace(month=tmnow.month+1, day=1, hour=17,
157 | minute=0, second=0)
158 | else:
159 | tmnext = tmnow.replace(day=tmnow.day+1, hour=17, minute=0,
160 | second=0)
161 | tmdiff = tmnext - tmnow
162 | secs = tmdiff.seconds
163 | t = Timer(secs, self.execute_daily)
164 | print("Waiting for next update ({}) ... ".format(tmnext.strftime
165 | ('%Y-%m-%d %H:%M')))
166 | t.start()
167 |
168 | if __name__ == '__main__':
169 | dbu = DBUpdater()
170 | dbu.execute_daily()
171 |
--------------------------------------------------------------------------------
/05_Stock_Price_API/Investar/MarketDB.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | #from bs4 import BeautifulSoup
3 | #import urllib
4 | #from urllib.request import urlopen
5 | import pymysql
6 | #import time
7 | #import pandas.io.sql as sql
8 | from datetime import datetime
9 | #from threading import Timer
10 | #import matplotlib.pyplot as plt
11 |
12 | class MarketDB:
13 | def __init__(self):
14 | """생성자: MariaDB 연결 및 종목코드 딕셔너리 생성"""
15 | self.conn = pymysql.connect(host='localhost', user='root', password='myPa$$word', db='INVESTAR', charset='utf8')
16 | self.codes = dict()
17 | self.getCompanyInfo()
18 |
19 | def __del__(self):
20 | """소멸자: MariaDB 연결 해제"""
21 | self.conn.close()
22 |
23 | def getCompanyInfo(self):
24 | """company_info 테이블에서 읽어와서 companyData와 codes에 저장"""
25 | sql = "SELECT * FROM company_info"
26 | companyInfo = pd.read_sql(sql, self.conn)
27 | for idx in range(len(companyInfo)):
28 | self.codes[companyInfo['code'].values[idx]] = companyInfo['company'].values[idx]
29 |
30 | def getDailyPrice(self, code, startDate, endDate):
31 | """daily_price 테이블에서 읽어와서 데이터프레임으로 반환"""
32 | sql = "SELECT * FROM daily_price WHERE code = '{}' and date >= '{}' and date <= '{}'".format(code, startDate, endDate)
33 | df = pd.read_sql(sql, self.conn)
34 | df.index = df['date']
35 | return df
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/05_Stock_Price_API/ch05_01_YahooFinance_SEC.py:
--------------------------------------------------------------------------------
1 | from pandas_datareader import data as pdr
2 | import yfinance as yf
3 | yf.pdr_override()
4 | import matplotlib.pyplot as plt
5 |
6 | df = pdr.get_data_yahoo('005930.KS', '2017-01-01') # ①
7 |
8 | plt.figure(figsize=(9, 6))
9 | plt.subplot(2, 1, 1) # ②
10 | plt.title('Samsung Electronics (Yahoo Finance)')
11 | plt.plot(df.index, df['Close'], 'c', label='Close') # ③
12 | plt.plot(df.index, df['Adj Close'], 'b--', label='Adj Close') # ④
13 | plt.legend(loc='best')
14 | plt.subplot(2, 1, 2) # ⑤
15 | plt.bar(df.index, df['Volume'], color='g', label='Volume') # ⑥
16 | plt.legend(loc='best')
17 | plt.show()
18 |
--------------------------------------------------------------------------------
/05_Stock_Price_API/ch05_02_NaverDatabase_SEC.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | from Investar import Analyzer # ①
3 |
4 | mk = Analyzer.MarketDB() # ②
5 | df = mk.get_daily_price('005930', '2017-07-10', '2018-06-30') # ③
6 |
7 | plt.figure(figsize=(9, 6))
8 | plt.subplot(2, 1, 1)
9 | plt.title('Samsung Electronics (Investar Data)')
10 | plt.plot(df.index, df['close'], 'c', label='Close') # ④
11 | plt.legend(loc='best')
12 | plt.subplot(2, 1, 2)
13 | plt.bar(df.index, df['volume'], color='g', label='Volume')
14 | plt.legend(loc='best')
15 | plt.show()
--------------------------------------------------------------------------------
/05_Stock_Price_API/ch05_03_SelectVersion.py:
--------------------------------------------------------------------------------
1 | import pymysql
2 |
3 | connection = pymysql.connect(host='localhost', port=3306, db='INVESTAR',
4 | user='root', passwd='myPa$$word', autocommit=True)
5 |
6 | cursor = connection.cursor()
7 | cursor.execute("SELECT VERSION();")
8 | result = cursor.fetchone()
9 |
10 | print ("MariaDB version : {}".format(result))
11 |
12 | connection.close()
--------------------------------------------------------------------------------
/05_Stock_Price_API/ch05_04_CreateTable.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS company_info (
2 | code VARCHAR(20),
3 | company VARCHAR(40),
4 | last_update DATE,
5 | PRIMARY KEY (code)
6 | );
7 |
8 | CREATE TABLE IF NOT EXISTS daily_price (
9 | code VARCHAR(20),
10 | date DATE,
11 | open BIGINT(20),
12 | high BIGINT(20),
13 | low BIGINT(20),
14 | close BIGINT(20),
15 | diff BIGINT(20),
16 | volume BIGINT(20),
17 | PRIMARY KEY (code, date)
18 | );
19 |
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_Client1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_Client1.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_Client2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_Client2.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_ConfigJson.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_ConfigJson.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_ConfigMy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_ConfigMy.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_DBUpdater.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_DBUpdater.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_DBUpdater1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_DBUpdater1.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_DBUpdater2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_DBUpdater2.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_Download2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_Download2.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_GetDailyPrice.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_GetDailyPrice.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_HeidiSQL1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_HeidiSQL1.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_HeidiSQL2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_HeidiSQL2.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_HeidiSQL3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_HeidiSQL3.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_HeidiSQL4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_HeidiSQL4.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_HeidiSQL5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_HeidiSQL5.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_Installer.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_Installer.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_Installer2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_Installer2.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_Installer3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_Installer3.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/API_RunRegistry.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/API_RunRegistry.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/DBUpdaterEx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/DBUpdaterEx.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/DBUpdaterEx2024-03-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/DBUpdaterEx2024-03-03.png
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/DBUpdaterEx_2024-06-30.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/DBUpdaterEx_2024-06-30.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/ExceptionOccured_2024-06-30.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/ExceptionOccured_2024-06-30.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/GetDailyPrice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/GetDailyPrice.png
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/HeidiSQL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/HeidiSQL.png
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/MTV2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/MTV2.png
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/MariaDB_Download.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/MariaDB_Download.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/MariaDB_DownloadPage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/MariaDB_DownloadPage.jpg
--------------------------------------------------------------------------------
/05_Stock_Price_API/imgs/MariaDB_IndexPage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/05_Stock_Price_API/imgs/MariaDB_IndexPage.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/ch06_01_EfficientFrontier.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | import matplotlib.pyplot as plt
4 | from Investar import Analyzer
5 |
6 | mk = Analyzer.MarketDB()
7 | stocks = ['삼성전자', 'SK하이닉스', '현대자동차', 'NAVER']
8 | df = pd.DataFrame()
9 | for s in stocks:
10 | df[s] = mk.get_daily_price(s, '2016-01-04', '2018-04-27')['close']
11 |
12 | daily_ret = df.pct_change()
13 | annual_ret = daily_ret.mean() * 252
14 | daily_cov = daily_ret.cov()
15 | annual_cov = daily_cov * 252
16 |
17 | port_ret = []
18 | port_risk = []
19 | port_weights = []
20 |
21 | for _ in range(20000):
22 | weights = np.random.random(len(stocks))
23 | weights /= np.sum(weights)
24 |
25 | returns = np.dot(weights, annual_ret)
26 | risk = np.sqrt(np.dot(weights.T, np.dot(annual_cov, weights)))
27 |
28 | port_ret.append(returns)
29 | port_risk.append(risk)
30 | port_weights.append(weights)
31 |
32 | portfolio = {'Returns': port_ret, 'Risk': port_risk}
33 | for i, s in enumerate(stocks):
34 | portfolio[s] = [weight[i] for weight in port_weights]
35 | df = pd.DataFrame(portfolio)
36 | df = df[['Returns', 'Risk'] + [s for s in stocks]]
37 |
38 | df.plot.scatter(x='Risk', y='Returns', figsize=(8, 6), grid=True)
39 | plt.title('Efficient Frontier')
40 | plt.xlabel('Risk')
41 | plt.ylabel('Expected Returns')
42 | plt.show()
--------------------------------------------------------------------------------
/06_Trading_Strategy/ch06_02_PortfolioOptimization.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | import matplotlib.pyplot as plt
4 | from Investar import Analyzer
5 |
6 | mk = Analyzer.MarketDB()
7 | stocks = ['삼성전자', 'SK하이닉스', '현대자동차', 'NAVER']
8 | df = pd.DataFrame()
9 | for s in stocks:
10 | df[s] = mk.get_daily_price(s, '2016-01-04', '2018-04-27')['close']
11 |
12 | daily_ret = df.pct_change()
13 | annual_ret = daily_ret.mean() * 252
14 | daily_cov = daily_ret.cov()
15 | annual_cov = daily_cov * 252
16 |
17 | port_ret = []
18 | port_risk = []
19 | port_weights = []
20 | sharpe_ratio = []
21 |
22 | for _ in range(20000):
23 | weights = np.random.random(len(stocks))
24 | weights /= np.sum(weights)
25 |
26 | returns = np.dot(weights, annual_ret)
27 | risk = np.sqrt(np.dot(weights.T, np.dot(annual_cov, weights)))
28 |
29 | port_ret.append(returns)
30 | port_risk.append(risk)
31 | port_weights.append(weights)
32 | sharpe_ratio.append(returns/risk) # ①
33 |
34 | portfolio = {'Returns': port_ret, 'Risk': port_risk, 'Sharpe': sharpe_ratio}
35 | for i, s in enumerate(stocks):
36 | portfolio[s] = [weight[i] for weight in port_weights]
37 | df = pd.DataFrame(portfolio)
38 | df = df[['Returns', 'Risk', 'Sharpe'] + [s for s in stocks]] # ②
39 |
40 | max_sharpe = df.loc[df['Sharpe'] == df['Sharpe'].max()] # ③
41 | min_risk = df.loc[df['Risk'] == df['Risk'].min()] # ④
42 |
43 | df.plot.scatter(x='Risk', y='Returns', c='Sharpe', cmap='viridis',
44 | edgecolors='k', figsize=(11,7), grid=True) # ⑤
45 | plt.scatter(x=max_sharpe['Risk'], y=max_sharpe['Returns'], c='r',
46 | marker='*', s=300) # ⑥
47 | plt.scatter(x=min_risk['Risk'], y=min_risk['Returns'], c='r',
48 | marker='X', s=200) # ⑦
49 | plt.title('Portfolio Optimization')
50 | plt.xlabel('Risk')
51 | plt.ylabel('Expected Returns')
52 | plt.show()
--------------------------------------------------------------------------------
/06_Trading_Strategy/ch06_03_BollingerBand.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | from Investar import Analyzer
3 |
4 | mk = Analyzer.MarketDB()
5 | df = mk.get_daily_price('NAVER', '2019-01-02')
6 |
7 | df['MA20'] = df['close'].rolling(window=20).mean() # ①
8 | df['stddev'] = df['close'].rolling(window=20).std() # ②
9 | df['upper'] = df['MA20'] + (df['stddev'] * 2) # ③
10 | df['lower'] = df['MA20'] - (df['stddev'] * 2) # ④
11 | df = df[19:] # ⑤
12 |
13 | plt.figure(figsize=(9, 5))
14 | plt.plot(df.index, df['close'], color='#0000ff', label='Close') # ⑥
15 | plt.plot(df.index, df['upper'], 'r--', label = 'Upper band') # ⑦
16 | plt.plot(df.index, df['MA20'], 'k--', label='Moving average 20')
17 | plt.plot(df.index, df['lower'], 'c--', label = 'Lower band')
18 | plt.fill_between(df.index, df['upper'], df['lower'], color='0.9') # ⑧
19 | plt.legend(loc='best')
20 | plt.title('NAVER Bollinger Band (20 day, 2 std)')
21 | plt.show()
22 |
--------------------------------------------------------------------------------
/06_Trading_Strategy/ch06_04_BollingerBand_PercentB.py:
--------------------------------------------------------------------------------
1 |
2 | import matplotlib.pyplot as plt
3 | from Investar import Analyzer
4 |
5 | mk = Analyzer.MarketDB()
6 | df = mk.get_daily_price('NAVER', '2019-01-02')
7 |
8 | df['MA20'] = df['close'].rolling(window=20).mean()
9 | df['stddev'] = df['close'].rolling(window=20).std()
10 | df['upper'] = df['MA20'] + (df['stddev'] * 2)
11 | df['lower'] = df['MA20'] - (df['stddev'] * 2)
12 | df['PB'] = (df['close'] - df['lower']) / (df['upper'] - df['lower']) # ①
13 | df = df[19:]
14 |
15 | plt.figure(figsize=(9, 8))
16 | plt.subplot(2, 1, 1) # ②
17 | plt.plot(df.index, df['close'], color='#0000ff', label='Close')
18 | plt.plot(df.index, df['upper'], 'r--', label = 'Upper band')
19 | plt.plot(df.index, df['MA20'], 'k--', label='Moving average 20')
20 | plt.plot(df.index, df['lower'], 'c--', label = 'Lower band')
21 | plt.fill_between(df.index, df['upper'], df['lower'], color='0.9')
22 | plt.title('NAVER Bollinger Band(20 day, 2 std)')
23 | plt.legend(loc='best')
24 |
25 | plt.subplot(2, 1, 2) # ③
26 | plt.plot(df.index, df['PB'], color='b', label='%B') # ④
27 | plt.grid(True)
28 | plt.legend(loc='best')
29 | plt.show()
30 |
--------------------------------------------------------------------------------
/06_Trading_Strategy/ch06_05_BollingerBand_BandWidth.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | from Investar import Analyzer
3 |
4 | mk = Analyzer.MarketDB()
5 | df = mk.get_daily_price('NAVER', '2019-01-02')
6 | df['MA20'] = df['close'].rolling(window=20).mean()
7 | df['stddev'] = df['close'].rolling(window=20).std()
8 | df['upper'] = df['MA20'] + (df['stddev'] * 2)
9 | df['lower'] = df['MA20'] - (df['stddev'] * 2)
10 | df['bandwidth'] = (df['upper'] - df['lower']) / df['MA20'] * 100 # ①
11 | df = df[19:]
12 |
13 | plt.figure(figsize=(9, 8))
14 | plt.subplot(2, 1, 1)
15 | plt.plot(df.index, df['close'], color='#0000ff', label='Close')
16 | plt.plot(df.index, df['upper'], 'r--', label ='Upper band')
17 | plt.plot(df.index, df['MA20'], 'k--', label='Moving average 20')
18 | plt.plot(df.index, df['lower'], 'c--', label ='Lower band')
19 | plt.fill_between(df.index, df['upper'], df['lower'], color='0.9')
20 | plt.title('NAVER Bollinger Band(20 day, 2 std)')
21 | plt.legend(loc='best')
22 | plt.subplot(2, 1, 2)
23 | plt.plot(df.index, df['bandwidth'], color='m', label='BandWidth') # ②
24 | plt.grid(True)
25 | plt.legend(loc='best')
26 | plt.show()
27 |
--------------------------------------------------------------------------------
/06_Trading_Strategy/ch06_06_BollingerBand_TrendFollowing.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | from Investar import Analyzer
3 |
4 | mk = Analyzer.MarketDB()
5 | df = mk.get_daily_price('NAVER', '2019-01-02')
6 |
7 | df['MA20'] = df['close'].rolling(window=20).mean()
8 | df['stddev'] = df['close'].rolling(window=20).std()
9 | df['upper'] = df['MA20'] + (df['stddev'] * 2)
10 | df['lower'] = df['MA20'] - (df['stddev'] * 2)
11 | df['PB'] = (df['close'] - df['lower']) / (df['upper'] - df['lower'])
12 | df['TP'] = (df['high'] + df['low'] + df['close']) / 3
13 | df['PMF'] = 0
14 | df['NMF'] = 0
15 | for i in range(len(df.close)-1):
16 | if df.TP.values[i] < df.TP.values[i+1]:
17 | df.PMF.values[i+1] = df.TP.values[i+1] * df.volume.values[i+1]
18 | df.NMF.values[i+1] = 0
19 | else:
20 | df.NMF.values[i+1] = df.TP.values[i+1] * df.volume.values[i+1]
21 | df.PMF.values[i+1] = 0
22 | df['MFR'] = (df.PMF.rolling(window=10).sum() /
23 | df.NMF.rolling(window=10).sum())
24 | df['MFI10'] = 100 - 100 / (1 + df['MFR'])
25 | df = df[19:]
26 |
27 | plt.figure(figsize=(9, 8))
28 | plt.subplot(2, 1, 1)
29 | plt.title('NAVER Bollinger Band(20 day, 2 std) - Trend Following')
30 | plt.plot(df.index, df['close'], color='#0000ff', label='Close')
31 | plt.plot(df.index, df['upper'], 'r--', label ='Upper band')
32 | plt.plot(df.index, df['MA20'], 'k--', label='Moving average 20')
33 | plt.plot(df.index, df['lower'], 'c--', label ='Lower band')
34 | plt.fill_between(df.index, df['upper'], df['lower'], color='0.9')
35 | for i in range(len(df.close)):
36 | if df.PB.values[i] > 0.8 and df.MFI10.values[i] > 80: # ①
37 | plt.plot(df.index.values[i], df.close.values[i], 'r^') # ②
38 | elif df.PB.values[i] < 0.2 and df.MFI10.values[i] < 20: # ③
39 | plt.plot(df.index.values[i], df.close.values[i], 'bv') # ④
40 | plt.legend(loc='best')
41 |
42 | plt.subplot(2, 1, 2)
43 | plt.plot(df.index, df['PB'] * 100, 'b', label='%B x 100') # ⑤
44 | plt.plot(df.index, df['MFI10'], 'g--', label='MFI(10 day)') # ⑥
45 | plt.yticks([-20, 0, 20, 40, 60, 80, 100, 120]) # ⑦
46 | for i in range(len(df.close)):
47 | if df.PB.values[i] > 0.8 and df.MFI10.values[i] > 80:
48 | plt.plot(df.index.values[i], 0, 'r^')
49 | elif df.PB.values[i] < 0.2 and df.MFI10.values[i] < 20:
50 | plt.plot(df.index.values[i], 0, 'bv')
51 | plt.grid(True)
52 | plt.legend(loc='best')
53 | plt.show();
54 |
--------------------------------------------------------------------------------
/06_Trading_Strategy/ch06_07_BollingerBand_IIP21.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | from Investar import Analyzer
3 |
4 | mk = Analyzer.MarketDB()
5 | df = mk.get_daily_price('SK하이닉스', '2018-11-01')
6 |
7 | df['MA20'] = df['close'].rolling(window=20).mean()
8 | df['stddev'] = df['close'].rolling(window=20).std()
9 | df['upper'] = df['MA20'] + (df['stddev'] * 2)
10 | df['lower'] = df['MA20'] - (df['stddev'] * 2)
11 | df['PB'] = (df['close'] - df['lower']) / (df['upper'] - df['lower'])
12 |
13 | df['II'] = (2*df['close']-df['high']-df['low'])
14 | /(df['high']-df['low'])*df['volume'] # ①
15 | df['IIP21'] = df['II'].rolling(window=21).sum()
16 | /df['volume'].rolling(window=21).sum()*100 # ②
17 | df = df.dropna()
18 |
19 | plt.figure(figsize=(9, 9))
20 | plt.subplot(3, 1, 1)
21 | plt.title('SK Hynix Bollinger Band(20 day, 2 std) - Reversals')
22 | plt.plot(df.index, df['close'], 'b', label='Close')
23 | plt.plot(df.index, df['upper'], 'r--', label ='Upper band')
24 | plt.plot(df.index, df['MA20'], 'k--', label='Moving average 20')
25 | plt.plot(df.index, df['lower'], 'c--', label ='Lower band')
26 | plt.fill_between(df.index, df['upper'], df['lower'], color='0.9')
27 |
28 | plt.legend(loc='best')
29 | plt.subplot(3, 1, 2)
30 | plt.plot(df.index, df['PB'], 'b', label='%b')
31 | plt.grid(True)
32 | plt.legend(loc='best')
33 |
34 | plt.subplot(3, 1, 3) # ③
35 | plt.bar(df.index, df['IIP21'], color='g', label='II% 21day') # ④
36 | plt.grid(True)
37 | plt.legend(loc='best')
38 | plt.show()
--------------------------------------------------------------------------------
/06_Trading_Strategy/ch06_08_BollingerBand_Reversals.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | from Investar import Analyzer
3 |
4 | mk = Analyzer.MarketDB()
5 | df = mk.get_daily_price('SK하이닉스', '2018-11-01')
6 |
7 | df['MA20'] = df['close'].rolling(window=20).mean()
8 | df['stddev'] = df['close'].rolling(window=20).std()
9 | df['upper'] = df['MA20'] + (df['stddev'] * 2)
10 | df['lower'] = df['MA20'] - (df['stddev'] * 2)
11 | df['PB'] = (df['close'] - df['lower']) / (df['upper'] - df['lower'])
12 |
13 | df['II'] = (2*df['close']-df['high']-df['low'])/(df['high']-df['low'])*df['volume']
14 | df['IIP21'] = df['II'].rolling(window=21).sum()/df['volume'].rolling(window=21).sum()*100
15 | df = df.dropna()
16 |
17 | plt.figure(figsize=(9, 9))
18 | plt.subplot(3, 1, 1)
19 | plt.title('SK Hynix Bollinger Band(20 day, 2 std) - Reversals')
20 | plt.plot(df.index, df['close'], 'm', label='Close')
21 | plt.plot(df.index, df['upper'], 'r--', label ='Upper band')
22 | plt.plot(df.index, df['MA20'], 'k--', label='Moving average 20')
23 | plt.plot(df.index, df['lower'], 'c--', label ='Lower band')
24 | plt.fill_between(df.index, df['upper'], df['lower'], color='0.9')
25 | for i in range(0, len(df.close)):
26 | if df.PB.values[i] < 0.05 and df.IIP21.values[i] > 0: # ①
27 | plt.plot(df.index.values[i], df.close.values[i], 'r^') # ②
28 | elif df.PB.values[i] > 0.95 and df.IIP21.values[i] < 0: # ③
29 | plt.plot(df.index.values[i], df.close.values[i], 'bv') # ④
30 | plt.legend(loc='best')
31 |
32 | plt.subplot(3, 1, 2)
33 | plt.plot(df.index, df['PB'], 'b', label='%b')
34 | plt.grid(True)
35 | plt.legend(loc='best')
36 |
37 | plt.subplot(3, 1, 3)
38 | plt.bar(df.index, df['IIP21'], color='g', label='II% 21day')
39 | for i in range(0, len(df.close)):
40 | if df.PB.values[i] < 0.05 and df.IIP21.values[i] > 0:
41 | plt.plot(df.index.values[i], 0, 'r^') # ⑤
42 | elif df.PB.values[i] > 0.95 and df.IIP21.values[i] < 0:
43 | plt.plot(df.index.values[i], 0, 'bv') # ⑥
44 | plt.grid(True)
45 | plt.legend(loc='best')
46 | plt.show()
47 |
48 |
49 |
--------------------------------------------------------------------------------
/06_Trading_Strategy/ch06_09_FirstScreen.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import matplotlib.pyplot as plt
3 | import datetime
4 | from mpl_finance import candlestick_ohlc
5 | #from mplfinance.original_flavor import candlestick_ohlc
6 | import matplotlib.dates as mdates
7 | from Investar import Analyzer
8 |
9 | mk = Analyzer.MarketDB()
10 | df = mk.get_daily_price('엔씨소프트', '2017-01-01')
11 |
12 |
13 | ema60 = df.close.ewm(span=60).mean() # ① 종가의 12주 지수 이동평균
14 | ema130 = df.close.ewm(span=130).mean() # ② 종가의 12주 지수 이동평균
15 | macd = ema60 - ema130 # ③ MACD선
16 | signal = macd.ewm(span=45).mean() # ④ 신호선(MACD의 9주 지수 이동평균)
17 | macdhist = macd - signal # ⑤ MACD 히스토그램
18 |
19 | df = df.assign(ema130=ema130, ema60=ema60, macd=macd, signal=signal,
20 | macdhist=macdhist).dropna()
21 | df['number'] = df.index.map(mdates.date2num) # ⑥
22 | ohlc = df[['number','open','high','low','close']]
23 |
24 | plt.figure(figsize=(9, 7))
25 | p1 = plt.subplot(2, 1, 1)
26 | plt.title('Triple Screen Trading - First Screen (NCSOFT)')
27 | plt.grid(True)
28 | candlestick_ohlc(p1, ohlc.values, width=.6, colorup='red',
29 | colordown='blue') # ⑦
30 | p1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
31 | plt.plot(df.number, df['ema130'], color='c', label='EMA130')
32 | plt.legend(loc='best')
33 |
34 | p2 = plt.subplot(2, 1, 2)
35 | plt.grid(True)
36 | p2.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
37 | plt.bar(df.number, df['macdhist'], color='m', label='MACD-Hist')
38 | plt.plot(df.number, df['macd'], color='b', label='MACD')
39 | plt.plot(df.number, df['signal'], 'g--', label='MACD-Signal')
40 | plt.legend(loc='best')
41 | plt.show()
42 |
--------------------------------------------------------------------------------
/06_Trading_Strategy/ch06_09_FirstScreenEx.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import mplfinance as mpf
3 | from Investar import Analyzer
4 |
5 | mk = Analyzer.MarketDB()
6 | df = mk.get_daily_price('엔씨소프트', '2017-01-01', '2019-12-31')
7 | df.index = pd.to_datetime(df.date)
8 | df = df[['open', 'high', 'low', 'close', 'volume']]
9 |
10 | ema60 = df.close.ewm(span=60).mean() # ① 종가의 12주 지수 이동평균
11 | ema130 = df.close.ewm(span=130).mean() # ② 종가의 26주 지수 이동평균
12 | macd = ema60 - ema130 # ③ MACD선
13 | signal = macd.ewm(span=45).mean() # ④ 신호선(MACD의 9주 지수 이동평균)
14 | macdhist = macd - signal # ⑤ MACD 히스토그램
15 |
16 | apds = [mpf.make_addplot(ema130, color='c'),
17 | mpf.make_addplot(macdhist, type='bar', panel=1, color='m'),
18 | mpf.make_addplot(macd, panel=1, color='b'),
19 | mpf.make_addplot(signal, panel=1, color='g'),
20 | ]
21 | mc = mpf.make_marketcolors(up='r', down='b', inherit=True)
22 | stl = mpf.make_mpf_style(marketcolors=mc)
23 | mpf.plot(df, title='Triple Screen Trading - First Screen (NCSOFT)', type='candle',
24 | addplot=apds, figsize=(9,7), panel_ratios=(1,1), style=stl)
25 |
--------------------------------------------------------------------------------
/06_Trading_Strategy/ch06_10_SecondScreen.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import matplotlib.pyplot as plt
3 | import datetime
4 | from mpl_finance import candlestick_ohlc
5 | #from mplfinance.original_flavor import candlestick_ohlc
6 | import matplotlib.dates as mdates
7 | from Investar import Analyzer
8 |
9 | mk = Analyzer.MarketDB()
10 | df = mk.get_daily_price('엔씨소프트', '2017-01-01')
11 |
12 | ema60 = df.close.ewm(span=60).mean()
13 | ema130 = df.close.ewm(span=130).mean()
14 | macd = ema60 - ema130
15 | signal = macd.ewm(span=45).mean()
16 | macdhist = macd - signal
17 |
18 | df = df.assign(ema130=ema130, ema60=ema60, macd=macd, signal=signal,
19 | macdhist=macdhist).dropna()
20 | df['number'] = df.index.map(mdates.date2num)
21 | ohlc = df[['number','open','high','low','close']]
22 |
23 | ndays_high = df.high.rolling(window=14, min_periods=1).max() # ①
24 | ndays_low = df.low.rolling(window=14, min_periods=1).min() # ②
25 | fast_k = (df.close - ndays_low) / (ndays_high - ndays_low) * 100 # ③
26 | slow_d= fast_k.rolling(window=3).mean() # ④
27 | df = df.assign(fast_k=fast_k, slow_d=slow_d).dropna() # ⑤
28 |
29 | plt.figure(figsize=(9, 7))
30 | p1 = plt.subplot(2, 1, 1)
31 | plt.title('Triple Screen Trading - Second Screen (NCSOFT)')
32 | plt.grid(True)
33 | candlestick_ohlc(p1, ohlc.values, width=.6, colorup='red', colordown='blue')
34 | p1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
35 | plt.plot(df.number, df['ema130'], color='c', label='EMA130')
36 | plt.legend(loc='best')
37 | p1 = plt.subplot(2, 1, 2)
38 | plt.grid(True)
39 | p1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
40 | plt.plot(df.number, df['fast_k'], color='c', label='%K')
41 | plt.plot(df.number, df['slow_d'], color='k', label='%D')
42 | plt.yticks([0, 20, 80, 100]) # ⑥
43 | plt.legend(loc='best')
44 | plt.show()
45 |
--------------------------------------------------------------------------------
/06_Trading_Strategy/ch06_11_TripleScreen.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import matplotlib.pyplot as plt
3 | import datetime
4 | from mpl_finance import candlestick_ohlc
5 | #from mplfinance.original_flavor import candlestick_ohlc
6 | import matplotlib.dates as mdates
7 | from Investar import Analyzer
8 |
9 | mk = Analyzer.MarketDB()
10 | df = mk.get_daily_price('엔씨소프트', '2017-01-01')
11 |
12 | ema60 = df.close.ewm(span=60).mean()
13 | ema130 = df.close.ewm(span=130).mean()
14 | macd = ema60 - ema130
15 | signal = macd.ewm(span=45).mean()
16 | macdhist = macd - signal
17 | df = df.assign(ema130=ema130, ema60=ema60, macd=macd, signal=signal, macdhist=macdhist).dropna()
18 |
19 | df['number'] = df.index.map(mdates.date2num)
20 | ohlc = df[['number','open','high','low','close']]
21 |
22 | ndays_high = df.high.rolling(window=14, min_periods=1).max()
23 | ndays_low = df.low.rolling(window=14, min_periods=1).min()
24 |
25 | fast_k = (df.close - ndays_low) / (ndays_high - ndays_low) * 100
26 | slow_d = fast_k.rolling(window=3).mean()
27 | df = df.assign(fast_k=fast_k, slow_d=slow_d).dropna()
28 |
29 | plt.figure(figsize=(9, 9))
30 | p1 = plt.subplot(3, 1, 1)
31 | plt.title('Triple Screen Trading (NCSOFT)')
32 | plt.grid(True)
33 | candlestick_ohlc(p1, ohlc.values, width=.6, colorup='red', colordown='blue')
34 | p1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
35 | plt.plot(df.number, df['ema130'], color='c', label='EMA130')
36 | for i in range(1, len(df.close)):
37 | if df.ema130.values[i-1] < df.ema130.values[i] and \
38 | df.slow_d.values[i-1] >= 20 and df.slow_d.values[i] < 20:
39 | plt.plot(df.number.values[i], 250000, 'r^')
40 | elif df.ema130.values[i-1] > df.ema130.values[i] and \
41 | df.slow_d.values[i-1] <= 80 and df.slow_d.values[i] > 80:
42 | plt.plot(df.number.values[i], 250000, 'bv')
43 | plt.legend(loc='best')
44 |
45 | p2 = plt.subplot(3, 1, 2)
46 | plt.grid(True)
47 | p2.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
48 | plt.bar(df.number, df['macdhist'], color='m', label='MACD-Hist')
49 | plt.plot(df.number, df['macd'], color='b', label='MACD')
50 | plt.plot(df.number, df['signal'], 'g--', label='MACD-Signal')
51 | plt.legend(loc='best')
52 |
53 | p3 = plt.subplot(3, 1, 3)
54 | plt.grid(True)
55 | p3.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
56 | plt.plot(df.number, df['fast_k'], color='c', label='%K')
57 | plt.plot(df.number, df['slow_d'], color='k', label='%D')
58 | plt.yticks([0, 20, 80, 100])
59 | plt.legend(loc='best')
60 | plt.show()
61 |
--------------------------------------------------------------------------------
/06_Trading_Strategy/ch06_12_DualMomentum.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import pymysql
3 | from datetime import datetime
4 | from datetime import timedelta
5 | from Investar import Analyzer
6 |
7 | class DualMomentum:
8 | def __init__(self):
9 | """생성자: KRX 종목코드(codes)를 구하기 위한 MarkgetDB 객체 생성"""
10 | self.mk = Analyzer.MarketDB()
11 |
12 | def get_rltv_momentum(self, start_date, end_date, stock_count):
13 | """특정 기간 동안 수익률이 제일 높았던 stock_count 개의 종목들 (상대 모멘텀)
14 | - start_date : 상대 모멘텀을 구할 시작일자 ('2020-01-01')
15 | - end_date : 상대 모멘텀을 구할 종료일자 ('2020-12-31')
16 | - stock_count : 상대 모멘텀을 구할 종목수
17 | """
18 | connection = pymysql.connect(host='localhost', port=3306,
19 | db='INVESTAR', user='root', passwd='******', autocommit=True)
20 | cursor = connection.cursor()
21 |
22 | # 사용자가 입력한 시작일자를 DB에서 조회되는 일자로 보정
23 | sql = f"select max(date) from daily_price where date <= '{start_date}'"
24 | cursor.execute(sql)
25 | result = cursor.fetchone()
26 | if (result[0] is None):
27 | print ("start_date : {} -> returned None".format(sql))
28 | return
29 | start_date = result[0].strftime('%Y-%m-%d')
30 |
31 |
32 | # 사용자가 입력한 종료일자를 DB에서 조회되는 일자로 보정
33 | sql = f"select max(date) from daily_price where date <= '{end_date}'"
34 | cursor.execute(sql)
35 | result = cursor.fetchone()
36 | if (result[0] is None):
37 | print ("end_date : {} -> returned None".format(sql))
38 | return
39 | end_date = result[0].strftime('%Y-%m-%d')
40 |
41 |
42 | # KRX 종목별 수익률을 구해서 2차원 리스트 형태로 추가
43 | rows = []
44 | columns = ['code', 'company', 'old_price', 'new_price', 'returns']
45 | for _, code in enumerate(self.mk.codes):
46 | sql = f"select close from daily_price "\
47 | f"where code='{code}' and date='{start_date}'"
48 | cursor.execute(sql)
49 | result = cursor.fetchone()
50 | if (result is None):
51 | continue
52 | old_price = int(result[0])
53 | sql = f"select close from daily_price "\
54 | f"where code='{code}' and date='{end_date}'"
55 | cursor.execute(sql)
56 | result = cursor.fetchone()
57 | if (result is None):
58 | continue
59 | new_price = int(result[0])
60 | returns = (new_price / old_price - 1) * 100
61 | rows.append([code, self.mk.codes[code], old_price, new_price,
62 | returns])
63 |
64 |
65 | # 상대 모멘텀 데이터프레임을 생성한 후 수익률순으로 출력
66 | df = pd.DataFrame(rows, columns=columns)
67 | df = df[['code', 'company', 'old_price', 'new_price', 'returns']]
68 | df = df.sort_values(by='returns', ascending=False)
69 | df = df.head(stock_count)
70 | df.index = pd.Index(range(stock_count))
71 | connection.close()
72 | print(df)
73 | print(f"\nRelative momentum ({start_date} ~ {end_date}) : "\
74 | f"{df['returns'].mean():.2f}% \n")
75 | return df
76 |
77 | def get_abs_momentum(self, rltv_momentum, start_date, end_date):
78 | """특정 기간 동안 상대 모멘텀에 투자했을 때의 평균 수익률 (절대 모멘텀)
79 | - rltv_momentum : get_rltv_momentum() 함수의 리턴값 (상대 모멘텀)
80 | - start_date : 절대 모멘텀을 구할 매수일 ('2020-01-01')
81 | - end_date : 절대 모멘텀을 구할 매도일 ('2020-12-31')
82 | """
83 | stockList = list(rltv_momentum['code'])
84 | connection = pymysql.connect(host='localhost', port=3306,
85 | db='INVESTAR', user='root', passwd='******', autocommit=True)
86 | cursor = connection.cursor()
87 |
88 |
89 | # 사용자가 입력한 매수일을 DB에서 조회되는 일자로 변경
90 | sql = f"select max(date) from daily_price "\
91 | f"where date <= '{start_date}'"
92 | cursor.execute(sql)
93 | result = cursor.fetchone()
94 | if (result[0] is None):
95 | print ("{} -> returned None".format(sql))
96 | return
97 | start_date = result[0].strftime('%Y-%m-%d')
98 |
99 |
100 | # 사용자가 입력한 매도일을 DB에서 조회되는 일자로 변경
101 | sql = f"select max(date) from daily_price "\
102 | f"where date <= '{end_date}'"
103 | cursor.execute(sql)
104 | result = cursor.fetchone()
105 | if (result[0] is None):
106 | print ("{} -> returned None".format(sql))
107 | return
108 | end_date = result[0].strftime('%Y-%m-%d')
109 |
110 |
111 | # 상대 모멘텀의 종목별 수익률을 구해서 2차원 리스트 형태로 추가
112 | rows = []
113 | columns = ['code', 'company', 'old_price', 'new_price', 'returns']
114 | for _, code in enumerate(stockList):
115 | sql = f"select close from daily_price "\
116 | f"where code='{code}' and date='{start_date}'"
117 | cursor.execute(sql)
118 | result = cursor.fetchone()
119 | if (result is None):
120 | continue
121 | old_price = int(result[0])
122 | sql = f"select close from daily_price "\
123 | f"where code='{code}' and date='{end_date}'"
124 | cursor.execute(sql)
125 | result = cursor.fetchone()
126 | if (result is None):
127 | continue
128 | new_price = int(result[0])
129 | returns = (new_price / old_price - 1) * 100
130 | rows.append([code, self.mk.codes[code], old_price, new_price,
131 | returns])
132 |
133 |
134 | # 절대 모멘텀 데이터프레임을 생성한 후 수익률순으로 출력
135 | df = pd.DataFrame(rows, columns=columns)
136 | df = df[['code', 'company', 'old_price', 'new_price', 'returns']]
137 | df = df.sort_values(by='returns', ascending=False)
138 | connection.close()
139 | print(df)
140 | print(f"\nAbasolute momentum ({start_date} ~ {end_date}) : "\
141 | f"{df['returns'].mean():.2f}%")
142 | return
143 |
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/AbsoluteMomentum.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/AbsoluteMomentum.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/BollingerBand.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/BollingerBand.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/BollingerBand_BandWidth.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/BollingerBand_BandWidth.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/BollingerBand_IIP21.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/BollingerBand_IIP21.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/BollingerBand_MFI.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/BollingerBand_MFI.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/BollingerBand_PercentB.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/BollingerBand_PercentB.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/BollingerBand_Reversals.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/BollingerBand_Reversals.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/BollingerBand_TrendFollowing.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/BollingerBand_TrendFollowing.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/BollingerBand_TrendFollowing_Naver.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/BollingerBand_TrendFollowing_Naver.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/BollingerOnBollingerBands.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/BollingerOnBollingerBands.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/DualMomentum.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/DualMomentum.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/DualMomentumInvesting.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/DualMomentumInvesting.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/FirstScreen.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/FirstScreen.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/Long-TermSecretsToShort-TermTrading.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/Long-TermSecretsToShort-TermTrading.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/Portpolio_optimization.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/Portpolio_optimization.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/RelativeMomentum.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/RelativeMomentum.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/SecondScreen.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/SecondScreen.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/TheNewTradingForALiving.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/TheNewTradingForALiving.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/TripleScreen.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/TripleScreen.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/ch06_EfficientFrontierLine.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/ch06_EfficientFrontierLine.jpg
--------------------------------------------------------------------------------
/06_Trading_Strategy/imgs/efficient_frontier.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/06_Trading_Strategy/imgs/efficient_frontier.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/ch07_01_index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | This is title.
4 |
5 |
6 | This is heading1 text.
7 | This is heading2 text.
8 | This is heading3 text.
9 | This is a paragraph.
10 | This is plain text.
11 | This is bold text.
12 | This is Italic text.
13 | This is strike text.
14 |
15 | - the first orderd list
16 | - the second orderd list
17 | - the third orderd list
18 |
19 |
20 | - unorderd list
21 | - unorderd list
22 | - unorderd list
23 |
24 |
25 |
26 | table header 1 |
27 | table header 2 |
28 | table header 3 |
29 |
30 |
31 | table data 4 |
32 | table data 5 |
33 | table data 6 |
34 |
35 |
36 | table data 7 |
37 | table data 8 |
38 | table data 9 |
39 |
40 |
41 | Visit Django homepage!
42 |
43 |
44 |
--------------------------------------------------------------------------------
/07_Django_and_Automation/ch07_02_index.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 | This is title.
5 |
6 |
7 |
8 | This is heading1 text.
9 | This is heading2 text.
10 | This is heading3 text.
11 | This is a paragraph.
12 | This is plain text.
13 | This is bold text.
14 | This is Italic text.
15 | This is strike text.
16 |
17 | - the first orderd list
18 | - the second orderd list
19 | - the third orderd list
20 |
21 |
22 | - unorderd list
23 | - unorderd list
24 | - unorderd list
25 |
26 |
27 |
28 | table header 1 |
29 | table header 2 |
30 | table header 3 |
31 |
32 |
33 | table data 4 |
34 | table data 5 |
35 | table data 6 |
36 |
37 |
38 | table data 7 |
39 | table data 8 |
40 | table data 9 |
41 |
42 |
43 | Visit Django homepage!
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/07_Django_and_Automation/ch07_03_style.css:
--------------------------------------------------------------------------------
1 | /* 테이블 데이터와 테이블 헤더에 대한 스타일 지정 */
2 | table td, table th {
3 | border: 1px solid #ddd;
4 | padding: 8px;
5 | }
6 |
7 | /* 테이블 행이 짝수 번째일 경우의 색상 지정 */
8 | table tr:nth-child(even){background-color: #f2f2f2;}
9 |
10 | /* 테이블 행에 마우스 커서를 올렸을 때의 색상 지정 */
11 | table tr:hover {background-color: #ddd;}
12 |
13 | /* 테이블 헤더에 대한 스타일 지정 */
14 | table th {
15 | padding-top: 12px;
16 | padding-bottom: 12px;
17 | text-align: left;
18 | background-color: #4CAF50;
19 | color: white;
20 | }
21 |
--------------------------------------------------------------------------------
/07_Django_and_Automation/ch07_04_balance_views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 | from bs4 import BeautifulSoup
3 | from urllib.request import urlopen
4 |
5 | def get_data(symbol):
6 | url = 'http://finance.naver.com/item/sise.nhn?code={}'.format(symbol)
7 | with urlopen(url) as doc:
8 | soup = BeautifulSoup(doc, "lxml", from_encoding="euc-kr")
9 | cur_price = soup.find('strong', id='_nowVal') # ①
10 | cur_rate = soup.find('strong', id='_rate') # ②
11 | stock = soup.find('title') # ③
12 | stock_name = stock.text.split(':')[0].strip() # ④
13 | return cur_price.text, cur_rate.text.strip(), stock_name
14 |
15 | def main_view(request):
16 | querydict = request.GET.copy()
17 | mylist = querydict.lists() # ⑤
18 | rows = []
19 | total = 0
20 |
21 | for x in mylist:
22 | cur_price, cur_rate, stock_name = get_data(x[0]) # ⑥
23 | price = cur_price.replace(',', '')
24 | stock_count = format(int(x[1][0]), ',') # ⑦
25 | sum = int(price) * int(x[1][0])
26 | stock_sum = format(sum, ',')
27 | rows.append([stock_name, x[0], cur_price, stock_count, cur_rate,
28 | stock_sum]) # ⑧
29 | total = total + int(price) * int(x[1][0]) # ⑨
30 |
31 | total_amount = format(total, ',')
32 | values = {'rows' : rows, 'total' : total_amount} # ⑩
33 | return render(request, 'balance.html', values) # ⑪
34 |
--------------------------------------------------------------------------------
/07_Django_and_Automation/ch07_05_balance.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 | Balance: {{ total }}
5 |
6 |
7 |
8 |
9 |
10 | 종목명 |
11 | 종목코드 |
12 | 현재가 |
13 | 주식수 |
14 | 등락률 |
15 | 평가금액 |
16 |
17 | {% for row in rows %}
18 |
19 | {% for x in row %}
20 | {{ x }} |
21 | {% endfor %}
22 |
23 | {% endfor %}
24 |
25 | 계좌 잔고 |
26 | {{ total }} |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/07_Django_and_Automation/ch07_06_b_style.css:
--------------------------------------------------------------------------------
1 | /* 테이블 폰트 및 테두리선 설정 */
2 | table {
3 | font-family: Arial, Helvetica, sans-serif;
4 | border-collapse: collapse;
5 | }
6 |
7 | /* 테이블 데이터 및 테이블 헤더 설정 */
8 | table td, table th {
9 | border: 1px solid #ddd;
10 | padding: 8px;
11 | }
12 |
13 | /* 테이블 행이 짝수 번째일 때의 색상 지정 */
14 | table tr:nth-child(even){background-color: #f2f2f2;}
15 |
16 | /* 테이블 행 위에 마우스 컬러가 올려졌을 때의 색상 지정 */
17 | table tr:hover {background-color: #ddd;}
18 |
19 | /* 테이블 헤더의 스타일 지정 */
20 | table th {
21 | padding-top: 12px;
22 | padding-bottom: 12px;
23 | background-color: #4D92AA;
24 | text-align: center;
25 | color: white;
26 | }
27 |
28 | /* 테이블 데이터의 텍스트 정렬 방식을 지정 */
29 | table td:nth-child(1){text-align: left;}
30 | table td:nth-child(2){text-align: center;}
31 | table td:nth-child(3){text-align: right;}
32 | table td:nth-child(4){text-align: right;}
33 | table td:nth-child(5){text-align: right;}
34 | table td:nth-child(6){text-align: right;}
--------------------------------------------------------------------------------
/07_Django_and_Automation/ch07_07_Slack_SendMessage.py:
--------------------------------------------------------------------------------
1 | from slacker import Slacker
2 | slack = Slacker('xoxb-341411373331-856655856231-e6wtlNsuv384K9fjtaIS7WiL')
3 |
4 | markdown_text = '''
5 | This message is plain.
6 | *This message is bold.*
7 | `This message is code.`
8 | _This message is italic._
9 | ~This message is strike.~
10 | '''
11 |
12 | attach_dict = {
13 | 'color' :'#ff0000',
14 | 'author_name':'INVESTAR',
15 | "author_link":'github.com/investar',
16 | 'title' :'오늘의 증시 KOSPI',
17 | 'title_link' :'http://finance.naver.com/sise/sise_index.nhn?code=KOSPI',
18 | 'text' :'2,326.13 △11.89 (+0.51%)',
19 | 'image_url' :'ssl.pstatic.net/imgstock/chart3/day/KOSPI.png'
20 | }
21 |
22 | attach_list = [attach_dict]
23 | slack.chat.post_message(channel="#general", text=markdown_text, attachments=attach_list)
--------------------------------------------------------------------------------
/07_Django_and_Automation/ch07_08_Backtrader_RSI.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 | import backtrader as bt
3 |
4 | class MyStrategy(bt.Strategy): # ①
5 | def __init__(self):
6 | self.rsi = bt.indicators.RSI(self.data.close) # ②
7 | def next(self): # ③
8 | if not self.position:
9 | if self.rsi < 30:
10 | self.order = self.buy()
11 | else:
12 | if self.rsi > 70:
13 | self.order = self.sell()
14 |
15 | cerebro = bt.Cerebro() # ④
16 | cerebro.addstrategy(MyStrategy)
17 | data = bt.feeds.YahooFinanceData(dataname='036570.KS', # ⑤
18 | fromdate=datetime(2017, 1, 1), todate=datetime(2019, 12, 1))
19 | cerebro.adddata(data)
20 | cerebro.broker.setcash(10000000) # ⑥
21 | cerebro.addsizer(bt.sizers.SizerFix, stake=30) # ⑦
22 |
23 | print(f'Initial Portfolio Value : {cerebro.broker.getvalue():,.0f} KRW')
24 | cerebro.run() # ⑧
25 | print(f'Final Portfolio Value : {cerebro.broker.getvalue():,.0f} KRW')
26 | cerebro.plot() # ⑨
--------------------------------------------------------------------------------
/07_Django_and_Automation/ch07_09_Backtrader_RSI_SMA.py:
--------------------------------------------------------------------------------
1 | import backtrader as bt
2 | from datetime import datetime
3 |
4 | class MyStrategy(bt.Strategy):
5 | def __init__(self):
6 | self.dataclose = self.datas[0].close
7 | self.order = None
8 | self.buyprice = None
9 | self.buycomm = None
10 | self.rsi = bt.indicators.RSI_SMA(self.data.close, period=21)
11 |
12 | def notify_order(self, order): # ①
13 | if order.status in [order.Submitted, order.Accepted]:
14 | return
15 | if order.status in [order.Completed]: # ②
16 | if order.isbuy():
17 | self.log(f'BUY : 주가 {order.executed.price:,.0f}, '
18 | f'수량 {order.executed.size:,.0f}, '
19 | f'수수료 {order.executed.comm:,.0f}, '
20 | f'자산 {cerebro.broker.getvalue():,.0f}')
21 | self.buyprice = order.executed.price
22 | self.buycomm = order.executed.comm
23 | else:
24 | self.log(f'SELL : 주가 {order.executed.price:,.0f}, '
25 | f'수량 {order.executed.size:,.0f}, '
26 | f'수수료 {order.executed.comm:,.0f}, '
27 | f'자산 {cerebro.broker.getvalue():,.0f}')
28 | self.bar_executed = len(self)
29 | elif order.status in [order.Canceled]:
30 | self.log('ORDER CANCELD')
31 | elif order.status in [order.Margin]:
32 | self.log('ORDER MARGIN')
33 | elif order.status in [order.Rejected]:
34 | self.log('ORDER REJECTED')
35 | self.order = None
36 |
37 | def next(self):
38 | if not self.position:
39 | if self.rsi < 30:
40 | self.order = self.buy()
41 | else:
42 | if self.rsi > 70:
43 | self.order = self.sell()
44 |
45 | def log(self, txt, dt=None): # ③
46 | dt = self.datas[0].datetime.date(0)
47 | print(f'[{dt.isoformat()}] {txt}')
48 |
49 | cerebro = bt.Cerebro()
50 | cerebro.addstrategy(MyStrategy)
51 | data = bt.feeds.YahooFinanceData(dataname='036570.KS',
52 | fromdate=datetime(2017, 1, 1), todate=datetime(2019, 12, 1))
53 | cerebro.adddata(data)
54 | cerebro.broker.setcash(10000000)
55 | cerebro.broker.setcommission(commission=0.0014) # ④
56 | cerebro.addsizer(bt.sizers.PercentSizer, percents=90) # ⑤
57 |
58 | print(f'Initial Portfolio Value : {cerebro.broker.getvalue():,.0f} KRW')
59 | cerebro.run()
60 | print(f'Final Portfolio Value : {cerebro.broker.getvalue():,.0f} KRW')
61 | cerebro.plot(style='candlestick') # ⑥
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/BackTrader_PlotRSISMA.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/BackTrader_PlotRSISMA.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Backtrader_Homepage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Backtrader_Homepage.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Backtrader_PlotRSI.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Backtrader_PlotRSI.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Balance_Naver.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Balance_Naver.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Balance_Sample2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Balance_Sample2.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Django_AdminLogin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Django_AdminLogin.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Django_AdminPage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Django_AdminPage.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Django_Hello.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Django_Hello.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Django_Homepage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Django_Homepage.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Django_IndexPage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Django_IndexPage.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Django_IndexTree.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Django_IndexTree.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Django_Logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Django_Logo.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Django_PIP.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Django_PIP.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Django_Python.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Django_Python.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Django_Rocket.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Django_Rocket.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Django_StaticImage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Django_StaticImage.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Django_Superuser.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Django_Superuser.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Django_Tree.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Django_Tree.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Slack_Bots.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Slack_Bots.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Slack_CreateApp.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Slack_CreateApp.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Slack_Scopes.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Slack_Scopes.jpg
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Slack_SmartPhone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Slack_SmartPhone.png
--------------------------------------------------------------------------------
/07_Django_and_Automation/imgs/Slack_mySlackBot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/07_Django_and_Automation/imgs/Slack_mySlackBot.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/ch08_01_AutoConnect.py:
--------------------------------------------------------------------------------
1 | from pywinauto import application
2 | import time
3 | import os
4 |
5 | os.system('taskkill /IM coStarter* /F /T')
6 | os.system('taskkill /IM CpStart* /F /T')
7 | os.system('taskkill /IM DibServer* /F /T')
8 | os.system('wmic process where "name like \'%coStarter%\'" call terminate')
9 | os.system('wmic process where "name like \'%CpStart%\'" call terminate')
10 | os.system('wmic process where "name like \'%DibServer%\'" call terminate')
11 | time.sleep(5)
12 |
13 | app = application.Application()
14 | app.start('C:\CREON\STARTER\coStarter.exe /prj:cp /id:userid /pwd:pa$$word /pwdcert:certPa$$word /autostart')
15 | time.sleep(60)
16 |
--------------------------------------------------------------------------------
/08_Volatility_Breakout/ch08_02_DynamicPageScraping_NaverETF.py:
--------------------------------------------------------------------------------
1 | from selenium import webdriver
2 | from bs4 import BeautifulSoup
3 | import pandas as pd
4 |
5 | # 옵션값 설정
6 | opt = webdriver.ChromeOptions()
7 | opt.add_argument('headless')
8 |
9 | # 웹드라이버를 통해 네이버 금융 ETF 페이지에 접속
10 | drv = webdriver.Chrome('C:\myPackage\chromedriver.exe', options=opt)
11 | drv.implicitly_wait(3)
12 | drv.get('https://finance.naver.com/sise/etf.nhn')
13 |
14 | # 뷰티풀 수프로 테이블을 스크래핑
15 | bs = BeautifulSoup(drv.page_source, 'lxml')
16 | drv.quit()
17 | table = bs.find_all("table", class_="type_1 type_etf")
18 | df = pd.read_html(str(table), header=0)[0]
19 |
20 | # 불필요한 열과 행을 삭제하고 인덱스를 재설정해서 출력
21 | df = df.drop(columns=['Unnamed: 9'])
22 | df = df.dropna()
23 | df.index = range(1, len(df)+1)
24 | print(df)
25 |
26 | # 링크 주소에 포함된 종목코드를 추출하여 전체 종목코드와 종목명 출력
27 | etf_td = bs.find_all("td", class_="ctg")
28 | etfs = {}
29 | for td in etf_td:
30 | s = str(td.a["href"]).split('=')
31 | code = s[-1]
32 | etfs[td.a.text] = code
33 | print("etfs :", etfs)
--------------------------------------------------------------------------------
/08_Volatility_Breakout/ch08_03_EtfAlgoTrader.py:
--------------------------------------------------------------------------------
1 | import os, sys, ctypes
2 | import win32com.client
3 | import pandas as pd
4 | from datetime import datetime
5 | from slacker import Slacker
6 | import time, calendar
7 | from bs4 import BeautifulSoup
8 | from urllib.request import urlopen
9 | from selenium import webdriver
10 | from selenium.webdriver.chrome.options import Options
11 |
12 | slack = Slacker('xoxb-341411373331-390645946323-wPFYKNbhlgef4bMUiP1CvSyX')
13 | def dbgout(message):
14 | """인자로 받은 문자열을 파이썬 셸과 슬랙으로 동시에 출력한다."""
15 | print(datetime.now().strftime('[%m/%d %H:%M:%S]'), message)
16 | strbuf = datetime.now().strftime('[%m/%d %H:%M:%S] ') + message
17 | slack.chat.post_message('#etf-algo-trading', strbuf)
18 |
19 | def printlog(message, *args):
20 | """인자로 받은 문자열을 파이썬 셸에 출력한다."""
21 | print(datetime.now().strftime('[%m/%d %H:%M:%S]'), message, *args)
22 |
23 | # 크레온 플러스 공통 OBJECT
24 | cpCodeMgr = win32com.client.Dispatch('CpUtil.CpStockCode')
25 | cpStatus = win32com.client.Dispatch('CpUtil.CpCybos')
26 | cpTradeUtil = win32com.client.Dispatch('CpTrade.CpTdUtil')
27 | cpStock = win32com.client.Dispatch('DsCbo1.StockMst')
28 | cpOhlc = win32com.client.Dispatch('CpSysDib.StockChart')
29 | cpBalance = win32com.client.Dispatch('CpTrade.CpTd6033')
30 | cpCash = win32com.client.Dispatch('CpTrade.CpTdNew5331A')
31 | cpOrder = win32com.client.Dispatch('CpTrade.CpTd0311')
32 |
33 | def check_creon_system():
34 | """크레온 플러스 시스템 연결 상태를 점검한다."""
35 | # 관리자 권한으로 프로세스 실행 여부
36 | if not ctypes.windll.shell32.IsUserAnAdmin():
37 | printlog('check_creon_system() : admin user -> FAILED')
38 | return False
39 |
40 | # 연결 여부 체크
41 | if (cpStatus.IsConnect == 0):
42 | printlog('check_creon_system() : connect to server -> FAILED')
43 | return False
44 |
45 | # 주문 관련 초기화 - 계좌 관련 코드가 있을 때만 사용
46 | if (cpTradeUtil.TradeInit(0) != 0):
47 | printlog('check_creon_system() : init trade -> FAILED')
48 | return False
49 | return True
50 |
51 | def get_current_price(code):
52 | """인자로 받은 종목의 현재가, 매도호가, 매수호가를 반환한다."""
53 | cpStock.SetInputValue(0, code) # 종목코드에 대한 가격 정보
54 | cpStock.BlockRequest()
55 | item = {}
56 | item['cur_price'] = cpStock.GetHeaderValue(11) # 현재가
57 | item['ask'] = cpStock.GetHeaderValue(16) # 매도호가
58 | item['bid'] = cpStock.GetHeaderValue(17) # 매수호가
59 | return item['cur_price'], item['ask'], item['bid']
60 |
61 | def get_ohlc(code, qty):
62 | """인자로 받은 종목의 OHLC 가격 정보를 qty 개수만큼 반환한다."""
63 | cpOhlc.SetInputValue(0, code) # 종목코드
64 | cpOhlc.SetInputValue(1, ord('2')) # 1:기간, 2:개수
65 | cpOhlc.SetInputValue(4, qty) # 요청개수
66 | cpOhlc.SetInputValue(5, [0, 2, 3, 4, 5]) # 0:날짜, 2~5:OHLC
67 | cpOhlc.SetInputValue(6, ord('D')) # D:일단위
68 | cpOhlc.SetInputValue(9, ord('1')) # 0:무수정주가, 1:수정주가
69 | cpOhlc.BlockRequest()
70 | count = cpOhlc.GetHeaderValue(3) # 3:수신개수
71 | columns = ['open', 'high', 'low', 'close']
72 | index = []
73 | rows = []
74 | for i in range(count):
75 | index.append(cpOhlc.GetDataValue(0, i))
76 | rows.append([cpOhlc.GetDataValue(1, i), cpOhlc.GetDataValue(2, i),
77 | cpOhlc.GetDataValue(3, i), cpOhlc.GetDataValue(4, i)])
78 | df = pd.DataFrame(rows, columns=columns, index=index)
79 | return df
80 |
81 | def get_stock_balance(code):
82 | """인자로 받은 종목의 종목명과 수량을 반환한다."""
83 | cpTradeUtil.TradeInit()
84 | acc = cpTradeUtil.AccountNumber[0] # 계좌번호
85 | accFlag = cpTradeUtil.GoodsList(acc, 1) # -1:전체, 1:주식, 2:선물/옵션
86 | cpBalance.SetInputValue(0, acc) # 계좌번호
87 | cpBalance.SetInputValue(1, accFlag[0]) # 상품구분 - 주식 상품 중 첫번째
88 | cpBalance.SetInputValue(2, 50) # 요청 건수(최대 50)
89 | cpBalance.BlockRequest()
90 | if code == 'ALL':
91 | dbgout('계좌명: ' + str(cpBalance.GetHeaderValue(0)))
92 | dbgout('결제잔고수량 : ' + str(cpBalance.GetHeaderValue(1)))
93 | dbgout('평가금액: ' + str(cpBalance.GetHeaderValue(3)))
94 | dbgout('평가손익: ' + str(cpBalance.GetHeaderValue(4)))
95 | dbgout('종목수: ' + str(cpBalance.GetHeaderValue(7)))
96 | stocks = []
97 | for i in range(cpBalance.GetHeaderValue(7)):
98 | stock_code = cpBalance.GetDataValue(12, i) # 종목코드
99 | stock_name = cpBalance.GetDataValue(0, i) # 종목명
100 | stock_qty = cpBalance.GetDataValue(15, i) # 수량
101 | if code == 'ALL':
102 | dbgout(str(i+1) + ' ' + stock_code + '(' + stock_name + ')'
103 | + ':' + str(stock_qty))
104 | stocks.append({'code': stock_code, 'name': stock_name,
105 | 'qty': stock_qty})
106 | if stock_code == code:
107 | return stock_name, stock_qty
108 | if code == 'ALL':
109 | return stocks
110 | else:
111 | stock_name = cpCodeMgr.CodeToName(code)
112 | return stock_name, 0
113 |
114 | def get_current_cash():
115 | """증거금 100% 주문 가능 금액을 반환한다."""
116 | cpTradeUtil.TradeInit()
117 | acc = cpTradeUtil.AccountNumber[0] # 계좌번호
118 | accFlag = cpTradeUtil.GoodsList(acc, 1) # -1:전체, 1:주식, 2:선물/옵션
119 | cpCash.SetInputValue(0, acc) # 계좌번호
120 | cpCash.SetInputValue(1, accFlag[0]) # 상품구분 - 주식 상품 중 첫번째
121 | cpCash.BlockRequest()
122 | return cpCash.GetHeaderValue(9) # 증거금 100% 주문 가능 금액
123 |
124 | def get_target_price(code):
125 | """매수 목표가를 반환한다."""
126 | try:
127 | time_now = datetime.now()
128 | str_today = time_now.strftime('%Y%m%d')
129 | ohlc = get_ohlc(code, 10)
130 | if str_today == str(ohlc.iloc[0].name):
131 | today_open = ohlc.iloc[0].open
132 | lastday = ohlc.iloc[1]
133 | else:
134 | lastday = ohlc.iloc[0]
135 | today_open = lastday[3]
136 | lastday_high = lastday[1]
137 | lastday_low = lastday[2]
138 | target_price = today_open + (lastday_high - lastday_low) * 0.5
139 | return target_price
140 | except Exception as ex:
141 | dbgout("`get_target_price() -> exception! " + str(ex) + "`")
142 | return None
143 |
144 | def get_movingaverage(code, window):
145 | """인자로 받은 종목에 대한 이동평균가격을 반환한다."""
146 | try:
147 | time_now = datetime.now()
148 | str_today = time_now.strftime('%Y%m%d')
149 | ohlc = get_ohlc(code, 20)
150 | if str_today == str(ohlc.iloc[0].name):
151 | lastday = ohlc.iloc[1].name
152 | else:
153 | lastday = ohlc.iloc[0].name
154 | closes = ohlc['close'].sort_index()
155 | ma = closes.rolling(window=window).mean()
156 | return ma.loc[lastday]
157 | except Exception as ex:
158 | dbgout('get_movingavrg(' + str(window) + ') -> exception! ' + str(ex))
159 | return None
160 |
161 | def buy_etf(code):
162 | """인자로 받은 종목을 최유리 지정가 FOK 조건으로 매수한다."""
163 | try:
164 | global bought_list # 함수 내에서 값 변경을 하기 위해 global로 지정
165 | if code in bought_list: # 매수 완료 종목이면 더 이상 안 사도록 함수 종료
166 | #printlog('code:', code, 'in', bought_list)
167 | return False
168 | time_now = datetime.now()
169 | current_price, ask_price, bid_price = get_current_price(code)
170 | target_price = get_target_price(code) # 매수 목표가
171 | ma5_price = get_movingaverage(code, 5) # 5일 이동평균가
172 | ma10_price = get_movingaverage(code, 10) # 10일 이동평균가
173 | buy_qty = 0 # 매수할 수량 초기화
174 | if ask_price > 0: # 매도호가가 존재하면
175 | buy_qty = buy_amount // ask_price
176 | stock_name, stock_qty = get_stock_balance(code) # 종목명과 보유수량 조회
177 | #printlog('bought_list:', bought_list, 'len(bought_list):',
178 | # len(bought_list), 'target_buy_count:', target_buy_count)
179 | if current_price > target_price and current_price > ma5_price \
180 | and current_price > ma10_price:
181 | printlog(stock_name + '(' + str(code) + ') ' + str(buy_qty) +
182 | 'EA : ' + str(current_price) + ' meets the buy condition!`')
183 | cpTradeUtil.TradeInit()
184 | acc = cpTradeUtil.AccountNumber[0] # 계좌번호
185 | accFlag = cpTradeUtil.GoodsList(acc, 1) # -1:전체,1:주식,2:선물/옵션
186 | # 최유리 FOK 매수 주문 설정
187 | cpOrder.SetInputValue(0, "2") # 2: 매수
188 | cpOrder.SetInputValue(1, acc) # 계좌번호
189 | cpOrder.SetInputValue(2, accFlag[0]) # 상품구분 - 주식 상품 중 첫번째
190 | cpOrder.SetInputValue(3, code) # 종목코드
191 | cpOrder.SetInputValue(4, buy_qty) # 매수할 수량
192 | cpOrder.SetInputValue(7, "2") # 주문조건 0:기본, 1:IOC, 2:FOK
193 | cpOrder.SetInputValue(8, "12") # 주문호가 1:보통, 3:시장가
194 | # 5:조건부, 12:최유리, 13:최우선
195 | # 매수 주문 요청
196 | ret = cpOrder.BlockRequest()
197 | printlog('최유리 FoK 매수 ->', stock_name, code, buy_qty, '->', ret)
198 | if ret == 4:
199 | remain_time = cpStatus.LimitRequestRemainTime
200 | printlog('주의: 연속 주문 제한에 걸림. 대기 시간:', remain_time/1000)
201 | time.sleep(remain_time/1000)
202 | return False
203 | time.sleep(2)
204 | printlog('현금주문 가능금액 :', buy_amount)
205 | stock_name, bought_qty = get_stock_balance(code)
206 | printlog('get_stock_balance :', stock_name, stock_qty)
207 | if bought_qty > 0:
208 | bought_list.append(code)
209 | dbgout("`buy_etf("+ str(stock_name) + ' : ' + str(code) +
210 | ") -> " + str(bought_qty) + "EA bought!" + "`")
211 | except Exception as ex:
212 | dbgout("`buy_etf("+ str(code) + ") -> exception! " + str(ex) + "`")
213 |
214 | def sell_all():
215 | """보유한 모든 종목을 최유리 지정가 IOC 조건으로 매도한다."""
216 | try:
217 | cpTradeUtil.TradeInit()
218 | acc = cpTradeUtil.AccountNumber[0] # 계좌번호
219 | accFlag = cpTradeUtil.GoodsList(acc, 1) # -1:전체, 1:주식, 2:선물/옵션
220 | while True:
221 | stocks = get_stock_balance('ALL')
222 | total_qty = 0
223 | for s in stocks:
224 | total_qty += s['qty']
225 | if total_qty == 0:
226 | return True
227 | for s in stocks:
228 | if s['qty'] != 0:
229 | cpOrder.SetInputValue(0, "1") # 1:매도, 2:매수
230 | cpOrder.SetInputValue(1, acc) # 계좌번호
231 | cpOrder.SetInputValue(2, accFlag[0]) # 주식상품 중 첫번째
232 | cpOrder.SetInputValue(3, s['code']) # 종목코드
233 | cpOrder.SetInputValue(4, s['qty']) # 매도수량
234 | cpOrder.SetInputValue(7, "1") # 조건 0:기본, 1:IOC, 2:FOK
235 | cpOrder.SetInputValue(8, "12") # 호가 12:최유리, 13:최우선
236 | # 최유리 IOC 매도 주문 요청
237 | ret = cpOrder.BlockRequest()
238 | printlog('최유리 IOC 매도', s['code'], s['name'], s['qty'],
239 | '-> cpOrder.BlockRequest() -> returned', ret)
240 | if ret == 4:
241 | remain_time = cpStatus.LimitRequestRemainTime
242 | printlog('주의: 연속 주문 제한, 대기시간:', remain_time/1000)
243 | time.sleep(1)
244 | time.sleep(30)
245 | except Exception as ex:
246 | dbgout("sell_all() -> exception! " + str(ex))
247 |
248 | if __name__ == '__main__':
249 | try:
250 | symbol_list = ['A122630', 'A252670', 'A233740', 'A250780', 'A225130',
251 | 'A280940', 'A261220', 'A217770', 'A295000', 'A176950']
252 | bought_list = [] # 매수 완료된 종목 리스트
253 | target_buy_count = 5 # 매수할 종목 수
254 | buy_percent = 0.19
255 | printlog('check_creon_system() :', check_creon_system()) # 크레온 접속 점검
256 | stocks = get_stock_balance('ALL') # 보유한 모든 종목 조회
257 | total_cash = int(get_current_cash()) # 100% 증거금 주문 가능 금액 조회
258 | buy_amount = total_cash * buy_percent # 종목별 주문 금액 계산
259 | printlog('100% 증거금 주문 가능 금액 :', total_cash)
260 | printlog('종목별 주문 비율 :', buy_percent)
261 | printlog('종목별 주문 금액 :', buy_amount)
262 | printlog('시작 시간 :', datetime.now().strftime('%m/%d %H:%M:%S'))
263 | soldout = False;
264 |
265 | while True:
266 | t_now = datetime.now()
267 | t_9 = t_now.replace(hour=9, minute=0, second=0, microsecond=0)
268 | t_start = t_now.replace(hour=9, minute=5, second=0, microsecond=0)
269 | t_sell = t_now.replace(hour=15, minute=15, second=0, microsecond=0)
270 | t_exit = t_now.replace(hour=15, minute=20, second=0,microsecond=0)
271 | today = datetime.today().weekday()
272 | if today == 5 or today == 6: # 토요일이나 일요일이면 자동 종료
273 | printlog('Today is', 'Saturday.' if today == 5 else 'Sunday.')
274 | sys.exit(0)
275 | if t_9 < t_now < t_start and soldout == False:
276 | soldout = True
277 | sell_all()
278 | if t_start < t_now < t_sell : # AM 09:05 ~ PM 03:15 : 매수
279 | for sym in symbol_list:
280 | if len(bought_list) < target_buy_count:
281 | buy_etf(sym)
282 | time.sleep(1)
283 | if t_now.minute == 30 and 0 <= t_now.second <= 5:
284 | get_stock_balance('ALL')
285 | time.sleep(5)
286 | if t_sell < t_now < t_exit: # PM 03:15 ~ PM 03:20 : 일괄 매도
287 | if sell_all() == True:
288 | dbgout('`sell_all() returned True -> self-destructed!`')
289 | sys.exit(0)
290 | if t_exit < t_now: # PM 03:20 ~ :프로그램 종료
291 | dbgout('`self-destructed!`')
292 | sys.exit(0)
293 | time.sleep(3)
294 | except Exception as ex:
295 | dbgout('`main -> exception! ' + str(ex) + '`')
296 |
297 |
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/NaverFinance_Naver.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/NaverFinance_Naver.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_ConfirmOrder.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_ConfirmOrder.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_CreonBalance.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_CreonBalance.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_CreonDownload.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_CreonDownload.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_CreonPlusTray.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_CreonPlusTray.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_CreonPlustLogin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_CreonPlustLogin.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_CurrentPrice.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_CurrentPrice.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_EtfAlogTraderLog.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_EtfAlogTraderLog.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_EtfSise.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_EtfSise.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_HeadlessChrome.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_HeadlessChrome.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_IdleAdmin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_IdleAdmin.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_JobExecute.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_JobExecute.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_JobName.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_JobName.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_JobOperation.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_JobOperation.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_JobScheduler.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_JobScheduler.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_JobTrigger.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_JobTrigger.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_OHLC.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_OHLC.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_PythonAdmin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_PythonAdmin.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_PythonwAdmin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_PythonwAdmin.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_SlackMessage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_SlackMessage.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_TigerHoga.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_TigerHoga.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_TigerSise.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_TigerSise.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_Trigger.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_Trigger.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_VolatilityBreakout.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_VolatilityBreakout.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VB_WinSearch.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VB_WinSearch.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/VolatilityBreakout.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/VolatilityBreakout.jpg
--------------------------------------------------------------------------------
/08_Volatility_Breakout/imgs/yahoo_finance.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/08_Volatility_Breakout/imgs/yahoo_finance.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/ch09_01_StepFunction.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib.pyplot as plt
3 |
4 | def stepfunc(x):
5 | return np.where(x <= 0, 0, 1)
6 |
7 | x = np.arange(-10, 10, 0.1)
8 | y = stepfunc(x)
9 |
10 | plt.plot(x, y)
11 | plt.title('step function')
12 | plt.show()
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/ch09_02_SigmoidFunction.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib.pyplot as plt
3 |
4 | def sigmoid(x):
5 | return 1 / (1 + np.exp(-x))
6 |
7 | x = np.arange(-10, 10, 0.1)
8 | y = sigmoid(x)
9 |
10 | plt.plot(x, y)
11 | plt.title('sigmoid function')
12 | plt.show()
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/ch09_03_TanhFunction.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib.pyplot as plt
3 |
4 | def tanh(x):
5 | return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))
6 |
7 | x = np.arange(-10, 10, 0.1)
8 | y = tanh(x)
9 |
10 | plt.plot(x, y)
11 | plt.title('tanh function')
12 | plt.show()
13 |
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/ch09_04_ReLUFunction.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib.pyplot as plt
3 |
4 | def relu(x):
5 | return np.maximum(0, x)
6 |
7 | x = np.arange(-10, 10, 0.1)
8 | y = relu(x)
9 |
10 | plt.plot(x, y)
11 | plt.title('ReLU function')
12 | plt.show()
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/ch09_05_SoftmaxFunction.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib.pyplot as plt
3 |
4 | def softmax(x):
5 | return np.exp(x) / np.sum(np.exp(x))
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/ch09_06_MLP_HiddenLayer.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | X = np.array([10, 20]) # ①
3 | W1 = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
4 | B1 = np.array([1, 2, 3]) # ③
5 |
6 | def sigmoid(x):
7 | return 1 / (1 + np.exp(-x))
8 |
9 | A1 = np.dot(X, W1) + B1
10 | Z1 = sigmoid(A1)
11 |
12 | print('A1 :', A1)
13 | print('Z1 :', Z1)
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/ch09_07_MLP_OutputLayer.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | X = np.array([10, 20]) # ①
3 | W1 = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
4 | B1 = np.array([1, 2, 3]) # ③
5 |
6 | def sigmoid(x):
7 | return 1 / (1 + np.exp(-x))
8 |
9 | A1 = np.dot(X, W1) + B1
10 | Z1 = sigmoid(A1)
11 |
12 | W2 = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
13 | B2 = np.array([0.1, 0.2])
14 |
15 | A2 = np.dot(Z1, W2) + B2
16 | Y = sigmoid(A2)
17 |
18 | print('A2 :', A2)
19 | print('Y :', Y)
20 |
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/ch09_08_LinearRegression.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pylab as plt
2 | import tensorflow as tf
3 |
4 | x_data = [1, 2, 3, 4, 5]
5 | y_data = [2, 3, 4, 5, 6]
6 |
7 | w = tf.Variable(0.7)
8 | b = tf.Variable(0.7)
9 | learn_rate = 0.01
10 |
11 | print(f'step| w| b| cost')
12 | print(f'----|-----|-----|-----')
13 |
14 | for i in range(1, 1101):
15 | with tf.GradientTape() as tape:
16 | hypothesis = w * x_data + b
17 | cost = tf.reduce_mean((hypothesis - y_data)**2) # tf.losses.mean_squared_error(y, y_hat)
18 | dw, db = tape.gradient(cost, [w, b])
19 | w.assign_sub(learn_rate * dw) # a = a - b
20 | b.assign_sub(learn_rate * db)
21 |
22 | if i in [1, 3, 5, 10, 1000, 1100]:
23 | print(f"{i:4d}| {w.numpy():.2f}| {b.numpy():.2f}| {cost:.2f}")
24 | plt.figure(figsize=(7, 7))
25 | plt.title(f'[Step {i:d}] h(x) = { w.numpy():.2f}x + {b.numpy():.2f}')
26 | plt.plot(x_data, y_data, 'o') # ⑥
27 | plt.plot(x_data, w * x_data + b, 'r', label='hypothesis') # ⑦
28 | plt.xlabel('x_data')
29 | plt.ylabel('y_data')
30 | plt.xlim(0, 6)
31 | plt.ylim(1, 7)
32 | plt.legend(loc='best')
33 | plt.show()
34 |
35 |
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/ch09_09_RNN_StockPrediction.py:
--------------------------------------------------------------------------------
1 | from tensorflow.keras import Sequential
2 | from tensorflow.keras.layers import Dense, LSTM, Dropout
3 | import numpy as np
4 | import matplotlib.pyplot as plt
5 | from Investar import Analyzer
6 |
7 | mk = Analyzer.MarketDB()
8 | raw_df = mk.get_daily_price('삼성전자', '2018-05-04', '2020-01-22')
9 |
10 | window_size = 10
11 | data_size = 5
12 |
13 | def MinMaxScaler(data):
14 | """최솟값과 최댓값을 이용하여 0 ~ 1 값으로 변환"""
15 | numerator = data - np.min(data, 0)
16 | denominator = np.max(data, 0) - np.min(data, 0)
17 | # 0으로 나누기 에러가 발생하지 않도록 매우 작은 값(1e-7)을 더해서 나눔
18 | return numerator / (denominator + 1e-7)
19 |
20 | dfx = raw_df[['open','high','low','volume', 'close']]
21 | dfx = MinMaxScaler(dfx)
22 | dfy = dfx[['close']]
23 |
24 | x = dfx.values.tolist()
25 | y = dfy.values.tolist()
26 |
27 | data_x = []
28 | data_y = []
29 | for i in range(len(y) - window_size):
30 | _x = x[i : i + window_size] # 다음 날 종가(i+windows_size)는 포함되지 않음
31 | _y = y[i + window_size] # 다음 날 종가
32 | data_x.append(_x)
33 | data_y.append(_y)
34 | print(_x, "->", _y)
35 |
36 | train_size = int(len(data_y) * 0.7)
37 | train_x = np.array(data_x[0 : train_size])
38 | train_y = np.array(data_y[0 : train_size])
39 |
40 | test_size = len(data_y) - train_size
41 | test_x = np.array(data_x[train_size : len(data_x)])
42 | test_y = np.array(data_y[train_size : len(data_y)])
43 |
44 | # 모델 생성
45 | model = Sequential()
46 | model.add(LSTM(units=10, activation='relu', return_sequences=True, input_shape=(window_size, data_size)))
47 | model.add(Dropout(0.1))
48 | model.add(LSTM(units=10, activation='relu'))
49 | model.add(Dropout(0.1))
50 | model.add(Dense(units=1))
51 | model.summary()
52 |
53 | model.compile(optimizer='adam', loss='mean_squared_error')
54 | model.fit(train_x, train_y, epochs=60, batch_size=30)
55 | pred_y = model.predict(test_x)
56 |
57 | # Visualising the results
58 | plt.figure()
59 | plt.plot(test_y, color='red', label='real SEC stock price')
60 | plt.plot(pred_y, color='blue', label='predicted SEC stock price')
61 | plt.title('SEC stock price prediction')
62 | plt.xlabel('time')
63 | plt.ylabel('stock price')
64 | plt.legend()
65 | plt.show()
66 |
67 | # raw_df.close[-1] : dfy.close[-1] = x : pred_y[-1]
68 | print("Tomorrow's SEC price :", raw_df.close[-1] * pred_y[-1] / dfy.close[-1], 'KRW')
69 |
70 |
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_Difference.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_Difference.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_LR_Step1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_LR_Step1.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_LR_Step2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_LR_Step2.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_LR_Step3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_LR_Step3.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_LR_Step4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_LR_Step4.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_LR_Step5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_LR_Step5.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_LR_Step6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_LR_Step6.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_LTSM1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_LTSM1.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_LTSM2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_LTSM2.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_MLP.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_MLP.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_PerceptronImage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_PerceptronImage.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_RNN.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_RNN.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_ReLUFunc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_ReLUFunc.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_SigmoidFunc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_SigmoidFunc.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_StepFunc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_StepFunc.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_StockPricePrediction.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_StockPricePrediction.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_StockPricePrediction_Cmd.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_StockPricePrediction_Cmd.jpg
--------------------------------------------------------------------------------
/09_Deep_Learning_Prediction/imgs/AI_TanhFunc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/09_Deep_Learning_Prediction/imgs/AI_TanhFunc.jpg
--------------------------------------------------------------------------------
/10_Appendix_(Python_Built-in_Functions_and_AES-256_Encryption).pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/10_Appendix_(Python_Built-in_Functions_and_AES-256_Encryption).pdf
--------------------------------------------------------------------------------
/PowerPoint_Materials.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/INVESTAR/StockAnalysisInPython/e356b8fd80fcc48ef666d5f7bffcc22ae2ad66f4/PowerPoint_Materials.pptx
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 파이썬 증권 데이터 분석 (Stock Analysis in Python)
2 | 본 깃허브에서는 『파이썬 증권 데이터 분석』(한빛출판사, 2020) 서적과 관련된 소스 코드와 추가 자료를 공유합니다.
3 |
4 | - 소스 코드는 각 장별 디렉터리에 존재하며, 이미지 파일들은 각 장별로 imgs 디렉터리에 존재합니다.
5 |
6 | - 114 페이지 소스코드의 이미지 파일 URL은 http://bit.ly/2JnsHnT → http://bit.ly/3ZZyeXQ 변경됐습니다.
7 |
8 | - 지면 관계 상 싣지 못한 파이썬 내장함수표와 AES-256 암복호화 실습은
9 | 10_Appendix_(Python_Built-in_Functions_and_AES-256_Encryption).pdf 파일을 참고하시기 바랍니다.
10 |
11 | - 서적에 삽입된 그림의 PPT 원본은 PowerPoint_Materials.pptx 파일에 있습니다.
12 |
13 | ## 네이버 일별시세 전일비 데이터 변경에 따른 DBUpdaterEx 수정 내역
14 | 네이버 일별시세의 전일비 데이터가 기존에는 숫자로만 제공되었으나, 전일비 데이터에 상승/하락/보합 등의 문자열이 추가되면서 아래처럼 Exception이 발생하는 현상이 있었습니다.
15 | 
16 |
17 | 전일비 데이터(diff)에서 문자를 제외하고 숫자만 추출하도록 DBUpdaterEx.py에 아래처럼 코드 한 줄을 추가하였습니다. (2024-06-30 기준)
18 | 
19 |
20 | ## 시세조회 DB 업데이트 및 시세조회 API 빠른 사용법
21 | 책이 출간된지 제법 시간이 흘렀고 파이썬 라이브러리에도 변경된 내용이 많아서 최신 라이브러리 간 호환성이 확보되지 않을 수 있습니다. 시세조회 DB를 빠르게 구축해서 시세조회 API를 사용하고자 하시는 분은 아래처럼 requirements.txt에 명시된 라이브러리 버전으로 설치하시 바랍니다. (2024-03-03 기준)
22 | 1. Python 설치
23 | ① Win+R키를 눌러서 실행창이 나오면 appwiz.cpl를 입력한 후 '프로그램 변경 및 제거' 창에서 기존에 설치된 Python을 전부 제거
24 | ② https://www.python.org/ftp/python/3.8.1/python-3.8.1-amd64.exe 다운로드
25 | ③ 설치 프로그램을 실행한 후 'Add Python 3.8 to PATH' 체크박스에 체크한 후 'Install Now'로 설치
26 | ④ Python 설치가 완료되면 명령창을 새로 실행해서 python --version 명령으로 Python 3.8.1이 설치됐는지 확인
27 | 2. Python 라이브러리 설치
28 | ① https://github.com/INVESTAR/StockAnalysisInPython/blob/master/02_Python_Programming/requirements.txt 다운로드
29 | ② c:\Users\hwang\Downloads>python -m pip install --upgrade pip
30 | ③ c:\Users\hwang\Downloads>pip install -r requirements.txt
31 | 3. Investar 데이터베이스 생성
32 | ① https://mariadb.com/downloads/ 접속
33 | ② MariaDB Community -> Windows 64bit -> 10.5.24GA 다운로드해서 실행
34 | ③ 바탕화면에 생성된 HediSQL 아이콘을 더블 클릭하여 실행한 후 Investar DB를 utf8_general_ci 로 생성
35 | 
36 | ④ 쿼리 탭을 클릭해서 테이블 생성 쿼리를 실행
37 | CREATE TABLE IF NOT EXISTS company_info (
38 | code VARCHAR(20),
39 | company VARCHAR(40),
40 | last_update DATE,
41 | PRIMARY KEY (code)
42 | );
43 | CREATE TABLE IF NOT EXISTS daily_price (
44 | code VARCHAR(20),
45 | date DATE,
46 | open BIGINT(20),
47 | high BIGINT(20),
48 | low BIGINT(20),
49 | close BIGINT(20),
50 | diff BIGINT(20),
51 | volume BIGINT(20),
52 | PRIMARY KEY (code, date)
53 | );
54 | 5. myPackage 생성 및 API 호출
55 | ① c:\myPackage\Investar 폴더를 생성
56 | ② https://github.com/INVESTAR/StockAnalysisInPython/tree/master/05_Stock_Price_API/Investar 폴더로부터 Analyzer.py, DBUpdaterEx.py, MarketDB.py를 다운로드 받아서 c:\myPackage\Investar 폴더로 복사
57 | ③ c:\myPackage\Investar>python DBUpdaterEx.py 실행해서 데이터베이스를 업데이트
58 | 
59 | ④ IDLE에서 c:\myPackage\Invesat\Analyzer.py 파일을 실행한 뒤 아래처럼 API 호출
60 | 
61 |
62 | ## 네이버 금융의 웹 스크레이핑 차단에 대한 안내
63 | 아래 내용은 2021년 10월 11일에 발행된 5쇄 서적부터 반영되어 있으며,
64 | 기존에 발행된 1쇄~4쇄 서적을 구매하신 분들은 아래 내용을 참고하시기 바랍니다.
65 |
66 | 2021년 1월 7일 저녁부터 네이버 금융에서 웹 크롤러의 스크레이핑을 차단하기 시작했습니다.
67 | 따라서 기존 방식대로 urllib.request.urlopen()이나 pandas.read_html()를 사용할 경우,
68 | 더 이상 네이버 금융의 웹 페이지를 읽어올 수 없습니다.
69 |
70 | 네이버 금융 서버에서 http 패킷 헤더의 웹 브라우저 정보(User-Agent)를 체크하기 때문에,
71 | 웹 스크레이핑을 하려면 requests 라이브러리를 이용해 웹 브라우저 정보를 보내야 합니다.
72 | 변경된 코드는 아래와 같으며 DBUpdaterEx.py로 깃헙에 올려두었습니다.
73 |
74 | 
75 |
76 | http://httpbin.org/user-agent 사이트에 접속하시면
77 | 현재 본인이 사용하는 웹 브라우저에 대한 정보를 확인할 수 있습니다.
78 | 샘플 코드의 "Mozilla/5.0"를 실제로 본인이 사용하는 웹 브라우저 정보로 변경하면
79 | 네이버 금융 페이지에서 차단될 가능성을 조금 더 줄일 수 있습니다.
80 |
--------------------------------------------------------------------------------