动量效应是金融市场中一种常见的现象,指的是过去表现较好的资产在未来一段时间内继续表现良好的趋势。本文将介绍一种基于动量效应的量化策略,并使用Python代码展示其实现过程。

策略逻辑

该策略的核心逻辑是:选取过去一段时间内涨幅最大的N只股票,持有它们在未来一段时间内,期望它们能够继续保持上涨趋势。

数据准备

首先,我们从AllTick的接口获取股票的历史价格数据。

import time
import requests
import pandas as pd

# 定义获取历史K线数据的函数
def get_historical_data(symbol, kline_type=1, kline_timestamp_end=0, query_kline_num=100, adjust_type=0):
    url = 'http://quote.aatest.online/quote-stock-b-api/kline'
    token = 'e945d7d9-9e6e-4721-922a-7251a9d311d0-1678159756806'
    
    # 构造查询参数
    query = {
        "trace": "python_http_test1",
        "data": {
            "code": symbol,
            "kline_type": kline_type,  # K线类型:1为日线
            "kline_timestamp_end": kline_timestamp_end,  # 结束时间戳,0表示最新时间
            "query_kline_num": query_kline_num,  # 获取的K线数量
            "adjust_type": adjust_type  # 复权类型:0为不复权
        }
    }
    
    # 发送请求
    response = requests.get(
        url=url,
        params={"token": token, "query": json.dumps(query)},
        headers={'Content-Type': 'application/json'}
    )
    
    # 解析返回的数据
    if response.status_code == 200:
        data = response.json()
        if data.get("code") == 0:  # 判断请求是否成功
            kline_data = data["data"]["kline"]
            df = pd.DataFrame(kline_data, columns=["timestamp", "open", "high", "low", "close", "volume"])
            df["timestamp"] = pd.to_datetime(df["timestamp"], unit="s")  # 转换时间戳为日期
            df.set_index("timestamp", inplace=True)
            return df
        else:
            print(f"Error: {data.get('message')}")
            return None
    else:
        print(f"Request failed with status code: {response.status_code}")
        return None

# 获取多只股票的历史数据
symbols = ["700.HK", "UNH.US", "AAPL.US"]  # 示例股票代码
start_date = "2022-01-01"
end_date = "2023-01-01"

# 获取历史数据并计算收益率
data = {}
for symbol in symbols:
    df = get_historical_data(symbol, query_kline_num=252)  # 获取252个交易日的数据
    if df is not None:
        df['returns'] = df['close'].pct_change()  # 计算每日收益率
        data[symbol] = df

# 将所有股票数据合并到一个DataFrame中
all_data = pd.concat(data.values(), keys=data.keys(), names=['symbol'])

动量计算

接下来,我们计算每只股票在过去一段时间内的累计收益率,作为其动量指标。

lookback_period = 20  # 动量计算周期
all_data['momentum'] = all_data.groupby('symbol')['returns'].rolling(window=lookback_period).apply(lambda x: (x + 1).prod() - 1).reset_index(level=0, drop=True)

策略构建

在每个调仓日,我们选取动量最大的N只股票,等权重持有。

import numpy as np

N = 5  # 持有股票数量
rebalance_freq = 'M'  # 每月调仓一次

# 计算每个调仓日的动量排名
all_data['rank'] = all_data.groupby('date')['momentum'].rank(ascending=False)

# 生成交易信号
all_data['signal'] = np.where(all_data['rank'] <= N, 1, 0)

# 计算策略收益
all_data['strategy_return'] = all_data.groupby('symbol')['signal'].shift(1) * all_data['returns']

# 计算组合收益
portfolio_return = all_data.groupby('date')['strategy_return'].sum() / N

策略评估

最后,我们可以计算策略的年化收益率、最大回撤等指标,并绘制策略的净值曲线。

# 计算年化收益率
annual_return = portfolio_return.mean() * 252

# 计算最大回撤
cumulative_return = (1 + portfolio_return).cumprod()
peak = cumulative_return.cummax()
drawdown = (cumulative_return - peak) / peak
max_drawdown = drawdown.min()

# 打印策略表现
print(f"年化收益率: {annual_return:.2%}")
print(f"最大回撤: {max_drawdown:.2%}")

# 绘制净值曲线
import matplotlib.pyplot as plt

plt.figure(figsize=(10, 6))
plt.plot(cumulative_return)
plt.title('Strategy Cumulative Return')
plt.xlabel('Date')
plt.ylabel('Cumulative Return')
plt.show()

总结

动量效应是量化交易中一个经典且有效的策略。本文介绍了一种基于动量效应的简单策略,并使用Python代码展示了其实现过程。需要注意的是,该策略仅作为示例,实际应用中需要考虑更多因素,如交易成本、风险控制等。