def print_parameter(prefix, xxx_todo_changeme): (math_expect, stocks_cnt, ops_cnt, avg_hold_days, stop_rate, days) = xxx_todo_changeme log.info( '%s: stop_rate %f%%, continue days %d, ' 'math expect: %f%%, stocks count: %d, operations count: %d, avg hold days: %f', prefix, stop_rate * 100, days, math_expect * 100, stocks_cnt, ops_cnt, avg_hold_days)
def _fetch_stocks(self): log.info("Fetch stocks from web") stocks = ts.get_stock_basics() with create_pool('fetch stocks') as pool: ret = pool.map(build_stock, [(i, stock) for i, stock in enumerate(stocks.iterrows())]) ret = [x for x in ret if x is not None] return ret
def fetch_stocks(self): if os.path.isfile(self.persist_f): stocks = self.read_stocks_from_persist() else: stocks = self._fetch_stocks() self.persist_stocks(stocks) log.info('Fetched all stocks') return self.process_stocks(stocks)
def print_loopback_result(self, debug=False): benefit_rate, ops = self.get_loopback_result() log.info('>>> %s %s: %+.2f%%', self.code, self.name, benefit_rate * 100) if debug: output_log = log.debug else: output_log = log.info for op in ops: output_log(op)
def fetch_basis(): log.info('Fetching stock basis...') pro = ts.pro_api( '4105aca09e41fde2adac11ff8cdf7e05cef205d946e06935562e0010') ret = pro.stock_basic(exchange='', list_status='L', fields='ts_code,symbol,name,area,industry,list_date') log.info('Fetched') df = ret[['ts_code', 'name']] df = df.set_index('ts_code') s = df.to_json(orient='index') return json.loads(s)
def terminate_pool_and_exit(signum, frame): global g_pool log.warn('Handle signal') if g_pool is not None: log.info('Closing pool...') for p in g_pool._pool: os.kill(p.pid, signal.SIGKILL) # .is_alive() will reap dead process while any(p.is_alive() for p in g_pool._pool): pass g_pool.terminate() g_pool.join() exit(1)
def find_chances(from_date, to_date, highest_days_n): def _in_list(code, l): for c, _ in l: if code == c: return True return False # customize js = get_customize_codes() log.info('customize stocks: %s', js) codes = js for code in get_codes(ts.get_hs300s()): if _in_list(code, codes): continue else: codes.append((code, None)) rets = [] cur_pos_rets = [] with ThreadPoolExecutor(max_workers=4) as executor: tasks = [ executor.submit(_loopback_stock, code, name, from_date, to_date, highest_days_n) for code, name in codes ] for task in as_completed(tasks): stock, is_chance, cur_pos = task.result() if is_chance: rets.append(stock) if cur_pos <= 0.1: cur_pos_rets.append((cur_pos, stock)) rets.sort(key=lambda s: s.get_benefit_rate(), reverse=True) log.info('==========Your chances==========') for stock in rets: log.info(stock) cur_pos_rets.sort(key=lambda s: s[0]) log.info('==========Underestimate==========') for _, stock in cur_pos_rets: log.info(stock) return rets, cur_pos_rets
def loop_verify(loopback, from_date): log.info('loop verify') loopback.from_date = from_date loopback.to_date = None stocks = [] total_benefit = 0.0 for stock in loopback.stocks: try: if stock.get_benefit() <= 0.0: break loopback.test_loopback_one(stock) stocks.append(stock) total_benefit += stock.get_benefit() except Exception as e: pass math_expt = total_benefit / len(stocks) loopback.plot_benefit("Math expt : %f" % math_expt, stocks)
def best_stocks(self, stocks, filt=None): period = 'from %s to %s' % (self.from_date, self.to_date if self.to_date else 'now') log.info('Best stocks %s, trade days: %d', period, self.trade_days()) self.print_loopback_condition() if filt: stocks = list(filter(filt, stocks)) log.info('Filter: %s', filt.__doc__) self.loopback(stocks) purchased_stocks = stocks # We only consider the stock we really purchased purchased_stocks = [ x for x in purchased_stocks if x.loopback_result is not None and x.loopback_result.ops ] purchased_stocks = sorted(purchased_stocks, key=lambda x: x.loopback_result.benefit, reverse=True) stocks = [] benefits = [] # FIXME: for stock in purchased_stocks: if stock.get_ops(): stock.print_loopback_result(debug=True) stocks.append(stock) benefits.append(stock.get_benefit_rate()) math_expt = avg(benefits) # avg_hold_days = avg(hold_days) log.info('Benefit mathematical expectation: %.2f%% for %d stocks', math_expt * 100, len(stocks)) # self.plot_benefit("%s Math expt: %f" % (period, math_expt), stocks) # plot_hist(sorted_stocks) self.where_is_my_chance(purchased_stocks)
def where_is_my_chance(self, stocks): log.info('=====Your chance=====') for stock in stocks: if self.is_chance_for(stock): log.info('%s', stock) stock.print_loopback_result()
def print_loopback_condition(self): log.info('>>>>Loopback condition<<<<') log.info('trend start from highest in %d days', self.highest_day_n) log.info('steps: %s', self.buy_steps) log.info('step buy ratio: %.2f%%', self.step_ratio * 100) log.info('step exit ratio: %.2f%%', self.step_exit_ratio * 100) log.info('stop condition: %.2f%% downside %s', self.stop_down_ratio_of_ma * 100, self.stop_ma) log.info('>>>>>>>>>>>>><<<<<<<<<<<<<')
def process_stocks(self, stocks): with create_pool('process stocks') as pool: stocks = pool.map(process_stock, stocks) log.info('Processed all stocks') return stocks
def persist_stocks(self, data): log.info("Persist stocks to file: %s", self.persist_f) os.makedirs(os.path.dirname(self.persist_f), exist_ok=True) with open(self.persist_f, 'wb') as f: pickle.dump(data, f)
def read_stocks_from_persist(self): log.info("Read stocks from file:%s", self.persist_f) with open(self.persist_f, 'rb') as f: return pickle.load(f)