예제 #1
0
def order_target_value(context, security, value):
    if value < 0:
        logger.info("目标价值不能为负,已调整为0")
        value = 0
    today_data = baoStockUtil.get_today_data(context, security)
    hold_value = context.positions.get(security, 0) * today_data['open']
    delta_value = value - hold_value
    order_value(context, security, delta_value)
예제 #2
0
def order_target(context, security, amount):
    if amount < 0:
        logger.info("目标股数不能为负,已调整为0")
        amount = 0
    today_data = baoStockUtil.get_today_data(context, security)
    hold_amount = context.positions.get(security, 0)  # TODO 卖出没有考虑 T+1
    delta_amount = amount - hold_amount
    _order(context, today_data, security, delta_amount)
예제 #3
0
def sendMsg(msg, friendName='quantMsg'):  # 给好友发送消息
    if len(msg.strip()) == 0:
        return
    logger.info("发送qq消息: " + msg)
    setText(msg)
    hwndQQ = win32gui.FindWindow(None, friendName)  # 找到名字为'friendName'的窗口
    if hwndQQ == 0:
        # logger.error('未找到qq对话框')
        raise Exception('未找到qq对话框 ' + friendName)
        # return
    win32gui.SendMessage(hwndQQ, win32con.WM_PASTE, 0, 0)
    win32gui.SendMessage(hwndQQ, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)
예제 #4
0
 def send_data(self, message):
     if len(message.strip()) == 0:
         return
     logger.info("发送微信消息: " + message)
     send_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' + self.get_access_token(
     )
     send_values = {
         "touser": self.TOUSER,
         "msgtype": "text",
         "agentid": self.AGENTID,
         "text": {
             "content": message
         },
         "safe": "0"
     }
     send_msg = (bytes(json.dumps(send_values), 'utf-8'))
     response = requests.post(send_url, send_msg)
     response = response.json()  # 当返回的数据是json串的时候直接用.json即可将respone转换成字典
     if 'ok' != response["errmsg"]:
         raise Exception('发送微信消息失败:' + response["errmsg"])
예제 #5
0
def get_stocks_info_from_h5(key='stocks_info'):
    """
    从h5文件中读取股票信息
    :return: df
    """
    result = get_h5_data(key)
    # 清空h5文件,重新构造
    clear_flag = False
    try:
        if not timeUtil.is_today(
                result.iloc[-1]['最新时间']) and timeUtil.is_trade_day():
            # 如果从文件里读出的信息不是当日的最新信息,则清空文件内容,这样做是为了每天初始化消息信号的标志位
            clear_flag = True
    except KeyError:  # 读取不到最新时间
        clear_flag = True

    if clear_flag:
        logger.info("清空h5文件,重新构造")
        result = init_stocks_info()
        put_h5_data(key, result)
    return result
예제 #6
0
def _order(context, today_data, security, amount):
    operate_flag = "买入"
    if amount < 0:
        operate_flag = "卖出"

    if len(today_data) == 0:
        logger.info("今日停牌")
        return

    # 当前股票价格
    p = today_data['open']
    if context.cash < amount * p:
        amount = int(context.cash / p)
        logger.info("现金不足,已调整为%d股" % amount)

    # 买卖的数量为100的倍数
    if amount % 100 != 0:
        if amount != -context.positions.get(security, 0):
            err_amount = amount
            # 负号为卖出,卖出时不等于当前持有这只股票的总数
            amount = int(amount / 100) * 100
            # logger.info("%s的数量%s不是100的倍数,已调整为%d股" % (operate_flag, err_amount, amount))

    # 卖出的数量大于已持有的数量时
    if context.positions.get(security, 0) < -amount:
        amount = -context.positions.get(security, 0)
        logger.info("卖出股票不能超过持仓数,已调整为%d股" % amount)

    logger.info("%s%s股" % (operate_flag, abs(amount)))

    # 更新持仓信息
    context.positions[security] = context.positions.get(security, 0) + amount
    if context.positions[security] == 0:
        del context.positions[security]

    # 更新现金信息
    context.cash = context.cash - amount * p
    # 保留两位小数
    context.cash = round(context.cash, 2)
    logger.info("剩余可用金额:%s" % context.cash)
예제 #7
0
파일: w_shape.py 프로젝트: 543090050/quant
def strategy_w_shape(code, current_data, history_data, round_=0):
    logger.info("第%d轮解析%s" % (round_, code))

    # 最后一天为买点,要是阳线
    if current_data['开盘价'] >= current_data['最新价']:
        # logger.info(code+"当前是阴线,不符合条件")
        return code + "当前是阴线,不符合条件"

    # 当前价格要上穿8日均线
    ma8 = dataUtil.get_cur_ma_line(history_data, current_data, 8)
    if current_data['最新价'] < ma8[-1]:
        return code + "当前价格在8日均线以下,不符合条件"

    # 合并k线
    history_data = shapeUtil.merge_all_k_line(history_data)
    # 将今日最新价 追加到history_data后
    history_data = dataUtil.fill_today_data(current_data, history_data)

    # 当天应是底分型的形态
    if not shapeUtil.is_bottom_shape(history_data, history_data.iloc[-2].name):
        return code + "当前不是底分型,不符合条件"

    # data_range 确定游标范围长度,默认从15开始,因为有三个趋势类型,每个趋势类型至少有5条k线
    for data_range in range(15, len(history_data) + 1):
        range_df = history_data[-data_range:]  # 从后往前逐步扩大范围
        # logger.info('游标天数=====:' + str(data_range) + " 时间范围: " + range_df.index[0].strftime('%Y-%m-%d') + " - " +
        #             range_df.index[-1].strftime('%Y-%m-%d'))

        for split in range(4, data_range - 4):  # 分割索引从4开始,保证区域内至少有3个值
            region1 = range_df[0:split]
            region2 = range_df[split:]

            high1_index = region1['high'].idxmax()
            high1_data = region1.loc[high1_index]
            min1_index = region1['low'].idxmin()
            min1_data = region1.loc[min1_index]
            min2_index = region2['low'].idxmin()
            min2_data = region2.loc[min2_index]

            # 倒数第二天应是min2应该在的位置;倒数第一天完成成底分型;
            min2_temp = history_data.iloc[-2]
            if min2_temp.name != min2_index:
                continue
                # return '未找到符合条件的时间范围'

            region3 = range_df.loc[min1_index:min2_index]
            if len(region3) < 3:  # 区域3需要掐头去尾掉区域一二的最小值,这里的判断保证区域三内至少有值
                continue
            region3 = region3[1:-1]  # 去掉 区域三 头尾的最小值

            high2_index = region3['high'].idxmax()
            high2_data = region3.loc[high2_index]

            high1 = high1_data['high']
            min1 = min1_data['low']
            high2 = high2_data['high']
            min2 = min2_data['low']

            # TODO debug找日期
            # if high1_index.strftime('%Y-%m-%d') == '2020-10-16' and min1_index.strftime('%Y-%m-%d') == '2020-12-25' \
            #         and high2_index.strftime('%Y-%m-%d') == '2021-01-06':
            #     pass
            # else:
            #     continue

            # 开始校验====================================================================================================
            # 如果极值在起始边界,则为无效数据,跳过下面分型的校验。
            if high1_index.strftime('%Y-%m-%d') == range_df.index[0].strftime('%Y-%m-%d') \
                    or min2_index.strftime('%Y-%m-%d') == range_df.index[-1].strftime('%Y-%m-%d'):
                continue

            # 四个极点的顺序
            if high1_index < min1_index < high2_index < min2_index:
                pass
            else:
                continue

            # 确认极点形态
            if min1 <= min2 and high1 > high2:  # w 形态的四个主要点,高一低一;高二低二
                pass
            else:
                continue

            # high1要是整个范围内的最大值
            if high1_data['high'] < range_df['high'].max():
                continue

            # min1要是整个范围内的最小值
            if min1_data['low'] > range_df['low'].min():
                continue

            # min2要是high2到结束间的最小值
            region_high2_end = range_df.iloc[range_df.index.get_loc(high2_index
                                                                    ) + 1:]
            if min2_data['low'] > region_high2_end['low'].min():
                continue

            # 一顶和一底之间至少有 3 条k线。如果包括两个极点,就是5条k线
            if range_df.index.get_loc(min1_index) - range_df.index.get_loc(
                    high1_index) > 3:
                pass
            else:
                continue

            # 一底和二顶之间至少有 3 条k线。如果包括两个极点,就是5条k线
            if range_df.index.get_loc(high2_index) - range_df.index.get_loc(
                    min1_index) > 3:
                pass
            else:
                continue

            # 二顶和二底之间至少有 3 条k线。如果包括两个极点,就是5条k线
            if range_df.index.get_loc(min2_index) - range_df.index.get_loc(
                    high2_index) > 3:
                pass
            else:
                continue

            # 识别一顶分型
            if shapeUtil.is_top_shape(range_df, high1_index):
                pass
            else:
                continue

            # 识别一底分型
            if shapeUtil.is_bottom_shape(range_df, min1_index):
                pass
            else:
                continue

            # 识别二顶分型
            if shapeUtil.is_top_shape(range_df, high2_index):
                pass
            else:
                continue

            # 识别二底分型
            if shapeUtil.is_bottom_shape(range_df, min2_index):
                pass
            else:
                continue

            # 如果通过前面的校验,则加到结果集
            info = code + ' 符合底分型 ' + str(high1_index).replace(
                ' 00:00:00', ' ') + str(min1_index).replace(
                    ' 00:00:00', ' ') + str(high2_index).replace(
                        ' 00:00:00', ' ') + str(min2_index).replace(
                            ' 00:00:00', ' ')
            # mplfinance.plot(range_df, type='candle')
            # result.add(info)
            logger.info(info)
            stocks_info = h5Util.get_stocks_info()  # 这里单独读取是为了防止其他进程已经改了已有数据
            c_data = current_data.copy()
            c_data['w_shape_flag'] = 'True'
            stocks_info.loc[code] = c_data
            # stocks_info.loc[code, 'w_shape_flag'] = 'True'
            h5Util.put_h5_data("stocks_info", stocks_info)
            return info
    return '未找到符合条件的时间范围'
예제 #8
0
    lock = multiprocessing.Manager().Lock()  # 创建进程锁
    context = get_context()

    stocks_info = h5Util.get_stocks_info()
    # 将全部code按每组chunk_len个进行分组,代码分组后,将每组放入进程池分批处理
    for code_list in np.array_split(all_code_list,
                                    len(all_code_list) / chunk_len + 1):
        # handle_list(context, code_list, stocks_info)
        pool.apply_async(generate_signal,
                         (context, code_list, stocks_info, lock, round_))
    pool.close()
    pool.join()
    # 根据信号发送消息
    msgUtil.send_msg_by_signal()


if __name__ == '__main__':
    # handle_data()

    round_ = 0  # 轮次
    while 1:
        if timeUtil.in_trade_time(time1=vs.STRATEGY_START_TIME,
                                  time2=vs.STRATEGY_END_TIME):
            start_time = datetime.datetime.now()
            round_ = round_ + 1
            handle_data(round_)
            end_time = datetime.datetime.now()
            logger.info("完成第" + str(round_) + "轮解析,耗时" +
                        str(round((end_time - start_time).seconds / 60, 2)) +
                        "分钟")