def start_roll(current_day, total_money, old_group=None): # 买入的组合转债信息 {code:{amount:xxx}} group = {} with db_utils.get_daily_connect() as con: cur = con.cursor() rows = global_test_context.get_start_rows(cur, current_day) # 没找到可转债, 或者太贵了, 不满足轮动条件, 不买, 进入下一个交易日 if len(rows) == 0 or \ (global_test_context.need_check_double_low and is_too_expensive(rows, max_double_low=global_test_context.max_double_low)): # 取下一个交易日 next_day = get_next_day(current_day, cur) if next_day is not None: return start_roll(next_day, total_money, old_group) else: # 已经到结束日了 print('not found next day by ' + str(current_day)) return None, current_day, None # 等权分配资金 remain_money = do_push_bond(group, rows, total_money, old_group=old_group) return group, current_day, remain_money
def push_bond(group, cur, buy_num, exclude_ids, params, total_money, test_result, current_day, row_size): # 卖出几只, 就买入几只 params.setdefault("count", buy_num) push_rows = global_test_context.get_push_rows(cur, exclude_ids, params) # 没有找到满足条件的转债, 一个也不买, 下一个交易日重新开仓 if len(push_rows) == 0: print("not find bond to push with:" + str(params)) return True remain_money = do_push_bond(group, push_rows, total_money, row_size=row_size) for row in push_rows: bond_id = row[0] bond = group[bond_id] if bond is not None: _add_roll_row_to(test_result, current_day, bond_id, bond, '买入') else: print("not find bond in group by bond_id" + str(bond_id) + ", group:" + str(group)) # 对新的组合再次检查, 看是否满足条件 expensive = global_test_context.need_check_double_low and is_too_expensive( None, group, global_test_context.max_double_low) if expensive is False: # 只有继续下一个交易,才需要更新剩下的零头 test_result['remain_money'] = remain_money return expensive
def pop_bond(group, new_rows, current_day, test_result): sell_total_money = 0 total_money = 0 sell_num = 0 # 应该group已经用rows更新过了, 所以直接用group判断 if global_test_context.need_check_double_low and is_too_expensive( None, group, global_test_context.max_double_low): return len(new_rows), total_money for new_row in new_rows: bond_id = new_row[0] bond = group.get(bond_id) bond_nm = bond['bond_nm'] new_price = new_row[2] if new_price is None: print("price is None in row:" + str(new_row)) new_price = bond.get("price") total_money += new_price * bond.get("amount") max_price = global_test_context.max_price max_rise = global_test_context.max_rise # 价格超过200的轮出 if new_price >= max_price: print("pop bond:" + bond_nm + " when price >=" + str(max_price) + " at " + str(current_day)) sell_total_money += new_price * bond.get("amount") group.pop(bond_id) sell_num += 1 _add_roll_row_to(test_result, current_day, bond_id, bond, '价格超过' + str(max_price) + "卖出") # 强赎/退市的轮出 elif new_row[4] is not None and new_row[4] == 1: print("pop bond:" + bond_nm + " when delist or enforce at " + str(current_day)) sell_total_money += new_price * bond.get("amount") group.pop(bond_id) sell_num += 1 _add_roll_row_to(test_result, current_day, bond_id, bond, '退市卖出') # 一周涨幅超过30%的轮出 elif new_row[6] is not None and new_row[6] >= max_rise: print("pop bond:" + bond_nm + " when raise " + str(max_rise) + "% at " + str(current_day)) sell_total_money += new_price * bond.get("amount") group.pop(bond_id) sell_num += 1 _add_roll_row_to(test_result, current_day, bond_id, bond, '涨幅超过' + str(max_rise) + "%卖出") return sell_num, sell_total_money
def do_trade(current_day, group, previous_day, test_result): # 用来和七天前的价格进行比较, 如果涨幅过大(30%), 提前止盈 params = { "current": current_day, "pre_day": global_test_context.pre_day, 'max_price': global_test_context.max_price, } keys = sorted(group.keys()) ids = parse_bond_ids_params(keys, params) with db_utils.get_daily_connect() as con: cur = con.cursor() new_rows = get_hold_rows(cur, ids, params) # 异常数据, 跳过 if new_rows is None: print('not get new rows. params:' + str(params)) return False, previous_day, get_pre_total_money( previous_day, test_result) # 有可能那天停牌了, 导致两边数据不一致 if len(new_rows) != len(group): print("data is conflict. current_day:" + str(current_day) + ", group size:" + str(len(group)) + ", new_row size:" + str(len(new_rows))) # 为了计算盈亏, 主要更新价格 update_bond(group, new_rows) total_money = get_total_money(group, test_result) calc_test_result(test_result, total_money, current_day, previous_day) # 太贵了, 清仓(并没有实际的卖出操作, 只是总金额不再随价格变动) if global_test_context.need_check_double_low and \ is_too_expensive(new_rows, group, global_test_context.max_double_low, current_day, test_result, need_roll_row=global_test_context.one_strategy_with_one_scenario): print("clean all bonds at " + str(current_day) + " bonds:" + str(new_rows)) return True, current_day # 根据条件对转债进行轮换(不影响当天收益) break_roll = exchange_bond(cur, current_day, group, ids, params, new_rows, test_result) return break_roll, current_day