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 __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 __init__(self, strg_name, condi_index, condi_name): self.strategy_name = strg_name # 사용한 전략명 self.condi_name = condi_index # buy signal을 제공한 조건검색식(buy에서만 사용) self.condi_index = condi_name # buy signal을 제공한 조건검색식 index (buy에서만 사용) self.history = [] self.dbm = DBM('TopTrader') self.logger = TTlog().logger
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 __init__(self, init_balance, th): self.시작잔고 = init_balance self.예수금 = init_balance self.총평가금액 = 0.0 self.총매입금액 = 0.0 self.총최대매입금액 = 0.0 self.총평가손익 = 0.0 self.총손익 = 0.0 # 총평가손익 + 총누적손익 self.추정자산 = init_balance self.총수익률 = 0.0 self.총누적손익 = 0.0 self.총누적수익률 = 0.0 self.보유주식 = {} self.core_index = ['시작잔고', '예수금', '총평가금액', '총최대매입금액', '총매입금액', '총평가손익', '총손익', '추정자산', '총수익률', '총누적손익', '총누적수익률'] self.core_index = ['총누적손익', '총누적수익률', '총손익', '총수익률', '총평가손익', '총평가금액', '총매입금액', '추정자산', '총최대매입금액', '예수금', '시작잔고'] self.check_core_index() self.dbm = DBM('TopTrader') self.timestamp = None self.trading_history = th self.logger = TTlog().logger
def __init__(self, code): self.empty = True self.first_trading = True # 첫 거래인지 self.timestamp = None self.first_buy_time = None # if add/delete index, must update self.core_index self.timestamp = None self.code = code self.stock_name = cfg_mgr.STOCK_INFO[code]['stock_name'] self.현재가 = 0 self.매매수량 = 0 self.보유수량 = 0 self.매매금액 = 0 self.매입금액 = 0 self.최대매입금액 = 0 self.매입평균가 = 0.0 self.평가손익 = 0.0 self.실현손익 = 0 self.누적손익 = 0 self.평가금액 = 0.0 self.수익률 = 0.0 self.누적수익률 = 0.0 self.평가금액변동 = 0.0 self.매입금액변동 = 0.0 self.실현손익변동 = 0.0 self.core_index = [ 'timestamp', 'code', 'stock_name', '현재가', '매매수량', '보유수량', '매매금액', '매입금액', '최대매입금액', '매입평균가', '평가손익', '실현손익', '누적손익', '평가금액', '수익률', '누적수익률', '평가금액변동', '매입금액변동', '실현손익변동' ] self.check_core_index() self.time_series_sec1 = None self.logger = TTlog().logger self.dbm = DBM('TopTrader')
class TopTrader(QMainWindow, ui): def __init__(self): super().__init__() self.logger = TTlog().logger self.slack = Slack(config_manager.get_slack_token()) self.dbm = DBM('TopTrader') self.main() def complete_tick_data(self, date): return self.dbm.get_collect_tick_data_status(date, tick="1") == "END" def main(self): date = datetime(2018, 8, 2) with open("base_date_when_collect_tick_data.txt", "w") as f: f.write("{} {} {}\n".format(date.year, date.month, date.day)) while not self.complete_tick_data(date): os.system("python collect_1tick_data_real_condi_search.py")
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")
def __init__(self, condi_index, condi_name): self.condi_index = condi_index self.condi_name = condi_name self.dbm = DBM('TopTrader') self.disable_code_list = []
class ConditionalSearch(object): _inst = {} def __init__(self, condi_index, condi_name): self.condi_index = condi_index self.condi_name = condi_name self.dbm = DBM('TopTrader') self.disable_code_list = [] @classmethod def get_instance(cls, condi_index, condi_name): if condi_index not in cls._inst: cls._inst[condi_index] = ConditionalSearch(condi_index, condi_name) return cls._inst[condi_index] def set_disable_code_list(self, code_list): self.disable_code_list = code_list def detected_code_list(self, date): """특정일에 조건검색식으로부터 검출된 모든 code list 를 반환 :param data: :return: """ db_data = self.dbm.get_real_condi_search_data(date, self.condi_name) code_list = list(set([data['code'] for data in db_data])) if bool(self.disable_code_list): code_list = list(set(code_list) - set(self.disable_code_list)) code_list.sort() return code_list def get_stock_list(self, date): """특정일에 조건검색식으로부터 검출된 모든 stock list 를 반환 :param date: :return: """ code_list = self.detected_code_list(date) stock_list = [ Stock.get_instance(code) for code in code_list if code not in self.disable_code_list ] return stock_list def get_stock_list_at_timestamp(self, timestamp): """특정시간(timestamp)에 조건검색식으로부터 검출된 stock list를 반환 :param timestamp: :return: """ ret = [] for code, time_series in self.condi_hist.items(): if code in self.disable_code_list: continue if timestamp in time_series: ret.append(Stock.get_instance(code)) return ret def gen_condi_history(self, target_date): """조건검색식으로 부터 검색된 종목의 time series 정보를 생성 { code1: {t1: {현재가: xx, 거래량: xx}, t1: {현재가: xx, 거래량: xx}, .., t1: {현재가: xx, 거래량: xx}}, code2: {t1: {현재가: xx, 거래량: xx}, t1: {현재가: xx, 거래량: xx}, .., t1: {현재가: xx, 거래량: xx}} } :param target_date: :param condi_index: :return: """ db_data = self.dbm.get_real_condi_search_data(target_date, self.condi_name) self.condi_hist = defaultdict(list) for data in db_data: if data['code'] in self.disable_code_list: continue code, timestamp = data['code'], data['date'].replace(microsecond=0) self.condi_hist[code].append(timestamp) return self.condi_hist
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")
def __init__(self): super().__init__() self.logger = TTlog().logger self.slack = Slack(config_manager.get_slack_token()) self.dbm = DBM('TopTrader') self.main()
class Stock(object): """code당 1개의 객체(singleton/code)를 생성한다. """ _inst = {} def __init__(self, code): self.empty = True self.first_trading = True # 첫 거래인지 self.timestamp = None self.first_buy_time = None # if add/delete index, must update self.core_index self.timestamp = None self.code = code self.stock_name = cfg_mgr.STOCK_INFO[code]['stock_name'] self.현재가 = 0 self.매매수량 = 0 self.보유수량 = 0 self.매매금액 = 0 self.매입금액 = 0 self.최대매입금액 = 0 self.매입평균가 = 0.0 self.평가손익 = 0.0 self.실현손익 = 0 self.누적손익 = 0 self.평가금액 = 0.0 self.수익률 = 0.0 self.누적수익률 = 0.0 self.평가금액변동 = 0.0 self.매입금액변동 = 0.0 self.실현손익변동 = 0.0 self.core_index = [ 'timestamp', 'code', 'stock_name', '현재가', '매매수량', '보유수량', '매매금액', '매입금액', '최대매입금액', '매입평균가', '평가손익', '실현손익', '누적손익', '평가금액', '수익률', '누적수익률', '평가금액변동', '매입금액변동', '실현손익변동' ] self.check_core_index() self.time_series_sec1 = None self.logger = TTlog().logger self.dbm = DBM('TopTrader') def print_attr(self, trading_type, attr_list=None): if not cfg_mgr.STOCK_MONITOR: return self.logger.debug("\n" + ("-" * 100)) self.logger.debug("[Stock] Information : {}/{}".format( self.stock_name, self.code)) self.logger.debug("[Trading Type] -> {}-{}".format( trading_type, self.trading_reason)) if bool(attr_list): attr_val = [] for attr in attr_list: val = self.__getattribute__(attr) log_str = "{}: {}".format(attr, val) if isinstance(val, float): log_str = "{}: {:.2f}".format(attr, val) attr_val.append(log_str) self.logger.debug("\t".join(attr_val)) else: self.logger.debug(self.__repr__()) # pass def __repr__(self): core_index = self.core_index # log = ["{}: {}".format(attr, str(self.__getattribute__(attr))) for attr in core_index] log = [] for attr in core_index: val = self.__getattribute__(attr) log_str = "{}: {}".format(attr, val) if isinstance(val, float): log_str = "{}: {:.2f}".format(attr, val) log.append(log_str) return "\t".join(log) @classmethod def get_instance(cls, code): if code not in cls._inst: cls._inst[code] = Stock(code) return cls._inst[code] @classmethod def get_new_instance(cls, code, recycle_time_series=False): if code in cls._inst and recycle_time_series: time_series_sec1 = cls._inst[code].time_series_sec1 cls._inst[code] = Stock(code) cls._inst[code].time_series_sec1 = time_series_sec1 else: cls._inst[code] = Stock(code) return cls._inst[code] def get_holding_period(self, timestamp=None): """최초 해당 주식을 보유한 시간으로부터 경과된 시간을 반환한다. :return: """ if not bool(timestamp): timestamp = self.timestamp if not bool(self.first_buy_time) or timestamp <= self.first_buy_time: return timedelta(seconds=0) return timestamp - self.first_buy_time def bep(self, event, price, amount=None): """Backup/Evaluate/PostAction prev : 기존 데이터 :return: """ # Backup self.backup() # dispatch Evaluate function eval_fn = self.__getattribute__("evaluate_{}".format(event)) eval_fn(**{'price': price, 'amount': amount}) # dispatch Post function post_fn = self.__getattribute__("post_{}".format(event)) post_fn(**{'price': price, 'amount': amount}) # Update def backup(self): """중요 지표들을 모두 백업한다. 백업 지표는 앞에 '기존' 키워드가 붙는다. :return: """ core_index = [ '현재가', '매매수량', '보유수량', '매매금액', '매입금액', '최대매입금액', '매입평균가', '평가손익', '실현손익', '누적손익', '평가금액', '수익률', '누적수익률' ] for index in core_index: val = self.__getattribute__(index) self.__setattr__('기존' + index, val) def evaluate_buy(self, **kwargs): price, amount = kwargs['price'], kwargs['amount'] self.현재가 = price self.매매수량 = amount self.보유수량 = self.기존보유수량 + self.매매수량 self.매매금액 = self.현재가 * self.매매수량 self.매입금액 = self.기존매입금액 + self.매매금액 self.매입금액변동 = self.매입금액 - self.기존매입금액 self.최대매입금액 = max(self.최대매입금액, self.매입금액) self.매입평균가 = self.매입금액 / self.보유수량 self.평가손익 = (self.현재가 - self.매입평균가) * self.보유수량 # self.실현손익 = self.실현손익 self.실현손익변동 = 0 # self.누적손익 = self.누적손익 self.평가금액 = self.현재가 * self.보유수량 if self.보유수량 == 0: self.수익률 = 0.0 else: self.수익률 = round((self.평가금액 - self.매입금액) / self.매입금액 * 100, 2) self.누적수익률 = round(float(self.누적손익) / self.최대매입금액 * 100, 2) self.평가금액변동 = self.평가금액 - self.기존평가금액 if self.first_trading: self.first_buy_time = self.timestamp self.first_trading = False def post_buy(self, **kwargs): price, amount = kwargs['price'], kwargs['amount'] core_index = [ 'timestamp', '현재가', '매입평균가', '수익률', '누적수익률', '누적손익', '매매수량', '보유수량', '매입금액', '최대매입금액', '평가손익', '실현손익', '평가금액', '매매금액' ] self.print_attr('BUY', core_index) # pdb.set_trace() def evaluate_sell(self, **kwargs): price, amount = kwargs['price'], kwargs['amount'] self.현재가 = price self.매매수량 = amount self.보유수량 = self.기존보유수량 - self.매매수량 self.매매금액 = self.현재가 * self.매매수량 self.매입금액 = self.기존매입평균가 * self.보유수량 self.매입금액변동 = self.매입금액 - self.기존매입금액 self.최대매입금액 = max(self.최대매입금액, self.매입금액) # self.매입평균가 = self.매입평균가 self.평가손익 = (self.현재가 - self.매입평균가) * self.보유수량 self.실현손익 = (self.현재가 - self.매입평균가) * self.매매수량 self.실현손익변동 = self.실현손익 - self.기존실현손익 self.누적손익 += self.실현손익 self.평가금액 = self.현재가 * self.보유수량 # self.기존수익률 = round((self.기존평가금액 - self.기존매입금액) / self.기존매입금액 * 100, 2) if self.보유수량 == 0: self.수익률 = 0.0 else: self.수익률 = round((self.평가금액 - self.매입금액) / self.매입금액 * 100, 2) self.누적수익률 = round(float(self.누적손익) / self.최대매입금액 * 100, 2) self.평가금액변동 = self.평가금액 - self.기존평가금액 if self.보유수량 == 0: self.first_trading = True self.first_buy_time = None def post_sell(self, **kwargs): price, amount = kwargs['price'], kwargs['amount'] core_index = [ 'timestamp', '현재가', '매입평균가', '실현손익', '기존수익률', '기존누적수익률', '누적손익', '매매수량', '보유수량', '매입금액', '최대매입금액', '평가손익', '평가금액', '매매금액' ] self.print_attr('SELL', core_index) # pdb.set_trace() def evaluate_change_price(self, **kwargs): price, amount = kwargs['price'], 0 self.현재가 = price self.매매수량 = amount # self.보유수량 = self.기존보유수량 - self.매매수량 self.매매금액 = 0 # self.매입금액 = self.기존매입평균가 * self.보유수량 # self.최대매입금액 = max(self.최대매입금액, self.매입금액) # self.매입평균가 = self.매입평균가 self.평가손익 = (self.현재가 - self.매입평균가) * self.보유수량 # self.실현손익 = (self.현재가 - self.매입평균가) * self.매매수량 # self.누적손익 += self.실현손익 self.평가금액 = self.현재가 * self.보유수량 if self.보유수량 == 0: self.수익률 = 0.0 else: self.수익률 = round((self.평가금액 - self.매입금액) / self.매입금액 * 100, 2) # self.누적수익률 = round(float(self.누적손익) / self.최대매입금액 * 100, 2) self.평가금액변동 = self.평가금액 - self.기존평가금액 def post_change_price(self, **kwargs): price, amount = kwargs['price'], 0 core_index = [ '현재가', '매매수량', '보유수량', '매매금액', '매입금액', '최대매입금액', '매입평균가', '평가손익', '실현손익', '누적손익', '평가금액', '수익률', '누적수익률' ] # self.print_attr('CHANGE PRICE') @common.type_check def update_sell(self, price_per_stock: int, amount: int): """현재가에 amount 만큼 매도를 하여, 내부 정보를 업데이트 한다. :param amount: :return: """ self.bep('sell', price_per_stock, amount) @common.type_check def update_buy(self, price_per_stock: int, amount: int): """해당 주식을 매수하였을 경우, 관련 지표를 업데이트 :param price_per_stock: :param amount: :return: """ self.bep('buy', price_per_stock, amount) def update_stock_value(self, timestamp): """해당 주식의 현재가가 변경되었을 경우, 관련 지표를 업데이트 :param timestamp: :return: """ self.timestamp = timestamp 현재가 = self.time_series_sec1.ix[timestamp]['현재가'] self.bep('change_price', 현재가) def set_strategy(self, strg): """ :param strg: :return: """ self.strg = strg def gen_time_series_sec1(self, target_date): """특정종목 특정일의 초단위 tick_data(DataFrame 객체)를 생성한다. timestamp 현재가 volumn 2018-08-02 09:00:00 0.0 0.0 2018-08-02 09:00:01 15000.0 130.0 2018-08-02 09:00:02 15000.0 91.0 2018-08-02 09:00:03 15500.0 0.0 ...(생략) :param target_date: :return: """ if self.time_series_sec1 is not None: self.logger.info( "{}/{} use existing gen_time_series_sec1..".format( self.stock_name, self.code)) return self.time_series_sec1 self.logger.info("{}/{} gen_time_series_sec1..".format( self.stock_name, self.code)) 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) df = pd.DataFrame( self.dbm.get_tick_data(self.code, target_date, tick="1")) ts_group = df.groupby('timestamp') price = pd.DataFrame(ts_group.max()['현재가']) index = pd.date_range(s_time, e_time, freq='S') price = price.reindex(index, method='ffill', fill_value=0) # volumn = pd.DataFrame(ts_group.sum()['거래량']) # volumn = volumn.reindex(index, method='ffill', fill_value=0) # price['volumn'] = volumn # index = timestamp (freq=second) # 현재가 = max, ffill, fill_value=0 # 거래량 = sum, ffill, fill_value=0 self.time_series_sec1 = price return self.time_series_sec1 def get_curr_price(self, timestamp): """현 시점(timestamp)의 주가를 반환한다. :param timestamp: :return: """ if self.time_series_sec1 is None: y, m, d = timestamp.year, timestamp.month, timestamp.day self.time_series_sec1 = self.gen_time_series_sec1(datetime( y, m, d)) return self.time_series_sec1.ix[timestamp]['현재가'] def get_core_index(self): """Stock객체의 핵심 지표 리스트. 반드시 Stock객체의 속성값과 동기화가 되어야 함. :return: """ return self.core_index def check_core_index(self): """ :return: """ for index in self.get_core_index(): self.__getattribute__(index)