CREON Plus

[파이썬] 선물 분 차트 그리기(matplotlib 이용)

상품종류
선물옵션
언어종류
파이썬
작성일
2018/02/19
조회수
13052

선물 분 차트를 조회하고 이를 차트로 그리는 간단한 예제 입니다.

※ 주의사항: 본 예제는 PLUS 활용을 돕기 위해 예제로만 제공됩니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
import datetime
import sys
import ctypes
import time
 
import numpy as np
from PyQt5.QtWidgets import *
import win32com.client
import pandas as pd
import os
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.finance as matfin
import matplotlib.ticker as ticker
 
C_DT = 0    # 일자
C_TM = 1    # 시간
C_OP = 2    # 시가
C_HP = 3    # 고가
C_LP = 4    # 저가
C_CP = 5    # 종가
C_VL = 6    # 거래량
C_MA5 = 7    # 5일 이동평균
C_MA10 = 8    # 10일 이동평균
C_MA20 = 9    # 20일 이동평균
 
 
 
g_objCodeMgr = win32com.client.Dispatch('CpUtil.CpCodeMgr')
g_objCpStatus = win32com.client.Dispatch('CpUtil.CpCybos')
g_objCpTrade = win32com.client.Dispatch('CpTrade.CpTdUtil')
g_objFutureMgr = win32com.client.Dispatch("CpUtil.CpFutureCode")
def InitPlusCheck():
    # 프로세스가 관리자 권한으로 실행 여부
    if ctypes.windll.shell32.IsUserAnAdmin():
        print('정상: 관리자권한으로 실행된 프로세스입니다.')
    else:
        print('오류: 일반권한으로 실행됨. 관리자 권한으로 실행해 주세요')
        return False
 
    # 연결 여부 체크
    if (g_objCpStatus.IsConnect == 0):
        print("PLUS가 정상적으로 연결되지 않음. ")
        return False
 
    # 주문 관련 초기화
    if (g_objCpTrade.TradeInit(0!= 0):
        print("주문 초기화 실패")
        return False
 
    return True
 
 
 
 
class CpFutureChart:
    def __init__(self):
        self.objFutureChart = win32com.client.Dispatch("CpSysDib.FutOptChart")
 
 
    # 차트 요청 - 분간, 틱 차트
    def RequestMT(self, code, dwm, count, caller):
        # 연결 여부 체크
        bConnect = g_objCpStatus.IsConnect
        if (bConnect == 0):
            print("PLUS가 정상적으로 연결되지 않음. ")
            return False
 
        self.objFutureChart.SetInputValue(0, code)  # 종목코드
        self.objFutureChart.SetInputValue(1, ord('2'))  # 개수로 받기
        self.objFutureChart.SetInputValue(4, count)  # 조회 개수
        self.objFutureChart.SetInputValue(5, [0123458])  # 요청항목 - 날짜, 시간,시가,고가,저가,종가,거래량
        self.objFutureChart.SetInputValue(6, dwm)  # '차트 주기 - 분/틱
        self.objFutureChart.SetInputValue(71)  # 분틱차트 주기
        self.objFutureChart.SetInputValue(8, ord('0'))  # 갭보정
        self.objFutureChart.SetInputValue(9, ord('1'))  # 수정주가 사용
        self.objFutureChart.BlockRequest()
 
        rqStatus = self.objFutureChart.GetDibStatus()
        rqRet = self.objFutureChart.GetDibMsg1()
        print("통신상태", rqStatus, rqRet)
        if rqStatus != 0:
            exit()
 
        len = self.objFutureChart.GetHeaderValue(3)
 
        caller.chartData = {}
        caller.chartData[C_DT] = []
        caller.chartData[C_TM] = []
        caller.chartData[C_OP] = []
        caller.chartData[C_HP] = []
        caller.chartData[C_LP] = []
        caller.chartData[C_CP] = []
        caller.chartData[C_VL] = []
        caller.chartData[C_MA5] = []
        caller.chartData[C_MA10] = []
        caller.chartData[C_MA20] = []
 
        for i in range(len):
            caller.chartData[C_DT].$인서트$(0, self.objFutureChart.GetDataValue(0, i))
            caller.chartData[C_TM].$인서트$(0, self.objFutureChart.GetDataValue(1, i))
            caller.chartData[C_OP].$인서트$(0, self.objFutureChart.GetDataValue(2, i))
            caller.chartData[C_HP].$인서트$(0, self.objFutureChart.GetDataValue(3, i))
            caller.chartData[C_LP].$인서트$(0, self.objFutureChart.GetDataValue(4, i))
            caller.chartData[C_CP].$인서트$(0, self.objFutureChart.GetDataValue(5, i))
            caller.chartData[C_VL].$인서트$(0, self.objFutureChart.GetDataValue(6, i))
 
        #print(self.objFutureChart.Continue)
 
 
        return
 
 
 
class MyWindow(QWidget):
    def __init__(self):
        super().__init__()
 
        # plus 상태 체크
        if InitPlusCheck() == False:
            exit()
 
 
        # 기본 변수들
        self.chartData = {}
        self.code = ''
        self.isRq = False
 
        self.objChart = CpFutureChart()
 
        self.sizeControl()
        # 선물 종목 코드 추가
        for i in range(g_objFutureMgr.GetCount()):
            code = g_objFutureMgr.GetData(0, i)
            self.comboStg.addItem(code)
        self.comboStg.setCurrentIndex(0)
 
 
 
    def sizeControl(self) :
        # 윈도우 버튼 배치
        self.setWindowTitle("PLUS API TEST")
 
        self.setGeometry(50501200600)
        self.comboStg = QComboBox()
        #self.comboStg.move(20, nH)
        self.comboStg.currentIndexChanged.connect(self.comboChanged)
        #self.comboStg.resize(100, 30)
        self.label = QLabel('종목코드')
        #self.label.move(140, nH)
 
        # Figure 를 먼저 만들고 레이아웃에 들어 갈 sub axes 를 생성 한다.
        self.fig = plt.Figure()
        self.canvas = FigureCanvas(self.fig)
 
 
        # top layout
        topLayout = QHBoxLayout()
        topLayout.addWidget(self.comboStg)
        topLayout.addWidget(self.label)
        topLayout.addStretch(1)
        # topLayout.addSpacing(20)
 
        chartlayout = QVBoxLayout()
        chartlayout.addWidget(self.canvas)
 
 
        layout = QVBoxLayout()
        layout.addLayout(topLayout)
        layout.addLayout(chartlayout)
        layout.setStretchFactor(topLayout, 0)
        layout.setStretchFactor(chartlayout, 1)
 
        self.setLayout(layout)
 
    # 분차트 받기
    def RequestMi$엔차$t(self):
        if self.objChart.RequestMT(self.code, ord('m'), 100, self) == False:
            exit()
 
    def makeMovingAverage(self, maData, interval):
        #maData = []
        for i in range(0len(self.chartData[C_DT])) :
            if (i < interval) :
                maData.append(float('nan'))
                continue
            sum = 0
            for j in range (0, interval) :
                sum += self.chartData[C_CP][i - j]
            ma = sum / interval
            maData.append(ma)
        # print(maData)
 
 
    def drawMi$엔차$t(self):
        # 기존 거 지운다.
        self.fig.clf()
 
        # 211 - 2(행) * 1(열) 배치 1번째
        self.ax1 = self.fig.add_subplot(2,1,1)
        # 212 - 2(행) * 1(열) 배치 2번째
        self.ax2 = self.fig.add_subplot(2,1,2)
 
        ###############################################
        # 봉차트 그리기
        # self.ax1.xaxis.set_major_formatter(ticker.FixedFormatter(schartData[C_TM]))
        matfin.candlestick2_ohlc(self.ax1, self.chartData[C_OP], self.chartData[C_HP], self.chartData[C_LP], self.chartData[C_CP],
                                  width=0.8, colorup='r', colordown='b')
 
 
        ###############################################
        # x 축 인덱스 만들기 - 기본 순차 배열 추가
        x_tick_raw =  [i for i in range(len(self.chartData[C_DT]))]
        # x 축 인덱스 만들기 - 실제 화면에 표시될 텍스트 만들기
        x_tick_labels = []
 
        startDate = 0
        dateChanged = True
        for i in range(len(self.chartData[C_DT])) :
            # 날짜 변경 된 경우 날짜 정보 저장
            date = self.chartData[C_DT][i]
            if (date != startDate) :
                yy, mm = divmod(date, 10000)
                mm,dd = divmod(mm, 100)
                sDate = '%2d/%d '%(mm,dd)
                print(sDate)
                startDate = date
                dateChanged = True
 
            # 0 분 또는 30분 단위로 시간 표시
            hhh, mmm = divmod(self.chartData[C_TM][i], 100)
            stime = '%02d:%02d' % (hhh, mmm)
            if (mmm == 0 or mmm == 30):
                if dateChanged == True:
                    sDate += stime
                    x_tick_labels.append(sDate)
                    dateChanged = False
                else:
                    x_tick_labels.append(stime)
            else:
                x_tick_labels.append('')
 
 
        ###############################################
        # 이동 평균 그리기
        self.ax1.plot(x_tick_raw, self.chartData[C_MA5], label='ma5')
        self.ax1.plot(x_tick_raw, self.chartData[C_MA10], label='ma10')
        self.ax1.plot(x_tick_raw, self.chartData[C_MA20], label='ma20')
 
 
        ###############################################
        # 거래량 그리기
        self.ax2.bar(x_tick_raw, self.chartData[C_VL])
 
        ###############################################
        # x 축 가로 인덱스 지정
        self.ax1.set(xticks=x_tick_raw, xticklabels=x_tick_labels)
        self.ax2.set(xticks=x_tick_raw, xticklabels=x_tick_labels)
 
        self.ax1.grid()
        self.ax2.grid()
        plt.tight_layout()
        self.ax1.legend(loc='upper left')
 
        self.canvas.draw()
 
 
    def comboChanged(self):
        if self.isRq == True:
            return
        self.isRq = True
        self.code = self.comboStg.currentText()
        self.name = g_objFutureMgr.CodetoName(self.code)
        self.label.setText(self.name)
        self.RequestMi$엔차$t()
        self.makeMovingAverage(self.chartData[C_MA5], 5)
        self.makeMovingAverage(self.chartData[C_MA10], 10)
        self.makeMovingAverage(self.chartData[C_MA20], 20)
        self.drawMi$엔차$t()
        self.isRq = False
 
 
        #self.requestStgID(cur)
 
 
 
 
 
if __name__ == "__main__":
    app = QApplication($시스.$argv)
    myWindow = MyWindow()
    myWindow.show()
    app.$이엑스이씨$_()
 
 
cs
첨부파일
의견(2)
윤재만 13행 import matplotlib.finance 가 모듈설치가 않되는데 왜 그럴까요? (2021.06.23)
이상찬 matplotlib에 finance 모듈이 없다는데 대용할 수 있는 모듈이 없을까요? (2022.07.22)

첨부파일을 PDF뷰어로 확인 하실수 있으며, PDF뷰어 미설치 고객께서는 우측 다운로드를 통해 설치 후 이용 가능 합니다.

PDF뷰어 다운로드

인쇄