Warning: file_exists(): open_basedir restriction in effect. File(/www/wwwroot/com.xiximiao.oa/com.cmstop/public/www/wp-content/db.php) is not within the allowed path(s): (/www/wwwroot/com.xiximiao.oa/com.cmstop/public/www/:/tmp/:/proc/:/var/log/nginx/:/www/wwwroot/com.xiximiao.oa/com.cmstop/public/:/www/wwwroot/com.xiximiao.oa/com.cmstop/vendor/:/www/wwwroot/com.xiximiao.oa/com.cmstop/ppk/) in /www/wwwroot/com.xiximiao.oa/com.cmstop/public/www/wp-includes/load.php on line 707
2062 北向资金择时策略,北向资金交易能力一定强吗.py 量化策略分享 » 轻知量化 QMT、PTrade、聚宽策略分享交流平台

2062 北向资金择时策略,北向资金交易能力一定强吗.py 量化策略分享

策略名称:北向资金择时策略

策略说明:

本策略基于北向资金(沪股通和深股通)的净流入数据,通过计算短期和长期的指数加权移动平均线(EWMA)以及标准差,构建了一个择时信号。策略的核心思想是,当北向资金的短期净流入显著高于长期净流入时,认为市场可能处于上升趋势,选择开仓;反之,当短期净流入显著低于长期净流入时,认为市场可能处于下降趋势,选择平仓。

策略逻辑:

1. **数据获取**:

- 通过`query_northmoney`函数获取北向资金的买入金额、卖出金额等数据。
- 计算每日的北向资金净流入(买入金额 - 卖出金额)。

2. **信号生成**:
- 计算北向资金净流入的长期(71天)和短期(6天)指数加权移动平均线(EWMA)。
- 计算北向资金净流入的标准差(基于长期窗口)。
- 生成择时信号:`(短期EWMA - 长期EWMA) / 标准差`。
- 当信号值大于设定的高阈值(-0.499)时,认为市场处于上升趋势,选择开仓;当信号值小于设定的低阈值(-0.159)时,认为市场处于下降趋势,选择平仓。

3. **交易执行**:
- 在每日的`handle_data`函数中,根据生成的择时信号决定是否开仓或平仓。
- 开仓时,买入标的ETF(沪深300ETF,代码:510300.XSHG);平仓时,卖出所有持仓。

策略参数:

- **标的ETF**:沪深300ETF(510300.XSHG)
- **高阈值(threshold_h)**:-0.499
- **低阈值(threshold_l)**:-0.159
- **长期窗口(long_period)**:71天
- **短期窗口(short_period)**:6天

策略特点:

- **基于北向资金**:北向资金通常被视为“聪明钱”,其流入流出情况对市场有一定的预示作用。
- **择时信号**:通过短期和长期净流入的对比,捕捉市场的趋势变化。
- **动态调整**:根据市场情况动态调整仓位,避免在市场下跌时持有过多仓位。

适用场景:

- **市场趋势明显时**:当市场处于明显的上升或下降趋势时,策略表现较好。
- **北向资金活跃时**:在北向资金流入流出较为活跃的市场环境下,策略的信号更为有效。

风险提示:

- **滞后性**:择时信号基于历史数据生成,可能存在一定的滞后性。
- **市场波动**:在市场波动较大时,策略可能会频繁开仓平仓,增加交易成本。
- **北向资金数据限制**:北向资金数据从2014年11月开始,策略在早期数据不足时可能表现不稳定。

总结:

本策略通过北向资金的净流入数据构建择时信号,旨在捕捉市场的趋势变化,适合在趋势明显的市场环境下使用。策略的核心在于通过短期和长期净流入的对比,动态调整仓位,以期在市场上升时获得收益,在市场下跌时减少损失。

策略代码:

# 标题:【复现】北向资金交易能力一定强吗
# 作者:Hugo2046

'''
Author: Hugo
Date: 2020-09-28 21:52:43
LastEditTime: 2020-09-28 22:10:35
LastEditors: Hugo
Description: 根据最优参数进行择时回测,注意北流数据2014年11月才有数据

关键函数解释:
    distributed_query 用于若干数据查询限制
    query_northmoney 用于查询北向资金数据
    get_net_north_flow 用于计算北向资金净流量
    get_north_factor 是否开仓 大于阈值开仓 小于阈值平仓
'''


from jqdata import *

import numpy as np
import pandas as pd


enable_profile()  # 开启性能分析


def initialize(context):
    set_params()
    set_variables()
    set_backtest()


def set_params():

    g.target_etf = '510300.XSHG'  # 标的为HS300

    # 设置参数
    g.params = {'threshold_h': -0.4991838749623957,
                'threshold_l': -0.15982912319375642,
                'long_period': 71,
                'short_period': 6}


def set_variables():

    pass


def set_backtest():

    set_option("avoid_future_data", True)  # 避免数据
    set_option("use_real_price", True)  # 真实价格交易
    set_benchmark('000300.XSHG')  # 设置基准
    #log.set_level("order", "debuge")
    log.set_level('order', 'error')


# 每日盘前运行
def before_trading_start(context):

    set_slip_fee(context)


# 设置不同时期手续费


def set_slip_fee(context):
    # 将滑点设置为0
    set_slippage(FixedSlippage(0))
    # 根据不同的时间段设置手续费
    dt = context.current_dt

    if dt > datetime.datetime(2013, 1, 1):
        set_commission(PerTrade(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))

    elif dt > datetime.datetime(2011, 1, 1):
        set_commission(PerTrade(buy_cost=0.001, sell_cost=0.002, min_cost=5))

    elif dt > datetime.datetime(2009, 1, 1):
        set_commission(PerTrade(buy_cost=0.002, sell_cost=0.003, min_cost=5))

    else:
        set_commission(PerTrade(buy_cost=0.003, sell_cost=0.004, min_cost=5))


########################################### 数据获取 ####################################################

def distributed_query(query_func_name, start: str, end: str, limit=3000, **kwargs) -> pd.DataFrame:
    '''用于绕过最大条数限制'''

    days = get_trade_days(start, end)

    n_days = len(days)

    if len(days) > limit:

        n = n_days // limit

        df_list = []

        i = 0

        pos1, pos2 = n * i, n * (i + 1) - 1

        while pos2 < n_days:

            df = query_func_name(
                start=days[pos1],
                end=days[pos2],
                **kwargs)

            df_list.append(df)

            i += 1

            pos1, pos2 = n * i, n * (i + 1) - 1

            if pos1 < n_days:

                df = query_func_name(
                    start=days[pos1],
                    end=days[-1],
                    **kwargs)

                df_list.append(df)

            df = pd.concat(df_list, axis=0)

    else:

        df = query_func_name(
            start=start, end=end, **kwargs)

    return df


def query_northmoney(start: str, end: str, fields: list) -> pd.DataFrame:
    '''北向资金成交查询'''

    select_type = ['沪股通', '深股通']

    select_fields = ','.join([f"finance.STK_ML_QUOTA.%s" % i for i in fields])

    df_list = []
    for types in select_type:

        q = query(select_fields).filter(finance.STK_ML_QUOTA.day >= start,
                                        finance.STK_ML_QUOTA.day <= end,
                                        finance.STK_ML_QUOTA.link_name == types)
        df_list.append(finance.run_query(q))

    return pd.concat(df_list)


# 构造北流净值
def get_net_north_flow(watch_date: str, N: int) -> pd.Series:

    begin = get_trade_days(end_date=watch_date, count=N)[
        0].strftime('%Y-%m-%d')

    # 获取北流相关数据
    fields = ['day', 'link_name', 'buy_amount', 'sell_amount', 'sum_amount']
    north_money = distributed_query(
        query_northmoney, begin, watch_date, fields=fields)

    # 日度合计各项指标
    daily_northmoney = north_money.groupby('day').sum()

    daily_northmoney.index = pd.to_datetime(daily_northmoney.index)

    # 计算净流
    return daily_northmoney['buy_amount'] - daily_northmoney['sell_amount']

# 信号构造
def get_north_factor(north_flow: pd.Series, params: dict) -> bool:

    l = north_flow.ewm(span=params['long_period'], adjust=False).mean()

    s = north_flow.ewm(span=params['short_period'], adjust=False).mean()

    north_factor = (s - l) / north_flow.rolling(params['long_period']).std()

    record(north_factor=north_factor.iloc[-1],
           h=params['threshold_h'], l=params['threshold_l'])

    if north_factor.iloc[-1] > params['threshold_h']:
        log.info('需要开仓,信号:%.4f,阈值:%.4f' %
                 (north_factor.iloc[-1], params['threshold_h']))
        return True

    elif north_factor.iloc[-1] < params['threshold_l']:
        log.info('需要平仓,信号:%.4f,阈值:%.4f' %
                 (north_factor.iloc[-1], params['threshold_h']))
        return False

    else:
        log.info('不做操作,信号:%.4f,阈值:%.4f' %
                 (north_factor.iloc[-1], params['threshold_h']))
        return True

########################################### 交易 ####################################################


def handle_data(context, data):

    bar_time = context.previous_date.strftime('%Y-%m-%d')

    north_flow = get_net_north_flow(bar_time, 300)

    is_trade = get_north_factor(north_flow, g.params)
    if is_trade and len(context.portfolio.long_positions) == 0:
        log.info('执行开仓操作')
        order_target_value(g.target_etf, context.portfolio.total_value)

    if not is_trade and len(context.portfolio.long_positions) != 0:

        log.info('执行平仓操作')
        order_target(g.target_etf, 0)
2025-02-20
⚠️
本站资源大多来自网络,仅供网友学习交流,未经作者或上传书面授权,请勿作他用。
站长 vx: xiangyin615 或者 留言反馈 ,我们将尽快处理。
Notice: When you of the legal rights be violate, please stir to vx: xiangyin615
个人中心
购物车
优惠劵
搜索