def __init__(self):
        QMainWindow.__init__(self)

        # Application Configuration
        # UI
        self.setupUi(self)

        # Font(ko)
        self.set_ko_font()

        # Logger
        self.logger = TTlog(logger_name="TTRealCondi").logger

        # DB
        self.mongo = MongoClient()
        self.db = self.mongo.TopTrader

        # Slack
        self.slack = Slacker(config_manager.get_slack_token())

        # Kiwoom
        self.kw = Kiwoom()
        self.login()
        self.stock_info = self.kw.get_stock_basic_info()

        # app main
        self.main()
Ejemplo n.º 2
0
 def __init__(self):
     super().__init__()
     # self.setupUi(self)  # load app screen
     duration = sys.argv[1]
     self.logger = TTlog(logger_name="TT"+duration).logger
     self.mongo = MongoClient()
     self.tt_db = self.mongo.TopTrader
     self.slack = Slack(config_manager.get_slack_token())
     today = datetime.today()
     self.end_date = datetime(today.year, today.month, today.day, 16, 0, 0)
     self.kw = Kiwoom()
     self.login()
     self.get_screen_no = {
         "min1": "3000",
         "min3": "3001",
         "min5": "3002",
         "min10": "3003",
         "min60": "3004",
         "day": "3005",
         "week": "3006",
         "month": "3007",
         "year": "3008"
     }
     if duration.startswith("min"):
         self.collect_n_save_data_min(duration)
     else:
         self.collect_n_save_data(duration)
Ejemplo n.º 3
0
    def __init__(self):
        QMainWindow.__init__(self)

        # Application Configuration
        # UI
        self.setupUi(self)

        # Font(ko)
        self.set_ko_font()

        # Logger
        self.logger = TTlog(logger_name="TTRealCondi").logger

        # DB
        self.mongo = MongoClient()
        self.db = self.mongo.TopTrader
        self.dbm = DBM('TopTrader')

        # Slack
        self.slack = Slack(cfg_mgr.get_slack_token())

        # Kiwoom
        self.kw = Kiwoom()
        self.login()
        cfg_mgr.STOCK_INFO = self.kw.get_stock_basic_info()

        # app main
        cfg_mgr.MODE = constant.DEBUG
        self.main()
Ejemplo n.º 4
0
    def __init__(self):
        super().__init__()
        # self.setupUi(self)  # load app screen
        self.logger = TTlog(logger_name="RealCondi").logger
        self.mongo = MongoClient()
        self.tt_db = self.mongo.TopTrader
        self.slack = Slack(config_manager.get_slack_token())
        self.kw = Kiwoom()
        self.login()

        # ready to search condi
        self.load_stock_info()
        t = datetime.today()
        self.s_time = datetime(t.year, t.month, t.day, 9, 0, 0)  # 장 시작시간, 오전9시

        # fake trading
        self.timer = None
        self.start_timer()

        # core function
        self.screen_no = 4000
        self.N1, self.N2 = 0, 10

        # self.screen_no = 4001
        # self.N1, self.N2 = 10, 20

        self.real_condi_search()
Ejemplo n.º 5
0
 def __init__(self):
     super().__init__()
     self.logger = TTlog().logger
     self.mongo = MongoClient()
     self.tt_db = self.mongo.TopTrader
     self.slack = Slack(config_manager.get_slack_token())
     self.kw = Kiwoom()
     self.init_trading()
     # self.just_sell_all_stocks()
     self.auto_trading()
Ejemplo n.º 6
0
 def __init__(self):
     super().__init__()
     # self.setupUi(self)  # load app screen
     self.logger = TTlog().logger
     self.db = MongoClient().TopTrader
     self.kw = Kiwoom()
     self.login()
     self.realtime_stream()
     self.timer = None
     self.start_timer()
Ejemplo n.º 7
0
 def __init__(self):
     super().__init__()
     # self.setupUi(self)  # load app screen
     self.logger = TTlog().logger
     self.dbm = DBM('TopTrader')
     self.mongo = MongoClient()
     self.db = self.mongo.TopTrader
     self.slack = Slack(config_manager.get_slack_token())
     self.kw = Kiwoom()
     self.login()
     self.main()
Ejemplo n.º 8
0
class TopTrader(QMainWindow, ui):
    def __init__(self):
        super().__init__()
        # self.setupUi(self)  # load app screen
        self.logger = TTlog().logger
        self.db = MongoClient().TopTrader
        self.kw = Kiwoom()
        self.login()
        self.realtime_stream()
        self.timer = None
        self.start_timer()

    def login(self):
        # Login
        err_code = self.kw.login()
        if err_code != 0:
            self.logger.error("Login Fail")
            return
        self.logger.info("Login success")

    def start_timer(self):
        if self.timer:
            self.timer.stop()
            self.timer.deleteLater()
        self.timer = QTimer()
        self.timer.timeout.connect(self.timer_call)
        # self.timer.setSingleShot(True)
        self.timer.start(10000)  # 10 sec interval

    def timer_call(self):
        self.logger.info("")
        self.logger.info("=" * 100)
        self.logger.info("Timer Call !")
        self.logger.info("=" * 100)

    def realtime_stream_callback(self, data):
        self.logger.info("[realtime_stream_callback]")
        self.logger.info("data: {}".format(data))
        self.db.realtime_stream.insert({'real_data': data})

    def realtime_stream(self):
        code_list = "066570;000030;000270;000660;005930;068270;045390;064350;011390;025560"
        screen_no = "6001"
        self.kw.reg_callback("OnReceiveRealData", "",
                             self.realtime_stream_callback)
        self.kw.set_real_reg(screen_no, code_list,
                             "10;11;12;13;14;16;17;27;28;", 0)
Ejemplo n.º 9
0
class TopTrader(QMainWindow, ui):
    def __init__(self):
        QMainWindow.__init__(self)

        # Application Configuration
        # UI
        self.setupUi(self)

        # Font(ko)
        self.set_ko_font()

        # Logger
        self.logger = TTlog(logger_name="TTRealCondi").logger

        # DB
        self.mongo = MongoClient()
        self.db = self.mongo.TopTrader

        # Slack
        #self.slack = Slacker(cfg_mgr.get_slack_token())

        # Kiwoom
        self.kw = Kiwoom()
        self.login()
        cfg_mgr.stock_info = self.kw.get_stock_basic_info()

        # app main
        self.main()

    def login(self):
        err_code = self.kw.login()
        if err_code != 0:
            self.logger.error("Login Fail")
            exit(-1)
        self.logger.info("Login success")

    def set_ko_font(self):
        # 그래프에서 마이너스 폰트 깨지는 문제에 대한 대처
        mpl.rcParams['axes.unicode_minus'] = False

        #path = 'c:/Windows/Fonts/D2Coding-Ver1.3-20171129.ttc'
        path = 'c:/Windows/Fonts/gulim.ttc'
        font_name = fm.FontProperties(fname=path).get_name()
        plt.rcParams["font.family"] = font_name

    def main(self):
        print("Start Application")
class TopTrader(QMainWindow, ui):
    def __init__(self):
        QMainWindow.__init__(self)

        # Application Configuration
        # UI
        self.setupUi(self)

        # Font(ko)
        self.set_ko_font()

        # Logger
        self.logger = TTlog(logger_name="TTRealCondi").logger

        # DB
        self.mongo = MongoClient()
        self.db = self.mongo.TopTrader

        # Slack
        self.slack = Slacker(config_manager.get_slack_token())

        # Kiwoom
        self.kw = Kiwoom()
        self.login()
        self.stock_info = self.kw.get_stock_basic_info()

        # app main
        self.main()

    def login(self):
        err_code = self.kw.login()
        if err_code != 0:
            self.logger.error("Login Fail")
            exit(-1)
        self.logger.info("Login success")

    def set_ko_font(self):
        # 그래프에서 마이너스 폰트 깨지는 문제에 대한 대처
        mpl.rcParams['axes.unicode_minus'] = False

        path = 'c:/Windows/Fonts/D2Coding-Ver1.3.2-20180524.ttf'
        font_name = fm.FontProperties(fname=path).get_name()
        plt.rcParams["font.family"] = font_name

    def main(self):
        print("Start Application")
        # 금일 급등했던 종목 정보를 가져온다.
        stock_info = self.kw.rapidly_rising_price_stock(market="000",
                                                        time_gubun="2",
                                                        time="0",
                                                        vol_gubun="00000",
                                                        screen_no="5000")

        # 급등했던 종목중 상위 20개를 추린다.
        stock_info = stock_info[:20]

        # 상위 20개에 대해 체결강도 정보를 수집하여 DB에 저장한다.
        for stock in stock_info:
            code = stock['종목코드']
            ret = self.kw.get_chegyul_info(code, "9000")
            pdb.set_trace()
            for data in ret:
                h, m, s = data['시간'][:2], data['시간'][2:4], data['시간'][4:]
                t = datetime.today()
                data['date'] = datetime(t.year, t.month, t.day, int(h), int(m),
                                        int(s))
                data['code'] = code
                data['stock_name'] = self.stock_info[code]["stock_name"]
                data['market'] = self.stock_info[code]["market"]
            self.db.short_trading_info_chegyul.insert(ret)
            print(ret)

        # 상위 20개에 대해 분봉/틱봉 정보를 수집하여 DB에 저장한다.
        t = datetime.today()
        s_date = datetime(t.year, t.month, t.day, 9, 0, 0)
        e_date = datetime(t.year, t.month, t.day, 17, 0, 0)

        for stock in stock_info:
            code = stock['종목코드']
            ret = self.kw.stock_price_by_min(code, "1", "9001", s_date, e_date)
            for data in ret:
                data['stock_name'] = self.stock_info[code]["stock_name"]
                data['market'] = self.stock_info[code]["market"]
            self.db.time_series_min1.insert(ret)

            ret = self.kw.stock_price_by_tick(code, "10", "9002", s_date,
                                              e_date)
            for data in ret:
                data['stock_name'] = self.stock_info[code]["stock_name"]
                data['market'] = self.stock_info[code]["market"]
            self.db.time_series_tick10.insert(ret)

        # 상위 20개에 대해 호가 정보를 수집하여 DB에 저장한다.
        # for stock in stock_info:
        #     code = stock['종목코드']
        #     ret = self.kw.get_hoga_info(code, "9001")
        #     self.db.short_trading_info_hoga.insert(ret)
        #     print(ret)
        print("end")
Ejemplo n.º 11
0
class TopTrader(QMainWindow, ui):
    def __init__(self):
        super().__init__()
        self.logger = TTlog().logger
        self.mongo = MongoClient()
        self.tt_db = self.mongo.TopTrader
        self.slack = Slack(config_manager.get_slack_token())
        self.kw = Kiwoom()
        self.init_trading()
        # self.just_sell_all_stocks()
        self.auto_trading()

    def init_trading(self):
        self.login()
        # self.update_stock_info()
        self.load_stock_info()
        self.set_account()
        self.my_stock_pocket = set()  # 보유중인 종목의 code를 저장
        t = datetime.today()
        self.s_time = datetime(t.year, t.month, t.day, 9, 0, 0)  # 장 시작시간, 오전9시

    def login(self):
        # Login
        err_code = self.kw.login()
        if err_code != 0:
            self.logger.error("Login Fail")
            exit(-1)
        self.logger.info("Login success")

    def load_stock_info(self):
        self.stock_dict = {}
        doc = self.tt_db.stock_information.find({})
        for d in doc:
            code = d["code"]
            self.stock_dict[code] = d
        self.logger.info("loading stock_information completed.")

    def update_stock_info(self):
        # kospi
        kospi = []
        code_list = self.kw.get_code_list_by_market("0")
        for code in code_list:
            stock_name = self.kw.get_master_stock_name(code)
            kospi.append({
                "code": code,
                "stock_name": stock_name,
                "market": "kospi"
            })
        self.tt_db.stock_information.insert(kospi)

        # kosdaq
        kosdaq = []
        code_list = self.kw.get_code_list_by_market("10")
        for code in code_list:
            stock_name = self.kw.get_master_stock_name(code)
            kosdaq.append({
                "code": code,
                "stock_name": stock_name,
                "market": "kosdaq"
            })
        self.tt_db.stock_information.insert(kosdaq)

    def set_account(self):
        self.acc_no = self.kw.get_login_info("ACCNO")
        self.acc_no = self.acc_no.strip(";")  # 계좌 1개를 가정함.
        self.stock_account = self.get_account_info(self.acc_no)

        # kiwoom default account setting
        self.kw.set_account(self.acc_no)

    def start_timer(self):
        if self.timer:
            self.timer.stop()
            self.timer.deleteLater()
        self.timer = QTimer()
        self.timer.timeout.connect(self.check_stocks_to_sell)
        # self.timer.setSingleShot(True)
        self.timer.start(30000)  # 30 sec interval

    def just_sell_all_stocks(self):
        curr_time = datetime.today()
        self.stock_account = self.get_account_info(self.acc_no)
        for data in self.stock_account["종목정보"]:
            self.logger.info("Trading시간 종료되어 보유한 종목 모두 매도처리합니다.")
            code, stock_name, quantity = data["종목코드"][1:], data["종목명"], int(
                data["보유수량"])
            self.kw.시장가_신규매도(code, quantity)
            손익율 = data["손익율"]
            self.tt_db.trading_history.insert({
                'date':
                curr_time,
                'code':
                code,
                'stock_name':
                self.stock_dict[code]["stock_name"],
                'market':
                self.stock_dict[code]["market"],
                'event':
                '',
                'condi_name':
                '',
                'trade':
                'sell',
                'profit':
                손익율,
                'quantity':
                quantity,
                'hoga_gubun':
                '시장가',
                'account_no':
                self.acc_no
            })
            time.sleep(0.5)

    def check_stocks_to_sell(self):
        self.logger.info("[Timer Interrupt] 30 second")
        self.stock_account = self.get_account_info(self.acc_no)
        curr_time = datetime.today()
        self.logger.info("=" * 50)
        self.logger.info("현재 계좌 현황입니다...")

        if not bool(self.stock_account):
            self.logger.error("계좌정보를 제대로 받아오지 못했습니다.")
            return

        if datetime.today() < self.s_time:
            self.logger.info("시작시간이 되지 않아 매도하지 않습니다.")
            return

        self.my_stock_pocket = set()
        for data in self.stock_account["종목정보"]:
            code, stock_name, quantity = data["종목코드"][1:], data["종목명"], int(
                data["보유수량"])
            self.logger.info("* 종목: {}, 손익율: {}%, 보유수량: {}, 평가금액: {}원".format(
                data["종목명"], ("%.2f" % data["손익율"]), int(data["보유수량"]),
                format(int(data["평가금액"]), ',')))
            self.my_stock_pocket.add(code)
            손익율 = data["손익율"]
            if 손익율 >= 3.0 or 손익율 <= -2.0:
                if 손익율 > 0:
                    self.logger.info(
                        "시장가로 물량 전부 익절합니다. ^^    [{}:{}, {}주]".format(
                            stock_name, code, quantity))
                else:
                    self.logger.info(
                        "시장가로 물량 전부 손절합니다. ㅜㅜ. [{}:{}, {}주]".format(
                            stock_name, code, quantity))

                self.my_stock_pocket.remove(code)
                self.kw.시장가_신규매도(code, quantity)
                self.tt_db.trading_history.insert({
                    'date':
                    curr_time,
                    'code':
                    code,
                    'stock_name':
                    self.stock_dict[code]["stock_name"],
                    'market':
                    self.stock_dict[code]["market"],
                    'event':
                    '',
                    'condi_name':
                    '',
                    'trade':
                    'sell',
                    'profit':
                    손익율,
                    'quantity':
                    quantity,
                    'hoga_gubun':
                    '시장가',
                    'account_no':
                    self.acc_no
                })

    def get_account_info(self, acc_no):
        self.logger.info("계좌평가현황요청")
        ret = self.kw.계좌평가현황요청("계좌평가현황요청", acc_no, "", "1", "6001")
        return ret

    def search_condi(self, event_data):
        """키움모듈의 OnReceiveRealCondition 이벤트 수신되면 호출되는 callback함수
        이벤트 정보는 event_data 변수로 전달된다.

            ex)
            event_data = {
                "code": code, # "066570"
                "event_type": event_type, # "I"(종목편입), "D"(종목이탈)
                "condi_name": condi_name, # "스켈핑"
                "condi_index": condi_index # "004"
            }
        :param dict event_data:
        :return:
        """
        curr_time = datetime.today()
        if curr_time < self.s_time:
            self.logger.info("시작시간이 되지 않아 매수하지 않습니다.")
            return

        # 실시간 조건검색 이력정보
        self.tt_db.real_condi_search.insert({
            'date':
            curr_time,
            'code':
            event_data["code"],
            'stock_name':
            self.stock_dict[event_data["code"]]["stock_name"],
            'market':
            self.stock_dict[event_data["code"]]["market"],
            'event':
            event_data["event_type"],
            'condi_name':
            event_data["condi_name"]
        })

        if event_data["event_type"] == "I":
            예수금 = self.stock_account["계좌정보"]["예수금"]
            D2_예수금 = self.stock_account["계좌정보"]["예수금"]
            총예수금 = 예수금 + D2_예수금
            if 총예수금 < 100000:  # 잔고가 10만원 미만이면 매수 안함
                self.logger.info("총예수금({}) 부족으로 추가 매수하지 않습니다.".format(총예수금))
                return

            if event_data["code"] in self.my_stock_pocket:
                self.logger.info("해당 종목({}) 이미 보유중이라 추가매수하지 않습니다.".format(
                    self.stock_dict[event_data["code"]]["stock_name"]))
                return
            # curr_price = self.kw.get_curr_price(event_data["code"])
            # quantity = int(100000/curr_price)
            quantity = 20
            # self.kw.reg_callback("OnReceiveChejanData", ("조건식매수", "5000"), self.account_stat)
            stock_name = self.stock_dict[event_data["code"]]["stock_name"]
            market = self.stock_dict[event_data["code"]]["market"]
            self.tt_db.trading_history.insert({
                'date':
                curr_time,
                'code':
                event_data["code"],
                'stock_name':
                stock_name,
                'market':
                market,
                'event':
                event_data["event_type"],
                'condi_name':
                event_data["condi_name"],
                'trade':
                'buy',
                'quantity':
                quantity,
                'hoga_gubun':
                '시장가',
                'account_no':
                self.acc_no
            })
            self.logger.info("{}:{}를 {}주 시장가_신규매수합니다.".format(
                stock_name, event_data["code"], quantity))
            self.my_stock_pocket.add(event_data["code"])
            self.kw.시장가_신규매수(event_data["code"], quantity)
            # self.kw.send_order("조건식매수", "5000", self.acc_no, 1, event_data["code"], quantity, 0, "03", "")

    def auto_trading(self):
        """키움증권 HTS에 등록한 조건검색식에서 검출한 종목을 매수하고
        -2%, +3%에 손절/익절 매도하는 기본적인 자동매매 함수

        :return:
        """
        self.logger.info("TopTrader 자동매매 시작합니다...")

        self.timer = None
        self.start_timer()

        # callback fn 등록
        self.kw.reg_callback("OnReceiveRealCondition", "", self.search_condi)

        screen_no, cnt = 4000, 0
        condi_info = self.kw.get_condition_load()
        self.logger.info("실시간 조건 검색 시작합니다.")
        for condi_name, condi_id in condi_info.items():
            # 화면번호, 조건식이름, 조건식ID, 실시간조건검색(1)
            self.logger.info("화면번호: {}, 조건식명: {}, 조건식ID: {}".format(
                screen_no, condi_name, condi_id))
            self.kw.send_condition(str(screen_no), condi_name, int(condi_id),
                                   1)
            time.sleep(0.5)
            cnt += 1
            if cnt == 10:
                screen_no += 1
                cnt = 0
Ejemplo n.º 12
0
class TopTrader(QMainWindow, ui):
    def __init__(self):
        super().__init__()
        # self.setupUi(self)  # load app screen
        duration = sys.argv[1]
        self.logger = TTlog(logger_name="TT"+duration).logger
        self.mongo = MongoClient()
        self.tt_db = self.mongo.TopTrader
        self.slack = Slack(config_manager.get_slack_token())
        today = datetime.today()
        self.end_date = datetime(today.year, today.month, today.day, 16, 0, 0)
        self.kw = Kiwoom()
        self.login()
        self.get_screen_no = {
            "min1": "3000",
            "min3": "3001",
            "min5": "3002",
            "min10": "3003",
            "min60": "3004",
            "day": "3005",
            "week": "3006",
            "month": "3007",
            "year": "3008"
        }
        if duration.startswith("min"):
            self.collect_n_save_data_min(duration)
        else:
            self.collect_n_save_data(duration)

    def login(self):
        err_code = self.kw.login()
        if err_code != 0:
            self.logger.error("Login Fail")
            exit(-1)
        self.logger.info("Login success")

    def upsert_db(self, col, datas):
        self.logger.info("Upsert Data to DB")
        s_time = time.time()
        for doc in datas:
            # col.update(condition, new_data, upsert=True)
            col.update({'date': doc['date'], 'code': doc['code']}, doc, upsert=True)
        e_time = time.time()
        print("Time: ", int(e_time-s_time))

    def get_stock_list(self, market):
        kospi_code_list = self.kw.get_code_list_by_market(market)
        stock_list = [[c, self.kw.get_master_stock_name(c)] for c in kospi_code_list]
        stock_list = [(c, name) for c, name in stock_list if not any(map(lambda x: x in name, constant.FILTER_KEYWORD))]
        stock_list.sort()
        return stock_list

    def get_last_data(self, cur, duration):
        current_flag = True
        if duration.startswith("min"):
            first_date = datetime(2018, 7, 23, 0, 0, 0)
        else:
            first_date = datetime(2018, 6, 1, 0, 0, 0)

        # 최초 저장하는 경우
        if cur.count() == 0:
            s_date, e_date, s_index = first_date, self.end_date, 0
        else:
            data = cur.next()
            if (data['last'] + 1) != data['total']:
                # 지난번에 저장하다가 중간에 멈춘 경우
                if data['end_date'] != self.end_date:
                    s_date, e_date, s_index = data['start_date'], data['end_date'], data['last'] + 1
                    current_flag = False
                # 이번에 저장하다가 중간에 멈춘 경우
                else:
                    s_date, e_date, s_index = data['start_date'], self.end_date, data['last'] + 1
            else:
                # 지난번에 저장을 완료, 이번에 저장해야 하는 경우
                if data['end_date'] != self.end_date:
                    s_date, e_date, s_index = data['end_date'], self.end_date, 0
                # 이번에 저장을 완료
                else:
                    s_date, e_date, s_index = data['end_date'], self.end_date, data['last'] + 1
        return s_date, e_date, s_index, current_flag

    def collect_n_save_data_min(self, duration):
        """
        코스피 종목의 분단위 데이터를 수집한다.

        1. 한번도 db에 저장한적이 없다면 6/1일부터 오늘까지의 데이터를 저장한다.
        2. 지난번에 저장하다가 중간에 멈췄다면, 나머지 작업을 모두 완료 후, 해당시점의 e_date 부터 오늘까지의 데이터를 전 종목에 대해 저장한다.
        3.   이번에 저장하다가 중간에 멈췄다면, 이전 e_date 부터 오늘까지의 데이터를 전 종목에 대해 저장한다.
        4. 지난번에 저장을 완료했다면, 해당시점의 e_date 부터 오늘까지의 데이터를 전 종목에 대해 저장한다.

        :param duration: min1, min3, min5, min10, min60 중 하나의 값
        :return:
        """
        # stock_list = self.get_stock_list(constant.KOSPI)
        # stock_list += self.get_stock_list(constant.KOSDAQ)

        stock_list = self.get_stock_list(constant.KOSDAQ)
        cur = self.tt_db.time_series_temp2.find({'type': duration})
        s_date, e_date, s_index, current_flag = self.get_last_data(cur, duration)

        if not current_flag:
            msg = "[{}] {} ~ {}. start to collect stock data. this is previous process.".format(
                duration, s_date, e_date, e_date, self.end_date
            )
        else:
            msg = "[{}] {} ~ {}. start to collect stock data. this is current process.".format(
                duration, s_date, e_date
            )
        self.slack.log(msg)

        col = {
            "min1": self.tt_db.time_series_min1,
            "min3": self.tt_db.time_series_min3,
            "min5": self.tt_db.time_series_min5,
            "min10": self.tt_db.time_series_min10,
            "min60": self.tt_db.time_series_min60
        }[duration]
        fn = self.kw.stock_price_by_min

        total = len(stock_list)
        msg = "[{}] {} / {} -> start to collect stock data".format(duration, s_index, total)
        self.slack.log(msg)

        for i, stock in enumerate(stock_list[s_index:], s_index):
            code, stock_name = stock
            self.logger.info("%s/%s - %s/%s" % (i, total, code, stock_name))
            self.logger.info("period : {} ~ {}".format(s_date, e_date))
            self.logger.info("time_series_{}".format(duration))

            try:
                doc = fn(code, tick=duration.strip("min"), screen_no=self.get_screen_no[duration],
                         start_date=s_date, end_date=e_date)
            except KiwoomServerCheckTimeError as e:
                self.logger.error("[KiwoomServerCheckTimeError] {}".format(duration))
                self.tt_db.urgent2.update({'type': 'error'},
                                         {'type': 'error', 'error_code': e.error_code},
                                         upsert=True)
                exit(0)

            try:
                self.upsert_db(col, doc)
            except pymongo.errors.InvalidOperation as e:
                # cannot do an empty bulk write ?
                self.logger.error(e)

            self.tt_db.time_series_temp2.update({'type': duration},
                                               {'type': duration,
                                                'code': code,
                                                'stock_name': stock_name,
                                                'last': i,
                                                'start_date': s_date,
                                                'end_date': e_date,
                                                'total': total},
                                               upsert=True)
            self.tt_db.urgent2.update({'type': 'error'},
                                     {'type': 'error', 'error_code': 0},
                                     upsert=True)
        exit(0)  # Program exit

    def collect_n_save_data(self, duration):
        """
        코스피 종목의 분단위 데이터를 제외한 나머지 데이터를 수집한다.

        1. 한번도 db에 저장한적이 없다면 6/1일부터 오늘까지의 데이터를 저장한다.
        2. 지난번에 저장하다가 중간에 멈췄다면, 나머지 작업을 모두 완료 후, 해당시점의 e_date 부터 오늘까지의 데이터를 전 종목에 대해 저장한다.
        3.   이번에 저장하다가 중간에 멈췄다면, 이전 e_date 부터 오늘까지의 데이터를 전 종목에 대해 저장한다.
        4. 지난번에 저장을 완료했다면, 해당시점의 e_date 부터 오늘까지의 데이터를 전 종목에 대해 저장한다.

        :param duration: str - day, week, month, year 중 하나의 값
        :return:
        """
        stock_list = self.get_stock_list(constant.KOSPI)
        stock_list += self.get_stock_list(constant.KOSDAQ)
        cur = self.tt_db.time_series_temp2.find({'type': duration})
        s_date, e_date, s_index, current_flag = self.get_last_data(cur, duration)

        if not current_flag:
            msg = "[{}] {} ~ {}. start to collect stock data. this is previous process.".format(
                duration, s_date, e_date, e_date, self.end_date
            )
        else:
            msg = "[{}] {} ~ {}. start to collect stock data. this is current process.".format(
                duration, s_date, e_date
            )
            self.slack.log(msg)

        col = {
            "day": self.tt_db.time_series_day,
            "week": self.tt_db.time_series_week,
            "month": self.tt_db.time_series_month,
            "year": self.tt_db.time_series_year
        }[duration]

        fn = {
            "day": self.kw.stock_price_by_day,
            "week": self.kw.stock_price_by_week,
            "month": self.kw.stock_price_by_month
            # "year": self.kw.stock_price_by_year
        }[duration]

        total = len(stock_list)
        msg = "[{}] {} / {} -> start to collect stock data".format(duration, s_index, total)
        self.slack.log(msg)

        for i, stock in enumerate(stock_list[s_index:], s_index):
            code, stock_name = stock
            self.logger.info("%s/%s - %s/%s" % (i, total, code, stock_name))
            self.logger.info("time_series_{}".format(duration))
            try:
                doc = fn(code, screen_no=self.get_screen_no[duration], start_date=s_date, end_date=e_date)
            except KiwoomServerCheckTimeError as e:
                self.logger.error("[KiwoomServerCheckTimeError] {}".format(duration))
                self.tt_db.urgent2.update({'type': 'error'},
                                         {'type': 'error', 'error_code': e.error_code},
                                         upsert=True)
                exit(0)
            self.upsert_db(col, doc)
            self.tt_db.time_series_temp2.update({'type': duration},
                                               {'type': duration,
                                                'code': code,
                                                'stock_name': stock_name,
                                                'last': i,
                                                'start_date': s_date,
                                                'end_date': e_date,
                                                'total': total},
                                               upsert=True)

            self.tt_db.urgent2.update({'type': 'error'},
                                     {'type': 'error', 'error_code': 0},
                                     upsert=True)
        exit(0)  # Program exit
Ejemplo n.º 13
0
class TopTrader(QMainWindow, ui):
    def __init__(self):
        QMainWindow.__init__(self)

        # Application Configuration
        # UI
        self.setupUi(self)

        # Font(ko)
        self.set_ko_font()

        # Logger
        self.logger = TTlog(logger_name="TTRealCondi").logger

        # DB
        self.dbm = DBM('TopTrader')

        # Slack
        self.slack = Slacker(config_manager.get_slack_token())

        # Kiwoom
        self.kw = Kiwoom()
        self.login()
        self.stock_info = self.kw.get_stock_basic_info()

        # app main
        self.main()

    def login(self):
        err_code = self.kw.login()
        if err_code != 0:
            self.logger.error("Login Fail")
            exit(-1)
        self.logger.info("Login success")

    def set_ko_font(self):
        # 그래프에서 마이너스 폰트 깨지는 문제에 대한 대처
        mpl.rcParams['axes.unicode_minus'] = False

        path = 'c:/Windows/Fonts/D2Coding-Ver1.3-20171129.ttc'
        font_name = fm.FontProperties(fname=path).get_name()
        plt.rcParams["font.family"] = font_name

    def main(self):
        print("Start Application")
        target_date = datetime(2018, 8, 2)
        y, m, d = target_date.year, target_date.month, target_date.day
        s_time = datetime(y, m, d, 9, 0, 0)
        e_time = datetime(y, m, d, 15, 30, 0)
        self.code = '000020'
        df = pd.DataFrame(
            self.dbm.get_tick_data(self.code, target_date, tick="1"))
        ts_group = df.groupby('timestamp')
        volumn = pd.DataFrame(ts_group.sum()['거래량'])
        price = pd.DataFrame(ts_group.max()['현재가'])
        index = pd.date_range(s_time, e_time, freq='S')
        volumn = volumn.reindex(index, method='ffill', fill_value=0)
        price = price.reindex(index, method='ffill', fill_value=0)
        price['volumn'] = volumn

        from trading.account import Stock

        tick_data = defaultdict(list)
        stock_list = [
            Stock('900100', '주식1'),
            Stock('200710', '주식2'),
            Stock('206560', '주식3')
        ]
        for stock in stock_list:
            stock.gen_time_series_sec1(target_date)
            tick_data[stock.code] = stock.time_series_sec1
        pdb.set_trace()

        db_data = self.dbm.get_real_condi_search_data(target_date,
                                                      "소형주_급등_005_003")

        condi_hist = defaultdict(defaultdict)
        for data in db_data[:5]:
            code, date = data['code'], data['date'].replace(microsecond=0)
            price = tick_data[code].ix[date]['현재가']
            condi_hist[code][date] = price

        pdb.set_trace()
        print("End Application")
Ejemplo n.º 14
0
class TopTrader(QMainWindow, ui):
    def __init__(self):
        super().__init__()
        # self.setupUi(self)  # load app screen
        self.logger = TTlog(logger_name="RealCondi").logger
        self.mongo = MongoClient()
        self.tt_db = self.mongo.TopTrader
        self.slack = Slack(config_manager.get_slack_token())
        self.kw = Kiwoom()
        self.login()

        # ready to search condi
        self.load_stock_info()
        t = datetime.today()
        self.s_time = datetime(t.year, t.month, t.day, 9, 0, 0)  # 장 시작시간, 오전9시

        # fake trading
        self.timer = None
        self.start_timer()

        # core function
        self.screen_no = 4000
        self.N1, self.N2 = 0, 10

        # self.screen_no = 4001
        # self.N1, self.N2 = 10, 20

        self.real_condi_search()

    def load_stock_info(self):
        self.stock_dict = {}
        doc = self.tt_db.stock_information.find({})
        for d in doc:
            code = d["code"]
            self.stock_dict[code] = d
        self.logger.info("loading stock_information completed.")

    def start_timer(self):
        if self.timer:
            self.timer.stop()
            self.timer.deleteLater()
        self.timer = QTimer()
        self.timer.timeout.connect(self.fake_check_to_sell)
        # self.timer.setSingleShot(True)
        self.timer.start(1000) # 1 sec interval

    def fake_check_to_sell(self):
        """

        :return:
        """

    def search_result(self, event_data):
        """

        :param event_data:
        :return:
        """
        curr_time = datetime.today()

        if curr_time < self.s_time:
            self.logger.info("=" * 100)
            self.logger.info("장 Open 전 입니다. 오전 9:00 이후에 검색 시작합니다.")
            self.logger.info("=" * 100)
            return

        # 실시간 조건검색 이력정보
        self.tt_db.real_condi_search.insert({
            'date': curr_time,
            'code': event_data["code"],
            'stock_name': self.stock_dict[event_data["code"]]["stock_name"],
            'market': self.stock_dict[event_data["code"]]["market"],
            'event': event_data["event_type"],
            'condi_index': event_data["condi_index"],
            'condi_name': event_data["condi_name"]
        })

    def real_condi_search(self):
        # callback fn 등록
        self.kw.reg_callback("OnReceiveRealCondition", "", self.search_result)
        # self.kw.notify_callback["OnReceiveRealCondition"] = self.search_condi

        condi_info = self.kw.get_condition_load()
        self.logger.info("실시간 조건 검색 시작합니다.")
        for condi_name, condi_id in list(condi_info.items())[self.N1:self.N2]:
            # 화면번호, 조건식이름, 조건식ID, 실시간조건검색(1)
            self.logger.info("화면번호: {}, 조건식명: {}, 조건식ID: {}".format(
                self.screen_no, condi_name, condi_id
            ))
            self.kw.send_condition(str(self.screen_no), condi_name, int(condi_id), 1)
            time.sleep(0.5)

    def login(self):
        err_code = self.kw.login()
        if err_code != 0:
            self.logger.error("Login Fail")
            exit(-1)
        self.logger.info("Login success")
Ejemplo n.º 15
0
class TopTrader(QMainWindow, ui):
    def __init__(self):
        super().__init__()
        # self.setupUi(self)  # load app screen
        self.logger = TTlog().logger
        self.dbm = DBM('TopTrader')
        self.mongo = MongoClient()
        self.db = self.mongo.TopTrader
        self.slack = Slack(config_manager.get_slack_token())
        self.kw = Kiwoom()
        self.login()
        self.main()

    def load_tick_data(self,
                       code,
                       stock_name,
                       date,
                       tick="1",
                       screen_no="1234"):
        """특정 종목의 하루단위 tick data를 가져오는 함수
        tick_data가 DB에 있으면 DB에서 가져오고, 없으면 kw module로부터 가져온다.

        :param code:
        :param stock_name:
        :param date:
        :param tick:
        :param screen_no:
        :return:
        """
        ret, cur = self.dbm.check_tick_cache(code, date, tick="1")

        if ret:
            tick_data = cur.next()
        else:
            base_date = datetime(date.year, date.month, date.day, 0, 0, 0)
            raw_data = self.kw.stock_price_by_tick(code,
                                                   tick=tick,
                                                   screen_no=screen_no,
                                                   date=base_date)
            tick_data = {
                'code':
                code,
                'stock_name':
                stock_name,
                'date':
                base_date,
                'time_series_1tick': [{
                    'timestamp': _d['date'],
                    '현재가': _d['현재가'],
                    '거래량': _d['거래량']
                } for _d in raw_data]
            }
        return tick_data

    def collect_tick_data(self,
                          code,
                          stock_name,
                          s_date,
                          e_date,
                          tick="1",
                          screen_no="1234"):
        """특정 종목의 일정 기간의 tick data를 DB에 저장하는 함수
        DB에 이미 값이 저장되어 있으면 저장하지 않고 skip 한다.
        s_date, e_date는 초단위까지 지정이 가능하지만, 저장은 일단위로 저장한다.
        tick은 1, 3, 5, 10, 30 선택 가능하다.

        :param code:
        :param stock_name:
        :param tick:
        :param s_date:
        :param e_date:
        :return:
        """
        s_base_date = datetime(s_date.year, s_date.month, s_date.day, 0, 0, 0)
        e_base_date = datetime(e_date.year, e_date.month, e_date.day, 0, 0, 0)
        days = (e_base_date - s_base_date).days + 1
        date_list = [s_base_date + timedelta(days=x) for x in range(0, days)]
        for base_date in date_list:
            ret, cur = self.dbm.check_tick_cache(code, base_date, tick="1")
            if ret:
                self.logger.debug(
                    "No need to save data. already has data in DB")
                continue

            raw_data = self.kw.stock_price_by_tick(code,
                                                   tick=tick,
                                                   screen_no=screen_no,
                                                   date=base_date)
            tick_data = {
                'code':
                code,
                'stock_name':
                stock_name,
                'date':
                base_date,
                'time_series_1tick': [{
                    'timestamp': _d['date'],
                    '현재가': _d['현재가'],
                    '거래량': _d['거래량']
                } for _d in raw_data]
                # 'time_series': [{'timestamp': _d['date'], '현재가': _d['현재가'], '거래량': _d['거래량']} for _d in raw_data]
            }
            # DB에 없으면 수행되는 부분이라서 insert 함수를 사용.
            self.dbm.save_tick_data(tick_data, tick="1")

    def main(self):
        # 사용자 정의 부분_S
        # 8/2일자 조건검색식으로 검출된 모든 종목의 1tick data를 수집한다.
        with open("base_date_when_collect_tick_data.txt") as f:
            year, month, day = [int(i) for i in f.read().strip().split(" ")]
        self.base_date = datetime(year, month, day)
        # 사용자 정의 부분_E

        # kospi, kosdaq 모든 종목의 코드와 종목명 정보를 불러온다.
        self.stock_info = self.kw.get_stock_basic_info()

        code_list = self.dbm.get_code_list_condi_search_result(self.base_date)
        code_list.sort()
        self.dbm.record_collect_tick_data_status("START",
                                                 self.base_date,
                                                 tick="1")
        for num, code in enumerate(code_list, 1):
            stock_name = self.stock_info[code]["stock_name"]
            if self.dbm.already_collect_tick_data(code,
                                                  self.base_date,
                                                  tick="1"):
                self.logger.debug(
                    "{}/{} - {}:{} Skip. Already saved data!".format(
                        num, len(code_list), code, stock_name))
                continue

            self.logger.debug("{}/{} - {}:{} Start !".format(
                num, len(code_list), code, stock_name))
            self.collect_tick_data(code,
                                   stock_name,
                                   self.base_date,
                                   self.base_date,
                                   tick="1",
                                   screen_no="1234")
            self.logger.debug("{}/{} - {}:{} Completed !".format(
                num, len(code_list), code, stock_name))

            self.dbm.save_collect_tick_data_history(code,
                                                    self.base_date,
                                                    tick="1")
            self.dbm.record_collect_tick_data_status("WORKING",
                                                     self.base_date,
                                                     tick="1")

        self.dbm.record_collect_tick_data_status("END",
                                                 self.base_date,
                                                 tick="1")
        self.logger.debug("save all 1tick information..")
        exit(0)  # program exit

    def login(self):
        err_code = self.kw.login()
        if err_code != 0:
            self.logger.error("Login Fail")
            exit(-1)
        self.logger.info("Login success")
Ejemplo n.º 16
0
class TopTrader(QMainWindow, ui):
    def __init__(self):
        QMainWindow.__init__(self)

        # Application Configuration
        # UI
        self.setupUi(self)

        # Font(ko)
        self.set_ko_font()

        # Logger
        self.logger = TTlog(logger_name="TTRealCondi").logger

        # DB
        self.mongo = MongoClient()
        self.db = self.mongo.TopTrader
        self.dbm = DBM('TopTrader')

        # Slack
        self.slack = Slack(cfg_mgr.get_slack_token())

        # Kiwoom
        self.kw = Kiwoom()
        self.login()
        cfg_mgr.STOCK_INFO = self.kw.get_stock_basic_info()

        # app main
        cfg_mgr.MODE = constant.DEBUG
        self.main()

    def login(self):
        err_code = self.kw.login()
        if err_code != 0:
            self.logger.error("Login Fail")
            exit(-1)
        self.logger.info("Login success")

    def set_ko_font(self):
        # 그래프에서 마이너스 폰트 깨지는 문제에 대한 대처
        mpl.rcParams['axes.unicode_minus'] = False
        try:
            path = 'c:/Windows/Fonts/D2Coding-Ver1.3-20171129.ttc'
            font_name = fm.FontProperties(fname=path).get_name()
            plt.rcParams["font.family"] = font_name
        except FileNotFoundError as e:
            path = 'c:/Windows/Fonts/D2Coding-Ver1.3.2-20180524.ttf'
            font_name = fm.FontProperties(fname=path).get_name()
            plt.rcParams["font.family"] = font_name

    def collect_1tick_data(self, code, stock_name, date):
        col_tick1 = self.db.time_series_tick1
        cur = col_tick1.find({'code': code, 'date': date})
        if cur.count() != 0:
            print("{}:{} Already save data. so Skip to save data !".format(
                code, stock_name))
            return

        s_date = date
        e_date = date + timedelta(days=1)
        raw_data = self.kw.stock_price_by_tick(code,
                                               tick="1",
                                               screen_no="1234",
                                               start_date=s_date,
                                               end_date=e_date)
        data = {
            'code':
            code,
            'stock_name':
            stock_name,
            'date':
            date,
            'time_series_1tick': [{
                'timestamp': _d['date'],
                '현재가': _d['현재가'],
                '거래량': _d['거래량']
            } for _d in raw_data]
        }
        # col_tick1.insert(data)
        return data

    def check_cache_tick1(self, code, s_date, e_date):
        col_tick1 = self.db.time_series_tick1
        s_base_date = datetime(s_date.year, s_date.month, s_date.day, 0, 0, 0)
        cur = col_tick1.find({
            'code': code,
            'date': {
                '$gte': s_base_date,
                '$lte': e_date
            }
        })
        if cur.count() != 0:
            return True, cur
        return False, None

    def main(self):
        # 목표 !!!
        # 하루 단위의 조건검색 결과를 분석한다.

        # 사용자 지정 변수__S
        self.target_date = datetime.today()
        self.target_date = datetime(2018, 8, 2)  # temp code
        # 사용자 지정 변수__E

        # 조건검색식 load
        condi_info = self.kw.get_condition_load()
        strg_list = []
        # loop를 돌면서 각각의 조건검색식에 대해 결과 분석
        for condi_name, condi_index in condi_info.items():
            # 특정일의 특정조건검색식을 특정전략으로 검증
            condi = ConditionalSearch.get_instance(condi_index, condi_name)

            self.logger.info("=======[ Smulation(%s) Start! ]=======" %
                             condi.condi_name)
            strg = Strategy("short_trading.strategy", condi)
            strg.simulate(self.target_date)
            strg_list.append(strg)
            self.logger.info("=======[ Smulation(%s) End! ]=======" %
                             condi.condi_name)
            self.logger.info("\n\n\n")

        self.logger.info("end")
        exit(0)