'''

관련 포스팅

무한매수법 변형 단순화하고 백테스팅으로 개선해서 연복리 30%넘어가게  MDD는 절반으로 줄여보기!
https://[Log in to view URL]


위 포스팅을 꼭 참고하세요!!!

'''


# 장이 열리는날이 아니면 프로그램 종료 #############################################################
import exchange_calendars as ecals
import datetime as dt
from Util_discord_message import send_message

XKRX = ecals.get_calendar("XKRX")  ### 이거 미국코드로 바꿔라 
ismarketopen = XKRX.is_session(dt.date.today().strftime("%Y-%m-%d"))  # 오늘은 개장일인지 확인

if ismarketopen == False:  # 장 닫혔으면 종료한다.
    exit(0)
else:  # 장 열려으면 시작한다.
    send_message(f'[전략명 : 20일 고가, 10일 저가 전략] 시작합니다')
#############################################################################################
#############################################################################################






import KIS_Common as Common
import KIS_API_Helper_US as KisUS
import json
import pprint
import line_alert

Common.SetChangeMode("VIRTUAL")



BOT_NAME = Common.GetNowDist() + "_InfinityUpgradeBot"

#투자할 종목!
TargetStockList = ['TQQQ','SOXL','YINN']




#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$#
############# 해당 전략으로 매수한 종목 데이터 리스트 ####################
InfinityUpgradeDataList = list()
#파일 경로입니다.
bot_file_path = "UsStock_" + BOT_NAME + ".json"

try:
    #이 부분이 파일을 읽어서 리스트에 넣어주는 로직입니다. 
    with open(bot_file_path, 'r') as json_file:
        InfinityUpgradeDataList = json.load(json_file)

except Exception as e:
    print("Exception by First")
################################################################
#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$#
#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$#


#계좌 잔고를 가지고 온다!
Balance = KisUS.GetBalance()



print("--------------내 보유 잔고---------------------")

pprint.pprint(Balance)

print("--------------------------------------------")
#총 평가금액에서 해당 봇에게 할당할 총 금액비율 1.0 = 100%  0.5 = 50%
InvestRate = 0.4

#기준이 되는 내 총 평가금액에서 투자비중을 곱해서 나온 포트폴리오에 할당된 돈!!
TotalMoney = float(Balance['TotalMoney']) * InvestRate

#각 종목당 투자할 금액! 리스트의 종목 개수로 나눈다!
StockMoney = TotalMoney / len(TargetStockList)
print("TotalMoney:", str(format(round(TotalMoney), ',')))
print("StockMoney:", str(format(round(StockMoney), ',')))



print("--------------내 보유 주식---------------------")
#그리고 현재 이 계좌에서 보유한 주식 리스트를 가지고 옵니다!
MyStockList = KisUS.GetMyStockList()
pprint.pprint(MyStockList)
print("--------------------------------------------")



while True:

    try:
        ### 이거 미국 시간으로 바꿔야 한다. 
        t_now = dt.datetime.now()
        t_0900 = t_now.replace(hour=9, minute=0, second=0, microsecond=0)
        t_1500 = t_now.replace(hour=15, minute=0, second=0, microsecond=0)
        t_1519 = t_now.replace(hour=15, minute=19, second=0, microsecond=0)
        t_1520 = t_now.replace(hour=15, minute=20, second=0, microsecond=0)
        t_1530 = t_now.replace(hour=15, minute=30, second=0, microsecond=0)

        if t_0900 < t_now < t_1500 : 
            time.sleep(60)

        if t_1500 < t_now < t_1600 : 
            #마켓이 열렸는지 여부~!
            IsMarketOpen = KisUS.IsMarketOpen()
            
            #장이 열렸을 때!
            if IsMarketOpen == True:
            
            
                #투자할 종목을 순회한다!
                for stock_code in TargetStockList:
            
                    #주식(ETF) 정보~
                    stock_name = ""
                    stock_amt = 0 #수량
                    stock_avg_price = 0 #평단
                    stock_eval_totalmoney = 0 #총평가금액!
                    stock_revenue_rate = 0 #종목 수익률
                    stock_revenue_money = 0 #종목 수익금
            
            
                    #매수된 상태라면 정보를 넣어준다!!!
                    for my_stock in MyStockList:
                        if my_stock['StockCode'] == stock_code:
                            stock_name = my_stock['StockName']
                            stock_amt = int(my_stock['StockAmt'])
                            stock_avg_price = float(my_stock['StockAvgPrice'])
                            stock_eval_totalmoney = float(my_stock['StockNowMoney'])
                            stock_revenue_rate = float(my_stock['StockRevenueRate'])
                            stock_revenue_money = float(my_stock['StockRevenueMoney'])
            
                            break
                            
            
                    #현재가
                    CurrentPrice = KisUS.GetCurrentPrice(stock_code)
            
                        
                    #종목 데이터
                    PickStockInfo = None
            
                    #저장된 종목 데이터를 찾는다
                    for StockInfo in InfinityUpgradeDataList:
                        if StockInfo['StockCode'] == stock_code:
                            PickStockInfo = StockInfo
                            break
            
                    #PickStockInfo 이게 없다면 매수되지 않은 처음 상태이거나 이전에 손으로 매수한 종목인데 해당 봇으로 돌리고자 할 때!
                    if PickStockInfo == None:
                        #잔고가 없다 즉 처음이다!!!
                        if stock_amt == 0:
            
                            InfinityDataDict = dict()
                            
                            InfinityDataDict['StockCode'] = stock_code #종목 코드
                            InfinityDataDict['MaxRound'] = 40 #맥스 회차!
                            InfinityDataDict['Round'] = 0    #현재 회차
                            InfinityDataDict['IsReady'] = 'Y' #하루에 한번 체크하고 매수등의 처리를 하기 위한 플래그
            
                            InfinityUpgradeDataList.append(InfinityDataDict) #데이터를 추가 한다!
            
            
                            msg = stock_code + " 개선무한매수봇 첫 시작!!!!"
                            print(msg) 
                            line_alert.SendMessage(msg) 
                            
                        #데이터가 없는데 잔고가 있다? 이미 이 봇으로 트레이딩 하기전에 매수된 종목!
                        else:
                            print("Exist")
            
                            InfinityDataDict = dict()
                            
                            InfinityDataDict['StockCode'] = stock_code #종목 코드
                            InfinityDataDict['MaxRound'] = 40 #맥스 회차!
                            
                            #분할된 투자금!
                            StMoney = StockMoney / InfinityDataDict['MaxRound']
                            InfinityDataDict['Round'] = int(stock_eval_totalmoney / StMoney)    #현재 회차 - 매수된 금액을 분할된 단위 금액으로 나누면 회차가 나온다!
                            InfinityDataDict['IsReady'] = 'Y' #하루에 한번 체크하고 매수등의 처리를 하기 위한 플래그
            
            
                            InfinityUpgradeDataList.append(InfinityDataDict) #데이터를 추가 한다!
            
            
                            msg = stock_code + " 기존에 매수한 종목을 개선무한매수봇으로 변경해서 트레이딩 첫 시작!!!! " + str(InfinityDataDict['Round']) + "회차로 세팅 완료!"
                            print(msg) 
                            line_alert.SendMessage(msg) 
            
                        #파일에 저장
                        with open(bot_file_path, 'w') as outfile:
                            json.dump(InfinityUpgradeDataList, outfile)
                            
            
                    #이제 데이터(InfinityUpgradeDataList)는 확실히 있을 테니 본격적으로 트레이딩을 합니다!
                    for StockInfo in InfinityUpgradeDataList:
            
                        if StockInfo['StockCode'] == stock_code:
                            
            
                            #매수는 장이 열렸을 때 1번만 해야 되니깐! 안의 로직을 다 수행하면 N으로 바꿔준다! 
                            if StockInfo['IsReady'] == 'Y' :
            
            
                                #캔들 데이터를 읽는다
                                df = Common.GetOhlcv("US",stock_code, 1000)
            
                                #5일 이평선
                                Ma5_before2 = Common.GetMA(df,5,-3)
                                Ma5_before = Common.GetMA(df,5,-2)
                                Ma5 = Common.GetMA(df,5,-1)
            
                                print("MA5 ", Ma5_before, "-> ",Ma5)
            
                                #200일 이평선
                                Ma200_before2 = Common.GetMA(df,200,-3)
                                Ma200_before = Common.GetMA(df,200,-2)
                                Ma200 = Common.GetMA(df,200,-1)
            
                                print("MA200 ",Ma200)
            
                                
                                #RSI14
                                Rsi14= Common.GetRSI(df,14,-2)
                                
                                #107일 이평선
                                Ma107_before = Common.GetMA(df,107,-2)
                                
                                Ma100_before = Common.GetMA(df,100,-2)
                                Ma60_before = Common.GetMA(df,60,-2)
                                Ma20_before = Common.GetMA(df,20,-2)
                                
                                #3일 이평선
                                Ma3_before2 = Common.GetMA(df,3,-3)
                                Ma3_before = Common.GetMA(df,3,-2)
                                
                            
                                
                                
            
            
            
            
            
                                #1회차 이상 매수된 상황이라면 익절 조건을 체크해서 익절 처리 해야 한다!
                                if StockInfo['Round'] > 0 :
                                    
            
            
                                    #목표 수익률을 구한다! 
                                    TargetRate = 10.0  / 100.0
            
                                    FinalRate = TargetRate 
            
                                    #수익화할 가격을 구한다!
                                    RevenuePrice = stock_avg_price * (1.0 + FinalRate) 
                                    
                                    if CurrentPrice >= RevenuePrice or StockInfo['Round'] >= StockInfo['MaxRound']:
            
                                        #목표한 수익가격보다 현재가가 높다면 익절처리할 순간이다!
                                        if CurrentPrice >= RevenuePrice:
                                            
                    
                                            #현재가보다 아래에 매도 주문을 넣음으로써 시장가로 매도효과!
                                            pprint.pprint(KisUS.MakeSellLimitOrder(stock_code,stock_amt,CurrentPrice*0.9))
            
            
                                            msg = stock_code + " 개선무한매수봇 모두 팔아서 수익확정!!!!  [" + str(stock_revenue_money) + "] 수익 조으다! (현재 [" + str(StockInfo['Round']) + "] 라운드까지 진행되었고 모든 수량 매도 처리! )"
                                            print(msg) 
                                            line_alert.SendMessage(msg) 
            
                                            #전량 매도 모두 초기화! 
                                            StockInfo['Round'] = 0
            
            
                                            #파일에 저장
                                            with open(bot_file_path, 'w') as outfile:
                                                json.dump(InfinityUpgradeDataList, outfile)
                                                
                                                
                                        else:
                                            
                                            
                                            if StockInfo['Round'] >= StockInfo['MaxRound']: #쿼터 손절 들어간다!
                                                
                                                StockInfo['Round'] -= int(StockInfo['Round']/4.0)
                                                CutAmt = int(stock_amt / 4.0)
            
                                                pprint.pprint(KisUS.MakeSellLimitOrder(stock_code,CutAmt,CurrentPrice*0.9))
            
            
                                                msg = stock_code + " 개선무한매수봇 쿼터 손절!!!!  [" + str(stock_revenue_money/4.0) + "] 손익 확정! (현재 [" + str(StockInfo['Round']) + "] 라운드로 셋!)"
                                                print(msg) 
                                                line_alert.SendMessage(msg) 
            
            
                                                #파일에 저장
                                                with open(bot_file_path, 'w') as outfile:
                                                    json.dump(InfinityUpgradeDataList, outfile)
                                                    
                                                    
                                    else:
                                        
            
            
                                        if StockInfo['Round'] < StockInfo['MaxRound']:
                                            
                                            #개선본을 사용한다면 이 부분 주석처리 해야 해요!
                                            IsBuyGo = False
                                            
                                            ##########################################################################################
                                            ##########################################################################################
                                            ############### 블로그 내용 수정 예정이지만 매수는 100일선 아래에서 3일선이 증가될때로 변경 되었습니다 ################
                                            ##########################################################################################
                                            ##########################################################################################
                                
                                            if Ma100_before > df['close'][-2]: #어제 종가가 100일선보다 작은 하락장!
            
                                                if Ma3_before2 < Ma3_before: #전일까지 3일선이 증가했다면 그때만 매수!!
                                                    IsBuyGo = True
            
                                            else: #200일선 위에 있는 상승장엔 기존 처럼 매일 매수!
                                                
                                                IsBuyGo = True
                                            #여기까지 주석처리요!!!!!!!!
                                                            
            
                                            ############# GMA 개선본!! 시작 #############
                                            ''' #개선본 사용시 위 부분은 주석처리!!!
                                            IsBuyGo = False
                                            if Ma107_before > df['close'][-2]: #현재가가 107일선보다 작은 하락장!
            
                                                if Ma3_before2 < Ma3_before: #전일까지 3일선이 증가했다면 그때만 매수!!
                                                    IsBuyGo = True
            
                                            else: #107일선 위에 있는 상승장엔 기존 처럼 매일 매수!
                                                
                                                IsBuyGo = True
                                            '''
                                            ############# GMA 개선본!! 끝 #############
                                
                                
                                            ############# GMA 개선본!! 시작 #############
                                            '''
                                            if Rsi14 >= 80: # 개선된 점 GMA #RSI 80이상의 과매도 구간에선 회차 매수 안함!!
                                                IsBuyGo = False
            
                                            '''
                                            ############# GMA 개선본!! 끝 #############
                                
                                
                                            #200일선 위에 있다가 아래로 종가가 떨어지면...
                                            if (Ma200_before2 < df['close'][-3] and Ma200_before > df['close'][-2]) :
                                            
            
                                                #현재가보다 아래에 매도 주문을 넣음으로써 시장가로 매도효과!
                                                pprint.pprint(KisUS.MakeSellLimitOrder(stock_code,stock_amt,CurrentPrice*0.9))
            
            
                                                msg = stock_code + " 개선무한매수봇 하락장 진입!!!!!  [" + str(stock_revenue_money) + "] 손익 확정!! (현재 [" + str(StockInfo['Round']) + "] 라운드까지 진행되었고 모든 수량 매도 처리! )"
                                                print(msg) 
                                                line_alert.SendMessage(msg) 
            
                                                #전량 매도 모두 초기화! 
                                                StockInfo['Round'] = 0
            
            
                                                #파일에 저장
                                                with open(bot_file_path, 'w') as outfile:
                                                    json.dump(InfinityUpgradeDataList, outfile)
                                                    
                                                IsBuyGo = False
                                                    
                                
            
                                            #한 회차 매수 한다!!
                                            if IsBuyGo == True:
            
                                                StockInfo['Round'] += 1 #라운드 증가!
            
                                
                                                #분할된 투자금!
                                                StMoney = StockMoney / StockInfo['MaxRound']
            
            
                                                BuyAmt = int(StMoney / CurrentPrice)
                                                
                                                #1주보다 적다면 투자금이나 투자비중이 작은 상황인데 일단 1주는 매수하게끔 처리 하자!
                                                if BuyAmt < 1:
                                                    BuyAmt = 1
            
                                                #시장가 주문을 넣는다!
                                                #현재가보다 위에 매수 주문을 넣음으로써 시장가로 매수!
                                                pprint.pprint(KisUS.MakeBuyLimitOrder(stock_code,BuyAmt,CurrentPrice*1.1))
            
            
                                                msg = stock_code + " 개선무한매수봇 " + str(StockInfo['Round']) + "회차 매수 완료!"
                                                print(msg) 
                                                line_alert.SendMessage(msg) 
            
                 
                                
                                
                                if StockInfo['Round'] == 0 and Ma5_before < df['close'][-2] : #전일 종가가 5일선 위에 있을 때만 
                                    
                                    if Ma200_before > df['close'][-2]: #200일선 아래에 있을 땐 40분할
                                        StockInfo['MaxRound'] = 40
                                        
                                    else: # 200일선 위에 있을 땐 30분할
                                        StockInfo['MaxRound'] = 30 
                                        
                                        ############# GMA 개선본!! 시작 #############
                                        '''
                                        StockInfo['MaxRound'] = 55
            
                                        
                                        if Ma100_before <= df['close'][-2]:
                                            StockInfo['MaxRound'] -= 15
            
            
                                        if Ma60_before <= df['close'][-2]:
                                            StockInfo['MaxRound'] -= 8
            
            
                                        if Ma20_before <= df['close'][-2]:
                                            StockInfo['MaxRound'] -= 7     
                                        '''    
                                        ############# GMA 개선본!! 끝 #############
                            
                                    
                                    StockInfo['Round'] += 1 #라운드 증가!
            
                    
                                    #분할된 투자금!
                                    StMoney = StockMoney / StockInfo['MaxRound']
            
            
                                    BuyAmt = int(StMoney / CurrentPrice)
                                    
                                    #1주보다 적다면 투자금이나 투자비중이 작은 상황인데 일단 1주는 매수하게끔 처리 하자!
                                    if BuyAmt < 1:
                                        BuyAmt = 1
            
                                    #시장가 주문을 넣는다!
                                    #현재가보다 위에 매수 주문을 넣음으로써 시장가로 매수!
                                    pprint.pprint(KisUS.MakeBuyLimitOrder(stock_code,BuyAmt,CurrentPrice*1.1))
            
            
                                    msg = stock_code + " 개선무한매수봇 " + str(StockInfo['Round']) + "회차 매수 완료!"
                                    print(msg) 
                                    line_alert.SendMessage(msg) 
                                            
                                            
                                            
                                        
                                #위 로직 완료하면 N으로 바꿔서 오늘 매수는 안되게 처리!
                                StockInfo['IsReady'] = 'N' 
            
                                #파일에 저장
                                with open(bot_file_path, 'w') as outfile:
                                    json.dump(InfinityUpgradeDataList, outfile) 
                                    
                            break
            
            # 장이 닫혔다면
            else:
            
                    
                #장이 끝나고 다음날 다시 매수시도 할수 있게 Y로 바꿔줍니당!
                for StockInfo in InfinityUpgradeDataList:
                    StockInfo['IsReady'] = 'Y'
            
            
                #파일에 저장
                with open(bot_file_path, 'w') as outfile:
                    json.dump(InfinityUpgradeDataList, outfile)
                    
                    
            pprint.pprint(InfinityUpgradeDataList)    
    







    
    # maxretry
    except requests.packages.urllib3.exceptions.MaxRetryError:
        send_message(f'Max Retry Error 60초 대기 후 재실행')
        time.sleep(60)

    except requests.packages.urllib3.exceptions.ConnectionError:
        send_message(f'Connection 에러발생 60초 대기 후 재실행')
        time.sleep(60)

    except requests.exceptions.ConnectionError:
        send_message(f'Connection 에러 2번째 발생 60초 대기 후 재실행')
        time.sleep(60)

    # 최상위 에러는 마지막에 놔둬야한다. 그리고 위 에러말고는 종료하게 만든다.
    except Exception as ex:
        send_message(f'Main 오류발생 :{ex}')
        exit(0)

    except Exception as e:
        send_message(f"[오류 발생] : {e}")
        exit(0)









Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: