def start_loop(): # 更新时间 hour = 18 rdinfo = redisRW.redisrw(redisRW.db_info) # 上次入库时间 update_time = rdinfo.read_dec_datetime('update') if update_time is not None: last_up_date = update_time['datetime'] now_date = datetime.datetime.now() diff_days = (now_date.date() - last_up_date.date()).days if diff_days > 1 or (diff_days == 1 and last_up_date.hour < hour): last_up_date = now_date update(rdinfo, last_up_date) else: last_up_date = datetime.datetime.now() update(rdinfo, last_up_date) while True: now_date = datetime.datetime.now() if now_date.hour >= hour: # 只有在今天指定时间更新才有效 if last_up_date.date() < now_date.date( ) or last_up_date.hour < hour: last_up_date = now_date update(rdinfo, last_up_date) if comm.is_trade_time(): global commobj print('登陆交易终端', rpcTrade.login()) # 清空数据 redisRW.redisrw(redisRW.db_backtest_chicang).del_db() redisRW.redisrw(redisRW.db_sell).del_db() runQuotation.start_quotation_process(commobj) print('结束交易终端', rpcTrade.kill()) time.sleep(5)
def start_quotation_process(commobj, back_test_date: datetime.datetime = None, process_count=3): # 交易时间不允许回放行情 if commobj.is_backtest and comm.is_trade_time(): return rdxg = redisRW.redisrw(redisRW.db_xg) rdsell = redisRW.redisrw(redisRW.db_sell) rdsell.del_db() # 读取选股数据 xg_data_list = rdxg.read_all_dec() if len(xg_data_list) == 0: print('没有选股数据') wait_trade_time_end() return # 清空数据 redisRW.redisrw(redisRW.db_realtime_tick).del_db() rdmainquotation = redisRW.redisrw(redisRW.db_mainquotaion) rdmainquotation.del_db() # 数据分块 bk = math.ceil(len(xg_data_list) / process_count) bk_data_list = [] temp = [] p_list = [] for i in range(len(xg_data_list)): if i > 0 and i % bk == 0: bk_data_list.append(temp) temp = [] temp.append(xg_data_list[i]) if len(temp) > 0: bk_data_list.append(temp) if back_test_date is None: tdx = dataTdx.DataTdx() # 可用服务器 addrs_list_info = tdx.get_sort_address_info() addr_ky_count = len(addrs_list_info) if addr_ky_count == 0: print('没有可用服务器。') wait_trade_time_end() return print('可用服务器', addr_ky_count, '最大延时', addrs_list_info[addr_ky_count - 1][3], 'ms') # 启动通达信实时行情进程 for b in bk_data_list: p = Process(target=c_ths_tdx, args=(commobj, addrs_list_info, b)) p_list.append(p) p.start() else: # 启动回测行情模拟进程 for b in bk_data_list: p = Process(target=c_ths_back_test, args=(commobj, back_test_date, b)) p_list.append(p) p.start() print('行情服务已启动,选股数量', len(xg_data_list)) for p in p_list: p.join() print('行情服务结束。')
def backtest_start(commobj, start_date: datetime.datetime, end_date: datetime.datetime): """ 回测 """ rdchicang = redisRW.redisrw(redisRW.db_backtest_chicang) rdchicang.del_db() rddaysell = redisRW.redisrw(redisRW.db_day_sell) rddaysell.del_db() # 日线回测 commobj.testbar = True zbstrategy = zbStrategy.Strategy(None) while start_date.date() <= end_date.date(): if start_date.weekday() in range(5): # 选股 zbstrategy.stock_select(rdchicang, start_date) get_ticks_from_xg_and_start_backtest(commobj, start_date) #input('按任意键继续...') start_date += datetime.timedelta(days=1) ex_buy_count = 0 day_sj_zdf_count = Decimal(0) ex_zdf_count = Decimal(0) sz_count = 0 xd_count = 0 ex_sz_count = 0 ex_xd_count = 0 datas = [] max_zyk = None max_huice = None for d in rddaysell.read_l_date_dec_json('daysell', 0, -1): ex_buy_count += d['buy_count'] ex_sz_count += d['sz'] ex_xd_count += d['xd'] zdf = d['sj_zdf_count'] if (max_zyk is None) or d['zyk'] > max_zyk: max_zyk = d['zyk'] huice = d['zyk'] - max_zyk if (max_huice is None) or huice < max_huice: max_huice = huice if zdf > 0: sz_count += 1 else: xd_count += 1 day_sj_zdf_count += zdf ex_zdf_count += d['ex_zdf_count'] datas.append({ 'datetime': d['datetime'], 'ex_buy_count': ex_buy_count, 'ex_zdf_count': float(str(ex_zdf_count.quantize(Decimal('0.01'), ROUND_HALF_UP))), 'day_sj_zdf_count': float(str(day_sj_zdf_count.quantize(Decimal('0.01'), ROUND_HALF_UP))), 'zyk': float(str(d['zyk'].quantize(Decimal('0.01'), ROUND_HALF_UP))), 'day_sz': sz_count, 'day_xd': xd_count, 'ex_sz_count': ex_sz_count, 'ex_xd_count': ex_xd_count }) ply.write_html_tol('./WebServer/html/charts.html', datas, max_huice)
def main(): global commobj if len(sys.argv) > 1 and sys.argv[1] == 'b': commobj = comm.commObj(redisRW.redisrw(redisRW.db_backtest_chicang), Decimal('1000000'), is_backtest=True) print('进入回测系统。可用资金:', commobj.balance) else: commobj = comm.commObj(redisRW.redisrw(redisRW.db_chicang), Decimal(rpcTrade.get_ky_balance()), is_backtest=False) print('进入实盘系统。可用资金:', commobj.balance) Process(target=runWeb.main, args=(commobj, )).start() start_loop()
def c_ths_tdx(lockobj, addrs_list_info, xg_data_list): ths_list = [] addr_ky_count = len(addrs_list_info) addrs_sleep_time = {} for ad in addrs_list_info: addrs_sleep_time[ad[1]] = 0.0 rdkline = redisRW.redisrw(redisRW.db_kline) addr_index = 0 for xg_data in xg_data_list: # 把K线合并到选股数据中 code = xg_data['code'] klines = rdkline.read_l_dec(code, 0, 0) if len(klines) == 0: continue xg_data['kline'] = klines[0] ip = addrs_list_info[addr_index][1] port = addrs_list_info[addr_index][2] th = threading.Thread(target=th_tdx_run, args=(lockobj, ip, port, xg_data, addrs_sleep_time[ip])) ths_list.append(th) addr_index += 1 if addr_index >= addr_ky_count: addr_index = 0 addrs_sleep_time[ip] += 0.5 for th in ths_list: th.start() m = sorted(addrs_sleep_time.items(), key=lambda x: x[1], reverse=True) print('任务报告', os.getpid(), len(ths_list), '个线程启动完毕。最后开始时间', m[0][1], '秒。') for th in ths_list: th.join()
def xg_data(code, name, avg_line_zdf, zs_date, zy_date, price_zs, price_zy, chicang={}): # 行业信息 rdhangye = redisRW.redisrw(redisRW.db_hangye) hy = rdhangye.read_dec(code) if hy is None: hy = {'hangye': ''} return { 'code': code, 'name': name, 'hangye': hy['hangye'], 'avg_line_zdf': avg_line_zdf, 'chicang': chicang, 'bz': 0, 'zs_date': zs_date, 'zy_date': zy_date, 'price_zy': price_zy, 'price_zs': price_zs }
def c_ths_back_test(lockobj, back_test_date, xg_data_list): tdx = dataTdx.DataTdx() tdx.select_fast_addr() ths_list = [] rdkline = redisRW.redisrw(redisRW.db_kline) for xg_data in xg_data_list: # 把K线合并到选股数据中 code = xg_data['code'] klines = rdkline.read_klines_from_before_date_count_dec( code, back_test_date, 1) if len(klines) == 0: continue xg_data['kline'] = klines[0] data_ticks = tdx.get_history_ticks( code, datetime.datetime.strptime(klines[0]['datetime'], '%Y%m%d')) ticks_len = len(data_ticks) if (data_ticks is None) or ticks_len == 0: return close_tick = data_ticks[ticks_len - 1] xg_data['amount_open'] = Decimal(str(close_tick['amount_open'])) th = threading.Thread(target=th_back_test_run, args=(lockobj, xg_data)) ths_list.append(th) #break for th in ths_list: th.start() print('任务报告', os.getpid(), len(ths_list), '个线程启动完毕。') for th in ths_list: th.join()
def sell(self, tick): if not self.common['lock'].acquire(timeout=0.1): return False if self.common['b']: rdchicang = redisRW.redisrw(redisRW.db_backtest_chicang) else: rdchicang = redisRW.redisrw(redisRW.db_chicang) cc_tol = 0 cc_amount = Decimal(0) cc_price = Decimal(0) try: rdsell = redisRW.redisrw(redisRW.db_sell) code = tick['code'] tick_chicang = tick['chicang'] trade_date = tick['datetime'] price = tick['price'] cc_tol = tick_chicang['tol'] cc_price = price cc_amount = comm.sell_money_from_tol(code, cc_price, cc_tol) if not self.common['b']: r = httpTrade.sell(code, tick['name'], price, tick_chicang['tol']) if r: print('卖出下单成功') if cc_tol > 0: # 可用金额 self.common['balance'] += cc_amount tick_chicang['tol'] -= cc_tol if tick_chicang['tol'] == 0: tick_chicang['status'] = 1 tick_chicang['sell_price'] = cc_price zdf = (cc_price / tick_chicang['price'] - 1) * 100 if not rdchicang.delete(code): print(code, '删除持仓数据错误。') rdsell.write_json( code, { 'code': code, 'datetime': trade_date, 'price': cc_price, 'money': cc_amount, 'zdf': zdf }) return True finally: self.common['lock'].release()
def _xg_hot_p(self, rdchicang, codes_info, date: datetime = None): """ 选股-热点股票 date 从指定日期开始选股,不指定则为最新 """ # 分析的历史根数 count_week = 1 count = 2 count_short = 15 rdkline = redisRW.redisrw(redisRW.db_kline) rdfinance = redisRW.redisrw(redisRW.db_finance) rdxg = redisRW.redisrw(redisRW.db_xg) rdindex = redisRW.redisrw(redisRW.db_index) for d in codes_info: code = d['code'] if date is not None: klines = rdkline.read_klines_from_before_date_count_dec( code, date, count) else: klines = rdkline.read_klines_from_count_dec(code, count) # 持仓 cc_data = rdchicang.read_dec(d['code']) if cc_data: # 重设价格 price = rdkline.read_klines_from_date_dec( code, datetime.datetime.strptime(cc_data['chicang']['datetime'], '%Y%m%d %H:%M:%S'))[0]['open'] cc_data['chicang']['price'] = price # 更新市值 cc_data['chicang']['marketValue'] = comm.sell_money_from_tol( code, klines[0]['close'], cc_data['chicang']['tol']) rdchicang.delete(d['code']) rdchicang.write_json(d['code'], cc_data) continue if len(klines) == 0: continue tj = klines[0]['pctChg'] > 0.1 and \ klines[0]['ma_5'] > klines[1]['ma_5'] if not tj: continue r_data = comm.xg_data(code, d['name'], 0, None, None, None, None) if r_data and (rdxg.read_str(code) is None): if not rdxg.write_json(code, r_data): print(code, '选股数据写入错误。')
def fupan(): # 选股 zbstrategy = zbStrategy.Strategy(None) zbstrategy.stock_select(redisRW.redisrw(redisRW.db_chicang)) tk_date = datetime.datetime.now() # 获取最新一天的ticks,并启动回测 commobj = comm.commObj(redisRW.redisrw(redisRW.db_backtest_chicang), 1, is_backtest=True) getticks = runQuotation.get_ticks_from_xg_and_start_backtest( commobj, tk_date) while not getticks: print(tk_date, '没有ticks,尝试前一天。') tk_date -= datetime.timedelta(days=1) getticks = runQuotation.get_ticks_from_xg_and_start_backtest( commobj, tk_date) print('策略提示', '将买入标记重点的股票。') return True
def __init__(self, commObj, xg_data): self.ticks = [] self.xg_data = xg_data self.code = xg_data['code'] self.name = xg_data['name'] self.hangye = xg_data['hangye'] self.chicang = xg_data['chicang'] if self.chicang: self.chicang['datetime'] = datetime.datetime.strptime( self.chicang['datetime'], '%Y%m%d %H:%M:%S') self.bz = xg_data['bz'] self.price_zs = xg_data['price_zs'] self.price_zy = xg_data['price_zy'] self.zs_date = xg_data['zs_date'] self.zy_date = xg_data['zy_date'] self.strategy = zbStrategy.Strategy(commObj) self.rdrealtimetick = redisRW.redisrw(redisRW.db_realtime_tick) self.rdmainquotation = redisRW.redisrw(redisRW.db_mainquotaion) self.history_data = zbBase.history_calculate_by_kline(xg_data)
def xg_data(code, name, chicang={}): # 行业信息 rdhangye = redisRW.redisrw(redisRW.db_hangye) hy = rdhangye.read_dec(code) if hy is None: hy = {'hangye': ''} return { 'code': code, 'name': name, 'hangye': hy['hangye'], 'chicang': chicang, }
def _get_sz_index_kline(start_date: datetime.date): rdindex = redisRW.redisrw(redisRW.db_index) rdindex.delete(comm.index_sz_code) klines = dataBaostock.get_kline_index_from_start_date( comm.index_sz_code, start_date) k_len = len(klines) if k_len == 0: raise Exception('指数K线获取错误。') # 计算 zbKline.klines_calculate(comm.index_sz_code, klines) if k_len != rdindex.wirte_l_datas(comm.index_sz_code, klines): raise Exception('指数K线存储错误。')
def stock_select(self, is_backtest, codes_bk, date: datetime = None): rdxg = redisRW.redisrw(redisRW.db_xg) rdxg.del_db() p_list = [] for b in codes_bk: p = Process(target=self._stock_select, args=(is_backtest, b, date)) p_list.append(p) p.start() tm = datetime.datetime.now() print('正在选股...') for p in p_list: p.join() if is_backtest: rdchicang = redisRW.redisrw(redisRW.db_backtest_chicang) else: rdchicang = redisRW.redisrw(redisRW.db_chicang) # 持仓 for d in rdchicang.read_all_dec(): rdxg.write_json(d['code'], d) print(datetime.datetime.now() - tm) print('被选股票', len(rdxg.read_codes()), '其中持仓', len(rdchicang.read_codes()))
def stock_select(self, rdchicang, date: datetime = None): rdxg = redisRW.redisrw(redisRW.db_xg) rdxg.del_db() # 实例化通达信对象 tdx = dataTdx.DataTdx() tdx.select_fast_addr() # 读取市场股票 codes_info = tdx.get_szsh_a_codes() # 数据分块 process_count = 4 bk = math.ceil(len(codes_info) / process_count) bk_data_list = [] temp = [] p_list = [] for i in range(len(codes_info)): if i > 0 and i % bk == 0: bk_data_list.append(temp) temp = [] temp.append(codes_info[i]) if len(temp) > 0: bk_data_list.append(temp) for b in bk_data_list: p = Process(target=self._xg_hot_p, args=(rdchicang, b, date)) p_list.append(p) p.start() tm = datetime.datetime.now() print('正在选股...') for p in p_list: p.join() # 只选择3只 """top_xg = [] for d in rdxg.read_all_dec(): top_xg.append(d) rdxg.delete(d['code']) top_xg = sorted(top_xg, key=lambda x: x['avg_line_zdf'], reverse=False) cc_len = len(rdchicang.read_codes()) i = 0 for d in top_xg: if not rdxg.write_json(d['code'], d): print(d['code'], '选股数据写入错误。') i += 1 # 只选择3只 if i == 3 - cc_len: break""" # 持仓 for d in rdchicang.read_all_dec(): rdxg.write_json(d['code'], d) print(datetime.datetime.now() - tm) print('被选股票', len(rdxg.read_codes()), '其中持仓', len(rdchicang.read_codes()))
def c_ths_tdx(lockobj, addrs_list_info, xg_data_list): tdx = dataTdx.DataTdx() tdx.select_fast_addr() ths_list = [] addr_ky_count = len(addrs_list_info) addrs_sleep_time = {} for ad in addrs_list_info: addrs_sleep_time[ad[1]] = 0.0 rdkline = redisRW.redisrw(redisRW.db_kline) addr_index = 0 for xg_data in xg_data_list: # 把K线合并到选股数据中 code = xg_data['code'] klines = rdkline.read_l_dec(code, 0, 0) if len(klines) == 0: continue xg_data['kline'] = klines[0] # 前一天ticks data_ticks = tdx.get_history_ticks(code, datetime.datetime.strptime(klines[0]['datetime'], '%Y%m%d')) ticks_len = len(data_ticks) if (data_ticks is None) or ticks_len == 0: print('前一天tick获取错误。', code) continue close_tick = data_ticks[ticks_len - 1] xg_data['amount_open'] = Decimal(str(close_tick['amount_open'])) ip = addrs_list_info[addr_index][1] port = addrs_list_info[addr_index][2] th = threading.Thread(target=th_tdx_run, args=(lockobj, ip, port, xg_data, addrs_sleep_time[ip])) ths_list.append(th) addr_index += 1 if addr_index >= addr_ky_count: addr_index = 0 addrs_sleep_time[ip] += 0.5 for th in ths_list: th.start() m = sorted(addrs_sleep_time.items(), key=lambda x: x[1], reverse=True) print('任务报告', os.getpid(), len(ths_list), '个线程启动完毕。最后开始时间', m[0][1], '秒。') for th in ths_list: th.join()
def c_ths_back_test(lockobj, back_test_date, xg_data_list): ths_list = [] rdkline = redisRW.redisrw(redisRW.db_kline) for xg_data in xg_data_list: # 把K线合并到选股数据中 code = xg_data['code'] klines = rdkline.read_klines_from_before_date_count_dec( code, back_test_date, 1) if len(klines) == 0: continue xg_data['kline'] = klines[0] th = threading.Thread(target=th_back_test_run, args=(lockobj, xg_data)) ths_list.append(th) #break for th in ths_list: th.start() print('任务报告', os.getpid(), len(ths_list), '个线程启动完毕。') for th in ths_list: th.join()
def _stock_select(self, is_backtest, codes_info, date: datetime = None): """ 选股 date 从指定日期开始选股,不指定则为最新 """ # 分析的历史根数 count_week = 1 count = 2 count_short = 15 rdkline = redisRW.redisrw(redisRW.db_kline) rdfinance = redisRW.redisrw(redisRW.db_finance) rdxg = redisRW.redisrw(redisRW.db_xg) rdindex = redisRW.redisrw(redisRW.db_index) if is_backtest: rdchicang = redisRW.redisrw(redisRW.db_backtest_chicang) else: rdchicang = redisRW.redisrw(redisRW.db_chicang) for d in codes_info: code = d['code'] if date is not None: klines = rdkline.read_klines_from_before_date_count_dec( code, date, count) else: klines = rdkline.read_klines_from_count_dec(code, count) # 持仓 cc_data = rdchicang.read_dec(d['code']) if cc_data: # 重设价格 #price = rdkline.read_klines_from_date_dec(code, datetime.datetime.strptime(cc_data['chicang']['datetime'], '%Y%m%d %H:%M:%S'))[0]['open'] #cc_data['chicang']['price'] = price # 更新市值 cc_data['chicang']['marketValue'] = comm.sell_money_from_tol( code, klines[0]['close'], cc_data['chicang']['tol']) rdchicang.delete(d['code']) rdchicang.write_json(d['code'], cc_data) continue if len(klines) == 0: continue tj = (klines[0]['dif_c_dea'] == 1 and klines[0]['ma_5'] > klines[1]['ma_5']) if not tj: continue r_data = comm.xg_data(code, d['name']) if not rdxg.write_json(code, r_data): print(code, '选股数据写入错误。')
def __init__(self, push, code): self.push = push self.rdbacktest = redisRW.redisrw(redisRW.db_backtest_tick) self.rdmainquotation = redisRW.redisrw(redisRW.db_mainquotaion) self.code = code
def buy(self, tick, fg_data): if not self.common['lock'].acquire(timeout=0.1): return False if self.common['b']: rdchicang = redisRW.redisrw(redisRW.db_backtest_chicang) else: rdchicang = redisRW.redisrw(redisRW.db_chicang) try: cc_tol = 0 cc_amount = Decimal(0) cc_price = Decimal(0) code = tick['code'] tick_chicang = tick['chicang'] trade_date = tick['datetime'] price = tick['price'] cangwei = fg_data['cangwei'] cc_max = fg_data['cc_max'] # 加仓 cc_data = rdchicang.read_dec(code) # 新开仓 if not cc_data: if len(rdchicang.read_codes()) >= cc_max: return False buy_tol = comm.buy_tol_from_money(code, self.common['balance'], price, cangwei) if buy_tol is None: #print('余额不足。') return False cc_price = price cc_tol = buy_tol cc_amount = comm.sell_money_from_tol(code, cc_price, cc_tol, False) if not self.common['b']: r = httpTrade.buy(code, tick['name'], price, buy_tol) if r: print('买入下单成功') if cc_tol > 0: # 可用金额 self.common['balance'] -= cc_amount chicang = { 'code': code, 'datetime': trade_date, 'price': cc_price, 'tol': cc_tol, 'marketValue': cc_amount, 'status': 0 } # 加仓 if cc_data: c = cc_data['chicang'] all_tol = c['tol'] + cc_tol chicang['price'] = ( (c['price'] * c['tol'] + cc_tol * cc_price) / all_tol).quantize(Decimal('0.01'), ROUND_HALF_UP) chicang['tol'] = all_tol chicang['marketValue'] = comm.sell_money_from_tol( code, chicang['price'], chicang['tol'], False) if not rdchicang.delete(code): print(code, '删除持仓数据错误。') for k in fg_data.keys(): if k not in ['cangwei', 'price_buy']: chicang[k] = fg_data[k] for k in chicang.keys(): tick_chicang[k] = chicang[k] r_data = comm.xg_data(code, tick['name'], chicang) rdchicang.write_json(code, r_data) return True finally: self.common['lock'].release()
def get_ticks_from_xg_and_start_backtest(commobj, back_test_date: datetime.datetime): """ 回测初始化 """ rdbacktest = redisRW.redisrw(redisRW.db_backtest_tick) rdbacktest.del_db() rdxg = redisRW.redisrw(redisRW.db_xg) rdkline = redisRW.redisrw(redisRW.db_kline) xg_codes = rdxg.read_codes() if len(xg_codes) == 0: print(back_test_date, '没有选股数据。') return True # 存储当天tick数据 bar = progressBar.progressbar() bar.start('存储tick数据', len(xg_codes)) for code in xg_codes: bar.progress() if commobj.testbar: ticks = rdkline.read_klines_from_date_dec(code, back_test_date) else: ticks = dataAkshare.get_ticks(code, back_test_date) if len(ticks) == 0: continue if commobj.testbar: ticks[0]['code'] = code ticks[0]['price'] = ticks[0]['open'] ticks[0]['buyorsell'] = 0 ticks[0]['num'] = 0 ticks[0]['vol'] = ticks[0]['volume'] ticks.append(ticks[0].copy()) ticks[1]['price'] = ticks[1]['close'] ticks[1]['vol'] = 0 ticks[1]['amount'] = 0 date_time = ticks[0]['datetime'] ticks[0]['datetime'] = datetime.datetime(date_time.year, date_time.month, date_time.day, 9, 25) ticks[1]['datetime'] = datetime.datetime(date_time.year, date_time.month, date_time.day, 15) else: # 复权 factor = rdkline.get_adjust_factor(code, back_test_date) for tk in ticks: tk['price'] = Decimal(tk['price']) tk['price'] = (tk['price'] * factor).quantize( Decimal('0.01'), ROUND_HALF_UP) rdbacktest.wirte_l_datas(code, ticks) if len(rdbacktest.read_codes()) == 0: print(back_test_date, '没有tick数据') return print('回测日期', back_test_date) start_quotation_process(commobj, back_test_date) rddaysell = redisRW.redisrw(redisRW.db_day_sell) rdsell = redisRW.redisrw(redisRW.db_sell) # 简单统计 buy_count = 0 zdf_count = Decimal(0) sz_count = 0 xd_count = 0 for d in rdsell.read_all_dec(): buy_count += 1 zdf = d['zdf'] if zdf > 0: sz_count += 1 else: xd_count += 1 zdf_count += zdf if buy_count == 0: return # 持仓市值 market_value = 0 for d in commobj.rdchicang.read_all_dec(): market_value += d['chicang']['marketValue'] zc = commobj.balance + market_value zyk = (zc / commobj.init_balance - 1) * 100 zyk = zyk.quantize(Decimal('0.01'), ROUND_HALF_UP) rddaysell.wirte_l_data( 'daysell', { 'datetime': back_test_date, 'ex_zdf_count': zdf_count, 'sj_zdf_count': (zdf_count / buy_count), 'zyk': zyk, 'buy_count': buy_count, 'sz': sz_count, 'xd': xd_count }) print('卖出数量', buy_count, '上涨', sz_count, '下跌', xd_count, '盈利', (zdf_count / buy_count).quantize(Decimal('0.01'), ROUND_HALF_UP), '可用余额', commobj.balance, '持仓市值', market_value, '总资产', zc, '总盈亏', zyk) return True
def buy(self, tick): if not self.commobj.lock.acquire(timeout=0.1): return False try: cc_tol = 0 cc_amount = Decimal(0) cc_price = Decimal(0) code = tick['code'] tick_chicang = tick['chicang'] price = tick['price'] trade_date = tick['datetime'] if redisRW.redisrw(redisRW.db_sell).read_str(code): return # 限定持仓数量 # if len(self.commobj.rdchicang.read_codes()) >= 1: # return False cangwei = '10000' """elif cc_tol == 1: cangwei = '0.6' elif cc_tol == 2: cangwei = '0.9'""" buy_tol = comm.buy_tol_from_money(code, self.commobj.balance, price, cangwei) if buy_tol is None: # print('余额不足。。') return False if not self.commobj.is_backtest: ht_bh = rpcTrade.buy(code, tick['name'], str(price), buy_tol) print('买入合同编号:', ht_bh) if ht_bh: tm = datetime.datetime.now() e = False while not cc_tol == buy_tol: time.sleep(0.5) if (datetime.datetime.now() - tm).total_seconds() > 10: # 撤单 rpcTrade.cancel_oder_all() time.sleep(6) e = True cj_list = rpcTrade.get_chengjiao(ht_bh) if cj_list: cc_tol = 0 cc_amount = Decimal(0) cc_price = Decimal(0) for cj in cj_list: cc_tol += cj['tol'] cc_price += Decimal(str(cj['price'])) cc_amount += Decimal(str(cj['amount'])) cc_price /= Decimal(len(cj_list)) if e: print('已撤') break if cc_tol > 0: print('已成交:', cc_tol, cc_price, cc_amount) else: cc_price = price cc_tol = buy_tol cc_amount = comm.sell_money_from_tol(code, cc_price, cc_tol) if cc_tol > 0: # 可用金额 self.commobj.balance -= cc_amount + comm.trade_fee(cc_amount) chicang = { 'code': code, 'datetime': trade_date, 'price': cc_price, 'base_price': tick['price_low'], 'r_price': cc_price, 'sell_price': 0, 'tol': cc_tol, 'marketValue': cc_amount, 'status': 0 } for k in chicang.keys(): tick_chicang[k] = chicang[k] r_data = comm.xg_data(code, tick['name'], None, tick['zs_date'], tick['zy_date'], tick['price_zs'], tick['price_zy'], chicang) self.commobj.rdchicang.write_json(code, r_data) return True finally: self.commobj.lock.release()
def backtest_start(common, start_date: datetime.datetime, end_date: datetime.datetime): """ 回测 """ rdchicang = redisRW.redisrw(redisRW.db_backtest_chicang) rdchicang.del_db() rddaysell = redisRW.redisrw(redisRW.db_day_sell) rddaysell.del_db() codes_bk = comm.get_codes_bk() if not codes_bk: print('股票代码列表获取失败。') return zbstrategy = zbStrategy.Strategy(None) while start_date.date() <= end_date.date(): if start_date.weekday() in range(5): # 选股 zbstrategy.stock_select(common['b'], codes_bk, start_date) get_ticks_from_xg_and_start_backtest(common, start_date) #input('按任意键继续...') start_date += datetime.timedelta(days=1) ex_sz_count = 0 ex_xd_count = 0 ex_sell_count = 0 datas = [] zyk_list = [] max_huice = 0 max_zc = None day_sz_count = 0 day_xd_count = 0 last_zc = common['init_balance'] for d in rddaysell.read_l_date_dec_json('daysell', 0, -1): ex_sell_count += d['sell_count'] ex_sz_count += d['sz'] ex_xd_count += d['xd'] zyk_list.append(d['zyk']) if max_zc is None: max_zc = d['zc'] max_zc = max(max_zc, d['zc']) max_huice = max(max_huice, (1 - d['zc'] / max_zc) * 100) if d['zc'] < last_zc: day_sz_count += 1 else: day_xd_count += 1 last_zc = d['zc'] datas.append({ 'datetime': d['datetime'], 'ex_sell_count': ex_sell_count, 'ex_sz_count': ex_sz_count, 'ex_xd_count': ex_xd_count, 'day_sz_count': day_sz_count, 'day_xd_count': day_xd_count, 'zc': float(str(d['zc'])), }) if len(datas) == 0: print('没有交易数据') return zyk_std = float(str(np.std(zyk_list))) m_data = datas[len(datas) - 1] tol_days = (m_data['datetime'] - datas[0]['datetime']).days tol_days = max(1, tol_days) annualized = float(str(d['zyk'])) / tol_days * 365 sharperatio = 0 if zyk_std > 0: sharperatio = annualized / zyk_std ply.write_html_tol( os.path.join(current_path, '..', 'WebServer', 'html', 'charts.html'), datas, float(str(d['zyk'])), max_huice, annualized, sharperatio)
def get_all_clear_finance_qfq_kline_from_start_date(start_date: datetime.date): rdkline = redisRW.redisrw(redisRW.db_kline) rdkline_week = redisRW.redisrw(redisRW.db_kline_week) rdbaseinfo = redisRW.redisrw(redisRW.db_baseinfo) rdhangye = redisRW.redisrw(redisRW.db_hangye) rdfinance = redisRW.redisrw(redisRW.db_finance) # 清空数据 rdkline.del_db() rdkline_week.del_db() # 3年的财务信息 cw_start_year = datetime.datetime.now().year - 3 # 获取指数 _get_sz_index_kline(start_date) # 实例化通达信对象 tdx = dataTdx.DataTdx() tdx.select_fast_addr() # 没有行业信息则更新 if len(rdhangye.read_codes()) == 0: hy = dataBaostock.get_hangye() for h in hy: rdhangye.write_json(h['code'], h) # 读取市场股票 codes_info = tdx.get_szsh_a_codes() bar = progressBar.progressbar() bar.start('存储%s至今历史数据' % start_date.strftime('%Y%m%d'), len(codes_info)) for d in codes_info: bar.progress() code = d['code'] if comm.is_kzz(code): klines = tdx.get_kline_from_count(code, 800) none_klines = tdx.get_kline_from_count(code, 800) k_len = len(klines) if k_len == 0: bar.out_text(code, '没有K线数据。') continue # 复权因子 dataBaostock.qfq_adjust_factor(none_klines, klines) zbKline.klines_calculate(code, klines) if k_len != rdkline.wirte_l_datas(code, klines): bar.out_text(code, '历史K线数据存储错误。') continue continue # 前复权k线 klines = dataBaostock.get_kline_from_start_date(code, start_date) # 不复权k线 none_klines = dataBaostock.get_kline_from_start_date(code, start_date, adjustflag='3') #klines = akshareData.get_kline(code, start_date) k_len = len(klines) if k_len == 0: bar.out_text(code, '没有K线数据。') continue # 复权因子 dataBaostock.qfq_adjust_factor(none_klines, klines) # 前复权周k线 klines_week = dataBaostock.get_kline_from_start_date(code, start_date, frequency='w') # 计算 zbKline.klines_calculate(code, klines_week) zbKline.klines_calculate(code, klines) if k_len != rdkline.wirte_l_datas(code, klines) or \ len(klines_week) != rdkline_week.wirte_l_datas(code, klines_week): bar.out_text(code, '历史K线数据存储错误。') continue # 没有财务数据则更新 if rdfinance.read_str(code) is None: # 财务信息 finance_data = { 'code': code, 'profit': dataBaostock.get_profit_from_start_year(code, cw_start_year), 'balance': dataBaostock.get_balance_from_start_year(code, cw_start_year), 'cash_flow': dataBaostock.get_cash_flow_from_start_year( code, cw_start_year), 'growth': dataBaostock.get_growth_from_start_year(code, cw_start_year), 'operation': dataBaostock.get_operation_from_start_year( code, cw_start_year) } if not rdfinance.write_json(code, finance_data): bar.out_text(code, '财务信息存储错误。') # 没有基本信息则更新 '''if len(rdbaseinfo.read_l_str(code, 0, 0)) == 0:
def sell(self, tick): if not self.commobj.lock.acquire(timeout=0.1): return False cc_tol = 0 cc_amount = Decimal(0) cc_price = Decimal(0) try: rdsell = redisRW.redisrw(redisRW.db_sell) code = tick['code'] tick_chicang = tick['chicang'] trade_date = tick['datetime'] price = tick['price'] if not self.commobj.is_backtest: ht_bh = rpcTrade.sell(code, tick['name'], str(price), tick_chicang['tol']) print('卖出合同编号:', ht_bh) if ht_bh: tm = datetime.datetime.now() e = False while not cc_tol == tick_chicang['tol']: time.sleep(0.5) if (datetime.datetime.now() - tm).total_seconds() > 30: # 撤单 rpcTrade.cancel_oder_all() time.sleep(6) e = True cj_list = rpcTrade.get_chengjiao(ht_bh) if cj_list: cc_tol = 0 cc_amount = Decimal(0) cc_price = Decimal(0) for cj in cj_list: cc_tol += cj['tol'] cc_price += Decimal(str(cj['price'])) cc_amount += Decimal(str(cj['amount'])) cc_price /= Decimal(len(cj_list)) if e: print('已撤') break if cc_tol > 0: print('已成交:', cc_tol, cc_price, cc_amount) else: cc_tol = tick_chicang['tol'] cc_price = price cc_amount = comm.sell_money_from_tol(code, cc_price, cc_tol) if cc_tol > 0: # 可用金额 self.commobj.balance += cc_amount tick_chicang['tol'] -= cc_tol if tick_chicang['tol'] == 0: tick_chicang['status'] = 1 tick_chicang['sell_price'] = cc_price zdf = (cc_price / tick_chicang['price'] - 1) * 100 if not self.commobj.rdchicang.delete(code): print(code, '删除持仓数据错误。') rdsell.write_json( code, { 'code': code, 'datetime': trade_date, 'price': cc_price, 'money': cc_amount, 'zdf': zdf }) return True finally: self.commobj.lock.release()