한국투자증권 주식매매프로그램 만들기

파이썬 주식매매프로그램 만들기

미국 주식 프로그램 만들기(KIS Developers)/2. 필요한 함수 추가

16) 이동평균선 추가

토폴로지 2022. 10. 4. 23:24
import requests
import json
import yaml
import time
import websockets #pip install websockets
import asyncio
import pandas as pd #pip install pandas
from pandas import DataFrame

with open(r'config.yaml', encoding='UTF-8') as f:
    _cfg = yaml.load(f, Loader=yaml.FullLoader)
APP_KEY = _cfg['APP_KEY']
APP_SECRET = _cfg['APP_SECRET']
ACCESS_TOKEN = ""
CANO = _cfg['CANO']
ACNT_PRDT_CD = _cfg['ACNT_PRDT_CD']
ACTUAL_DOMAIN = _cfg['ACTUAL_DOMAIN']
WEB_SOCKET_DOMAIN = _cfg['WEB_SOCKET_DOMAIN']

# ACCESS TOKEN 발급
def get_access_token():
    url = 'oauth2/tokenP'
    request_url = f"{ACTUAL_DOMAIN}/{url}"
    headers = {
    }
    body = {
        "grant_type": "client_credentials",
        "appkey": APP_KEY,
        "appsecret": APP_SECRET,
    }
 
    res = requests.post(request_url, data=json.dumps(body), headers=headers)
    rescode = res.status_code
    if rescode == 200:
        ACCESS_TOKEN = res.json()["access_token"]
    else:
        print("Error Code : " + str(rescode) + " | " + res.text)
    
    return ACCESS_TOKEN
#한국계좌잔고 확인
def get_kor_balance():
    url = "uapi/domestic-stock/v1/trading/inquire-psbl-order"
    request_url = f"{ACTUAL_DOMAIN}/{url}"
    headers = {"Content-Type": "application/json",
               "authorization": f"Bearer {ACCESS_TOKEN}",
               "appKey": APP_KEY,
               "appSecret": APP_SECRET,
               "tr_id": "TTTC8908R",   #실전투자값: TTTC8908R
               "custtype": "P", #P: 개인
               }
    params = {
        "CANO": CANO, #계좌번호
        "ACNT_PRDT_CD": ACNT_PRDT_CD, #계좌번호 뒷자리
        "PDNO": "005930", # 종목 코드 005930은 삼성
        "ORD_UNPR": "65500", #1주당 가격
        "ORD_DVSN": "01", # 01: 시장가
        "CMA_EVLU_AMT_ICLD_YN": "Y", #CMA 평가금액포함여부: Y
        "OVRS_ICLD_YN": "Y" #해외포함여부: Y
    }
    res = requests.get(request_url, headers=headers, params=params)
    cash = res.json()['output']['ord_psbl_cash']
    #print(f"주문 가능 현금 잔고: {cash}원")
    return int(cash)
#미국 주야간 확인
def check_day_or_night():
    url = "uapi/overseas-stock/v1/trading/dayornight"
    request_url = f"{ACTUAL_DOMAIN}/{url}"
    headers = {"Content-Type": "application/json",
               "authorization": f"Bearer {ACCESS_TOKEN}",
               "appKey": APP_KEY,
               "appSecret": APP_SECRET,
               "tr_id": "JTTT3010R", 
               "custtype": "P", #P: 개인
               }
    params = {
    }
    res = requests.get(request_url, headers=headers, params=params)
    day_or_night = res.json()['output']['PSBL_YN']
    #미국: 23:30 ~ 06:00 (썸머타임 적용 시 22:30 ~ 05:00)
    return day_or_night
#해외주식 매수가능금액조회
def get_us_balance():
    #JTTT3007R : PSBL_YN(주야간 원장 구분) = 'Y' (야간용)
    #TTTS3007R : PSBL_YN(주야간 원장 구분) = 'N' (주간용)
    TR_ID = "JTTT3007R" if DAY_OR_NIGHT == 'Y' else "TTTS3007R"
    url = "uapi/overseas-stock/v1/trading/inquire-psamount"
    request_url = f"{ACTUAL_DOMAIN}/{url}"
    headers = {"Content-Type": "application/json",
               "authorization": f"Bearer {ACCESS_TOKEN}",
               "appKey": APP_KEY,
               "appSecret": APP_SECRET,
               "tr_id": TR_ID,   #실전투자값: TTTC8908R
               "custtype": "P", #P: 개인
               }
    params = {
        "CANO": CANO, #계좌번호
        "ACNT_PRDT_CD": ACNT_PRDT_CD, #계좌번호 뒷자리
        "OVRS_EXCG_CD": "NASD", #NASD : 나스닥 / NYSE : 뉴욕 / AMEX : 아멕스 SEHK : 홍콩 / SHAA : 중국상해 / SZAA : 중국심천 TKSE : 일본 / HASE : 하노이거래소 / VNSE : 호치민거래소
        "OVRS_ORD_UNPR": "30.0", #해외주문단가, 정수부분 23자리, 소수부분 8자리
        "ITEM_CD": "TQQQ", #종목코드
    }
    res = requests.post(request_url, headers=headers, params=params)
    cash = res.json()['output']['ovrs_ord_psbl_amt']
    #print(f"주문 가능 현금 잔고: {cash}$") 
    return cash
#국내주식주문(현금)
def buy_kor_stock(stock_code="005930", order_qty="1", order_price ="0", order_type="01"):
    url = "uapi/domestic-stock/v1/trading/order-cash"
    request_url = f"{ACTUAL_DOMAIN}/{url}"
    headers = {"Content-Type": "application/json",
               "authorization": f"Bearer {ACCESS_TOKEN}",
               "appKey": APP_KEY,
               "appSecret": APP_SECRET,
               "tr_id": "TTTC0802U",   #실전투자값: TTTC0802U
               "custtype": "P", #P: 개인
               }
    params = {
        "CANO": CANO, #계좌번호
        "ACNT_PRDT_CD": ACNT_PRDT_CD, #계좌번호 뒷자리
        "PDNO": stock_code, # 종목 코드 005930은 삼성
        "ORD_DVSN": order_type, #01 : 시장가 02 : 조건부지정가 03 : 최유리지정가 04 : 최우선지정가 05 : 장전 시간외 06 : 장후 시간외 07 : 시간외 단일가
        "ORD_QTY": order_qty,
        "ORD_UNPR": order_price, # 1주당 가격
        "CTAC_TLNO":"",
        "SLL_TYPE":"01",
        "ALGO_NO":""
    }
    res = requests.post(request_url, data=json.dumps(params), headers=headers)
    order_check = "주문 성공" if res.json()['rt_cd'] == "0" else "주문 실패"
    msg1 = res.json()['msg1']
    print(order_check + ": " + msg1)
    return res.json()['rt_cd'] # 주문성공 시 0 리턴
#국내주식주문(현금)
def sell_kor_stock(stock_code="005930", order_qty="1", order_price ="0", order_type="01"):
    url = "uapi/domestic-stock/v1/trading/order-cash"
    request_url = f"{ACTUAL_DOMAIN}/{url}"
    headers = {"Content-Type": "application/json",
               "authorization": f"Bearer {ACCESS_TOKEN}",
               "appKey": APP_KEY,
               "appSecret": APP_SECRET,
               "tr_id": "TTTC0801U",   #실전투자값: TTTC0802U
               "custtype": "P", #P: 개인
               }
    params = {
        "CANO": CANO, #계좌번호
        "ACNT_PRDT_CD": ACNT_PRDT_CD, #계좌번호 뒷자리
        "PDNO": stock_code, # 종목 코드 005930은 삼성
        "ORD_DVSN": order_type, #01 : 시장가 02 : 조건부지정가 03 : 최유리지정가 04 : 최우선지정가 05 : 장전 시간외 06 : 장후 시간외 07 : 시간외 단일가
        "ORD_QTY": order_qty,
        "ORD_UNPR": order_price, # 1주당 가격
        "CTAC_TLNO":"",
        "SLL_TYPE":"01",
        "ALGO_NO":""
    }
    res = requests.post(request_url, data=json.dumps(params), headers=headers)
    order_check = "주문 성공" if res.json()['rt_cd'] == "0" else "주문 실패"
    msg1 = res.json()['msg1']
    print(order_check + ": " + msg1)
    return res.json()['rt_cd'] # 주문성공 시 0 리턴
#해외주식주문(현금)
def buy_us_stock(stock_market="NASD", stock_code="TQQQ", order_qty="1", order_price ="0", order_type="00"):
    url = "uapi/overseas-stock/v1/trading/order"
    request_url = f"{ACTUAL_DOMAIN}/{url}"
    headers = {"Content-Type": "application/json",
               "authorization": f"Bearer {ACCESS_TOKEN}",
               "appKey": APP_KEY,
               "appSecret": APP_SECRET,
               "tr_id": "JTTT1002U",   #미국매수주문: JTTT1002U
               "custtype": "P", #P: 개인
               }
    params = {
        "CANO": CANO, #계좌번호
        "ACNT_PRDT_CD": ACNT_PRDT_CD, #계좌번호 뒷자리
        "OVRS_EXCG_CD": stock_market, #NASD : 나스닥 NYSE : 뉴욕 AMEX : 아멕스 SEHK : 홍콩 SHAA : 중국상해 SZAA : 중국심천 TKSE : 일본 HASE : 베트남 하노이 VNSE : 베트남 호치민
        "PDNO": stock_code, # 종목 코드
        "ORD_QTY": order_qty,
        "OVRS_ORD_UNPR": order_price, # 1주당 가격
        "ORD_SVR_DVSN_CD": "0",
        "ORD_DVSN": order_type, #00: 지정가 32: LOO(장 개시 지정가) 34: LOC(장마감지정가)   
    }
    res = requests.post(request_url, data=json.dumps(params), headers=headers)
    order_check = "주문 성공" if res.json()['rt_cd'] == "0" else "주문 실패"
    msg1 = res.json()['msg1']
    print(order_check + ": " + msg1)
    return res.json()['rt_cd'] # 주문성공 시 0 리턴
#해외주식주문(현금)
def sell_us_stock(stock_market="NASD", stock_code="TQQQ", order_qty="1", order_price ="0", order_type="00"):
    url = "uapi/overseas-stock/v1/trading/order"
    request_url = f"{ACTUAL_DOMAIN}/{url}"
    headers = {"Content-Type": "application/json",
               "authorization": f"Bearer {ACCESS_TOKEN}",
               "appKey": APP_KEY,
               "appSecret": APP_SECRET,
               "tr_id": "JTTT1006U",   #미국매도주문: JTTT1006U
               "custtype": "P", #P: 개인
               }
    params = {
        "CANO": CANO, #계좌번호
        "ACNT_PRDT_CD": ACNT_PRDT_CD, #계좌번호 뒷자리
        "OVRS_EXCG_CD": stock_market, #NASD : 나스닥 NYSE : 뉴욕 AMEX : 아멕스 SEHK : 홍콩 SHAA : 중국상해 SZAA : 중국심천 TKSE : 일본 HASE : 베트남 하노이 VNSE : 베트남 호치민
        "PDNO": stock_code, # 종목 코드
        "ORD_QTY": order_qty,
        "OVRS_ORD_UNPR": order_price, # 1주당 가격
        "ORD_SVR_DVSN_CD": "0",
        "ORD_DVSN": order_type, #00: 지정가 32: LOO(장 개시 지정가) 34: LOC(장마감지정가)   
    }
    res = requests.post(request_url, data=json.dumps(params), headers=headers)
    order_check = "주문 성공" if res.json()['rt_cd'] == "0" else "주문 실패"
    msg1 = res.json()['msg1']
    print(order_check + ": " + msg1)
    return res.json()['rt_cd'] # 주문성공 시 0 리턴
#국내주식기간별시세
def get_kor_stock_period_data(stock_code="005930", start_date="20220101", end_date="20220131", period="D"):
    url = "uapi/domestic-stock/v1/quotations/inquire-daily-itemchartprice"
    request_url = f"{ACTUAL_DOMAIN}/{url}"
    headers = {"Content-Type": "application/json",
               "authorization": f"Bearer {ACCESS_TOKEN}",
               "appKey": APP_KEY,
               "appSecret": APP_SECRET,
               "tr_id": "FHKST03010100",   
               "custtype": "P", #P: 개인
               }
    params = {
        "FID_COND_MRKT_DIV_CODE": "J", # J : 주식
        "FID_INPUT_ISCD": stock_code, #종목번호 (6자리)
        "FID_INPUT_DATE_1": start_date, # 조회 시작일자 (ex. 20220501)
        "FID_INPUT_DATE_2": end_date, # 조회 종료일자 (ex. 20220530)
        "FID_PERIOD_DIV_CODE": period, # D:일봉, W:주봉, M:월봉, Y:년봉
        "FID_ORG_ADJ_PRC": "1", # 0:수정주가 1:원주가
    }
    res = requests.get(request_url, headers=headers, params=params)
    print(res.json())
    return res.json()
#해외주식기간별시세
def get_us_stock_period_data(stock_market="NAS", stock_code="TQQQ", date="", period="0"):
    url = "uapi/overseas-price/v1/quotations/dailyprice"
    request_url = f"{ACTUAL_DOMAIN}/{url}"
    headers = {"Content-Type": "application/json",
               "authorization": f"Bearer {ACCESS_TOKEN}",
               "appKey": APP_KEY,
               "appSecret": APP_SECRET,
               "tr_id": "HHDFS76240000",
               "tr_cont": "",  
               "custtype": "P", #P: 개인
               }
    params = {
        "AUTH": "",
        "EXCD": stock_market,#HKS : 홍콩 NYS : 뉴욕 NAS : 나스닥 AMS : 아멕스 TSE : 도쿄 SHS : 상해 SZS : 심천 SHI : 상해지수 SZI : 심천지수 HSX : 호치민 HNX : 하노이
        "SYMB": stock_code, #종목코드 (ex. TSLA)
        "GUBN": period, #0 : 일 1 : 주 2 : 월
        "BYMD": date, # 조회 시작일자 (ex. 20220501)
        "MODP": "0", # # 0:원주가 1:수정주가
    }
    res = requests.get(request_url, headers=headers, params=params)
    #print(res.json())
    return res.json()
#국내주식실시간 체결가
async def get_kor_realtime_stock_price(stock_code = '005930'):
    # 웹 소켓에 접속.( 주석은 koreainvest test server for websocket)
    g_personalsecKey = ''
    custtype = 'P'  # customer type, 개인:'P' 법인 'B'
    tr_type = '1'
    tr_id = 'H0STCNT0'

    async with websockets.connect(WEB_SOCKET_DOMAIN, ping_interval=None) as websocket:
        senddata = '{"header":{"appkey":"' + APP_KEY + '","appsecret":"' + APP_SECRET + '","personalseckey":"' + g_personalsecKey + '","custtype":"' + custtype + '","tr_type":"' + tr_type + '","content-type":"utf-8"},"body":{"input":{"tr_id":"' + tr_id + '","tr_key":"' + stock_code + '"}}}'
        await websocket.send(senddata)
        time.sleep(1)

        # 데이터가 오기만 기다린다.
        while True:
            data = await websocket.recv()
            #print("Recev Command is :", data)
            if data[0] == '0':
                recv_str = data.split('|')
                stock_data = recv_str[3]
                stock_data_split = stock_data.split('^')
                stock_now_price = stock_data_split[2] #2 = 현재가 인덱스
                print(stock_now_price)
#해외주식실시간 체결가
async def get_us_realtime_stock_price(market_stock_code = 'DNASTQQQ'):
    # 웹 소켓에 접속.( 주석은 koreainvest test server for websocket)
    g_personalsecKey = ''
    custtype = 'P'  # customer type, 개인:'P' 법인 'B'
    tr_type = '1'
    tr_id = 'HDFSCNT0'

    async with websockets.connect(WEB_SOCKET_DOMAIN, ping_interval=None) as websocket:
        senddata = '{"header":{"appkey":"' + APP_KEY + '","appsecret":"' + APP_SECRET + '","personalseckey":"' + g_personalsecKey + '","custtype":"' + custtype + '","tr_type":"' + tr_type + '","content-type":"utf-8"},"body":{"input":{"tr_id":"' + tr_id + '","tr_key":"' + market_stock_code + '"}}}'
        await websocket.send(senddata)
        time.sleep(1)

        # 데이터가 오기만 기다린다.
        while True:
            data = await websocket.recv()
            #print("Recev Command is :", data)
            if data[0] == '0':               
                recv_str = data.split('|')
                stock_data = recv_str[3]
                stock_data_split = stock_data.split('^')
                stock_now_price = stock_data_split[11] #11 = 현재가 인덱스
                print(stock_now_price)
#해외주식기간별 시세 json을 데이터프레임으로 변환
def json_to_df_us_stock_data(json_data):
    stock_data = json_data['output2']

    df = pd.DataFrame(columns=['Open','Low','High','Close'])
    for i in stock_data:
        stock_day_data = [[i['open'],i['low'], i['high'],i['clos']]]
        stock_day_data_columns=['Open','High','Low','Close']
        stock_day_data_index= [i['xymd']]
        stock_day_df=DataFrame(data=stock_day_data,index=stock_day_data_index,columns=stock_day_data_columns)
        df=pd.concat([df,stock_day_df])   
    #print(df)
    df = df.sort_index(ascending=True)
    return df
#이동평균선 계산
def calc_SMA(data, period=20):
    return data.rolling(window=period).mean()
#일목균형표 계산
def calc_ICMK(data, period=26):
    period_high = data['High'].rolling(window=period).max()
    period_low = data['Low'].rolling(window=period).min()
    return (period_high + period_low) / 2

ACCESS_TOKEN = get_access_token()
DAY_OR_NIGHT = check_day_or_night()
#print(get_kor_balance())
#get_us_balance()
#buy_kor_stock("005930", "1", "56500", "00") # 1: 종목코드, 2: 주문수량, 3.주문가격 ,4: 주문방식(00은 지정가)
#sell_kor_stock("005930", "1", "56500", "00") # 1: 종목코드, 2: 주문수량, 3.주문가격 ,4: 주문방식(00은 지정가)
#buy_us_stock("NASD", "TQQQ", "1", "31.0", "00") # 1:거래소 2: 종목코드, 3: 주문수량, 4.주문가격 ,5: 주문방식(00은 지정가)
#sell_us_stock("NASD", "TQQQ", "1", "25.0", "00") # 1:거래소 2: 종목코드, 3: 주문수량, 4.주문가격 ,5: 주문방식(00은 지정가)
#get_kor_stock_period_data("005930", "20220101", "20220131", "D")
TQQQ_json = get_us_stock_period_data("NAS", "TQQQ", "", "0")
#asyncio.get_event_loop().run_until_complete(get_kor_realtime_stock_price())
#asyncio.get_event_loop().run_until_complete(get_us_realtime_stock_price("DNASTQQQ"))

TQQQ_df = json_to_df_us_stock_data(TQQQ_json)
TQQQ_df['SMA5'] = calc_SMA(TQQQ_df['Close'], 5) #이평선 5 추가
TQQQ_df['SMA10'] = calc_SMA(TQQQ_df['Close'], 10) #이평선 10 추가
TQQQ_df['SMA20'] = calc_SMA(TQQQ_df['Close'], 20) #이평선 20 추가
TQQQ_df['ICMK'] = calc_ICMK(TQQQ_df, 26) #일목균형표 26일선 추가
print(TQQQ_df)

5일선 10일선 20일선 지표 추가

반응형