Пример #1
0
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
Пример #2
0
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
Пример #3
0
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
Пример #4
0
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