From e85274bdc6db2e94e9bf464ad910de0ae8c67c08 Mon Sep 17 00:00:00 2001 From: dsyoon Date: Mon, 6 Mar 2023 00:21:19 +0900 Subject: [PATCH] init --- HTS_stocks.py | 122 ++++++++++++++++++++++++---------------- resources/BuyCount.xlsx | Bin 0 -> 18458 bytes 2 files changed, 73 insertions(+), 49 deletions(-) create mode 100644 resources/BuyCount.xlsx diff --git a/HTS_stocks.py b/HTS_stocks.py index a63a6cc..12609e7 100644 --- a/HTS_stocks.py +++ b/HTS_stocks.py @@ -165,35 +165,65 @@ class HTS_Stocks (HTS): return slow_k, p_slow_k, slow_k_week, p_slow_k_week, slow_k_month, p_slow_k_month - def getMaxPrice(self, code, valid_company): - max_price = 100000 - if code in valid_company: - if 0 < valid_company[code] <= 250: - max_price = 200000 - elif 250 < valid_company[code] <= 500: - max_price = 150000 - elif 500 < valid_company[code] <= 1000: - max_price = 100000 - elif 1000 < valid_company[code] <= 1500: - max_price = 50000 + def getBuyCount(self, stock_code, valid_company, bs_buy_price, slow_k_kospi, p_slow_k_kospi, slow_k_week_kospi, p_slow_k_week_kospi, slow_k_month_kospi, p_slow_k_month_kospi): + + base_price = 5000 + if stock_code in valid_company: + if 0 < valid_company[stock_code] <= 250: + base_price = 20000 + elif 250 < valid_company[stock_code] <= 500: + base_price = 10000 + elif 500 < valid_company[stock_code] <= 1000: + base_price = 5000 + elif 1000 < valid_company[stock_code] <= 1500: + base_price = 2000 else: - max_price = 100000 - return max_price + base_price = 1000 + + # kospi 상태 파악 + type_kospi = {'day':1, 'week':1, 'month':1} + if slow_k_kospi < p_slow_k_kospi: + if slow_k_kospi < 20: type_kospi['day'] = 4 + if 20 < slow_k_kospi < 30: type_kospi['day'] = 3 + if 30 < slow_k_kospi < 40: type_kospi['day'] = 2 + if slow_k_week_kospi < p_slow_k_week_kospi: + if slow_k_week_kospi < 20: type_kospi['week'] = 4 + if 20 < slow_k_week_kospi < 30: type_kospi['week'] = 3 + if 30 < slow_k_week_kospi < 40: type_kospi['week'] = 2 + if slow_k_month_kospi < p_slow_k_month_kospi: + if slow_k_month_kospi < 20: type_kospi['month'] = 4 + if 20 < slow_k_month_kospi < 30: type_kospi['month'] = 3 + if 30 < slow_k_month_kospi < 40: type_kospi['month'] = 2 + + type_stock = {'day':1, 'week':1, 'month':1} + slow_k, p_slow_k, slow_k_week, p_slow_k_week, slow_k_month, p_slow_k_month = self.getSlowK(stock_code) + if slow_k < p_slow_k: + if slow_k < 20: type_stock['day'] = 4 + if 20 < slow_k < 30: type_stock['day'] = 3 + if 30 < slow_k < 40: type_stock['day'] = 2 + if slow_k_week < p_slow_k_week: + if slow_k_week < 20: type_stock['week'] = 4 + if 20 < slow_k_week < 30: type_stock['week'] = 3 + if 30 < slow_k_week < 40: type_stock['week'] = 2 + if slow_k_month < p_slow_k_month: + if slow_k_month < 20: type_stock['month'] = 4 + if 20 < slow_k_month < 30: type_stock['month'] = 3 + if 30 < slow_k_month < 40: type_stock['month'] = 2 + + if (type_kospi['day'] == 1 and type_kospi['week'] == 1 and type_kospi['month'] == 1 and + type_stock['day'] == 1 and type_stock['week'] == 1 and type_stock['month'] == 1): + return 0 + + max_price = math.log(type_kospi['day']*type_kospi['week']*type_kospi['month']*type_stock['day']*type_stock['week']*type_stock['month'], 1.3) * base_price + buy_count = int(math.ceil(max_price / bs_buy_price)) + + return buy_count def buyRealTime(self, today, n = 200): - VALID_DAY = True print ("START...") THIS_TIME = datetime.now() slow_k_kospi, p_slow_k_kospi, slow_k_week_kospi, p_slow_k_week_kospi, slow_k_month_kospi, p_slow_k_month_kospi = self.getSlowK("^KS11") - if (50 < slow_k_kospi or 50 < p_slow_k_kospi or (slow_k_kospi < 50 and p_slow_k_kospi < 50 and slow_k_kospi < p_slow_k_kospi)): - print("#1 매수/매도 일이 아닙니다.", slow_k_kospi, p_slow_k_kospi) - VALID_DAY = False - if ((0 < slow_k_week_kospi < 50 and 0 < slow_k_month_kospi < 50) and - not ((20 < slow_k_week_kospi and slow_k_week_kospi < p_slow_k_week_kospi) or (20 < slow_k_month_kospi and slow_k_month_kospi < p_slow_k_month_kospi))): - print("#2 매수/매도 일이 아닙니다.", p_slow_k_week_kospi, slow_k_week_kospi, p_slow_k_month_kospi, slow_k_month_kospi) - VALID_DAY = False - all_stocks, valid_company = self.getCompanyInfo() while datetime.strptime(today + " 070000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 153100", '%Y%m%d %H%M%S'): @@ -232,41 +262,35 @@ class HTS_Stocks (HTS): data.drop(data.index[:len(data) - self.analyzed_day], inplace=True) bsLine, data = self.buySellChecker.checkTransactionWithEnvelope(data, stock_code, self.analyzed_day, isRealTime=False) - slow_k, p_slow_k, slow_k_week, p_slow_k_week, slow_k_month, p_slow_k_month = self.getSlowK(stock_code) - if ((0 < slow_k_week < 30 and 0 < slow_k_month < 30) and - not ((20 < slow_k_week and slow_k_week < p_slow_k_week) or (20 < slow_k_month and slow_k_month < p_slow_k_month))): - # 미체결 기록을 가져와서 10분 이상 된 매수 주문을 취소 한다. - ORDER_LIST = self.requestOrderList() - orderListToCancel = self.orderChecker.cancel(today, "A" + stock_code, ORDER_LIST, mins=10) - if len(orderListToCancel) > 0: - self.cancelOrderList(orderListToCancel) + # 미체결 기록을 가져와서 10분 이상 된 매수 주문을 취소 한다. + ORDER_LIST = self.requestOrderList() + orderListToCancel = self.orderChecker.cancel(today, "A" + stock_code, ORDER_LIST, mins=10) + if len(orderListToCancel) > 0: + self.cancelOrderList(orderListToCancel) - # 다음 조건이면 매수한다. - if len(data) > 10 and max(bsLine['buy'][len(bsLine['buy']) - 1:]) > 1000: + # 다음 조건이면 매수한다. + if len(data) > 10 and max(bsLine['buy'][len(bsLine['buy']) - 1:]) > 1000: - if not self.orderChecker.exist(today, "A" + stock_code, hours=9): + if not self.orderChecker.exist(today, "A" + stock_code, hours=9): - last_index = len(bsLine['buy'])-1 - if 0 < bsLine['buy'][last_index] < 200000: + last_index = len(bsLine['buy'])-1 + if 0 < bsLine['buy'][last_index] < 200000: - bs_buy_price = bsLine['buy'][last_index] - bs_buy_weight = bsLine['buy_weight'][last_index] - MAX_BUY_PRIFE = self.getMaxPrice(stock_code, valid_company) - buy_count = int(math.ceil(MAX_BUY_PRIFE / bs_buy_price)) - if MAX_BUY_PRIFE <= bs_buy_price < 2 * MAX_BUY_PRIFE: - buy_count = int(2 * MAX_BUY_PRIFE / bs_buy_price) + bs_buy_price = bsLine['buy'][last_index] + bs_buy_weight = bsLine['buy_weight'][last_index] + buy_count = self.getBuyCount(stock_code, valid_company, bs_buy_price, slow_k_kospi, p_slow_k_kospi, slow_k_week_kospi, p_slow_k_week_kospi, slow_k_month_kospi, p_slow_k_month_kospi) - if buy_count > 0: - # 매수를 주문한다. - orderNum = self.requestOrder(OrderType.buy, stock_code, buy_count, bs_buy_price) - self.orderChecker.buy(today, "A" + stock_code, buy_count, bs_buy_price, orderNum) + if buy_count > 0: + # 매수를 주문한다. + orderNum = self.requestOrder(OrderType.buy, stock_code, buy_count, bs_buy_price) + self.orderChecker.buy(today, "A" + stock_code, buy_count, bs_buy_price, orderNum) - # slackbot에 메시지를 보냄 - self.slackBot.post_to_slack(stock_code, stock_name, "BUY", bsLine['buy'][len(bsLine['buy']) - 1], buy_count) + # slackbot에 메시지를 보냄 + self.slackBot.post_to_slack(stock_code, stock_name, "BUY", bsLine['buy'][len(bsLine['buy']) - 1], buy_count) - # 로그 출력 - print("BUY", THIS_TIME.strftime('%Y%m%d %H%M%S'), orderNum, stock_code, stock_name, bs_buy_price, buy_count) + # 로그 출력 + print("BUY", THIS_TIME.strftime('%Y%m%d %H%M%S'), orderNum, stock_code, stock_name, bs_buy_price, buy_count) # 다음 조건이면 매도한다. if len(data) > 10 and max(bsLine['sell'][len(bsLine['sell']) - 1:]) > 1000: diff --git a/resources/BuyCount.xlsx b/resources/BuyCount.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..62818a4eb53c4a1737b58c124ab550acdf68eaf1 GIT binary patch literal 18458 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

@ZvJplJS1=A2 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

RLSvCJlLh|t{Iq4U z@#!fHU24lvE=b^{H(@kTp@|t6>j-Y~0{vKwjkqJrMtmn@{WA=A*bmDoy=pt<$lCC} zWY5HYGoTQg8FIYyGe(ygVW!vtB`W0X2K6)PbSx&p*;E^SIu`rr-l8FIk_RN^r%O z5hNC>B^Jy%ip;TgNpQ`>kt374p^sFLTQz2ymZrK(FrLNHCp43B4=R#Fo~qBj#T+J^t8;*XTZ!N(hp#;?z<(iF9}rHB$rocX6M??5bB>NDuz|2u zp?Sa2DHStJws80Tx|=u4(VIXp^utB9!;d7m25y?dB|^*wcrEmI89t^c1>r8kB{b>6 zJKQ-naK_Z3lAE;eW48whA8JqiPU6b&37ZbP0*ZO`bZ;iSE)~o8Oh1`;n`oBi$jNdg zx3vi`Rnh@P7)z9Pr;a9GZ8dGi?2#&_7k0DBEpBn6A&s97FpS6b?6H?}^AdcKz#aHayihR4Vd)$H9OhO( z8S`g#{rt(3A;-h1j$^0G%pVT2wBVaRD3R~u`dcW_v3I$A`Gx|vXe3FHZk5{*AY@<- z9n$yE1^Ut>HTByZTwKo$d$qLWH?kYpNAINGMGt zP1nqRXN`&=STRn+-uy)_TYYZ|6rjUp#s1>T>qsLYz~u|U#BGF7*}?&izoumJvKh{< zVE!1&?tvK4YIRb*`M==idh6^ZO{bTu3?<5o9kKB=yS3)=W`*Hb-|A2BUx+F@X*yWT4t#bMZc%7ZOP27}QSECqKFJT)942cGfT#q$bla+HF z$uEU4pf_N=JgP(k$*jI__smxN{vzDywXxNT5}8F#3` z{q0lKyJ}rGzrt5{&*4FpLQZIm+y)&woK(UKfg*~_5BK&@7gvi{x>w7OGy^eJe1Xar z>~$3vo@jP<4ExApST=;hHVhm|0&4Uj=SXLsgM2LE-Q*)pVtMwPakg&k^0$4Uoq2%G zXoT>2XVd5okJUX4ngGLjL(vq62*V933L+3|g7S!!vvr^vw!Y_7@T~SbN!PI3frmHe zknYBPO>9a`lxx`&B(?Tm9p-ksNxKXL*dWMW^nV7np{;}Q{~#Lz>EB=BF^bY)7OW4; zFi*k*pwt3mR-t*n!3;tK8=AHc>n@0#l9D-#kFDm-!-H6XEfiY|M;Rc=s+kh1+vj_E z-zi^7hQ9i?09Ra3Iaiu^LMS@I#;9S)9=8oZVf?&T;$I&}fG9sztJnG*7beCf4sw+H zvQjwFvY!DHJPJ|woJNml!yKaxzK^L^$GemzJ(vvmP5eVYdk|F)xzaIP^+V+_0F6-i z8A7dV62)^L5WmKTHzQu$M`cMLGq6lwgL2)ETsN1abUuRSa_J_|5cE^b`z8-JVzG$) zL)RWC)ek@7wDgu{EGQc}MkWM2N-YP-=C~_iGPrN8IltbhYIrgVE)YM`HL(ZDf%Ob| z(G)|Z`a0zXrM+F-b#myWYxv~A$z_sql41k*Wuqs#ZBYUOMTRLp7^dvx?CG*0)NfUP zgdHh)L4fwJ5M)$u7_ipzO&;A%uYu22 zJZ3x_@YL?W2WN}mm9vZEJ!YWSmAwYhvP*FD;@X+M5C4555GB*5?O}7*<;v}D?cs2x zl4sG5TL<;Z)|MGqI^8#a_b`5Vy>esh!~JkNf3`P%cyNAu>+a?0zIb#Pd3ER^R{8pgdgw|AyDc*M~g(QSs+G4?_QcdgR03EB-a{{huoi z!2Z&U|Bwd%_jdlC{QPH2$nd|~`R7#VzgPZyKIWg5>yds{{+H~`zqj!B1jRpF*oGts zK{Bx&|BYPDgJxyzj}>-u1y5|r`mrwkH1&{dz|>Qfh@saXaAR|p&$(d!N$+0i68>nAm&C) I^yjDl51{aFb^rhX literal 0 HcmV?d00001