股市能量场理论Python实战指南


在股票交易中,传统技术指标(如MACD、RSI)常因滞后性错过最佳买卖点。本文将融合物理学中的能量场理论,提出一个创新指标——市场能量潮(Market Energy Tide, MET),通过量化价格、成交量、波动率的能量转换,提前识别趋势转折点。文末提供可直接运行的Python代码,助你实战验证。


一、传统指标的局限性

1. 常见指标分析

  • 趋势线斜率:依赖主观画线,难以量化;
  • RSI/MACD:基于历史价格计算,信号滞后;
  • 波动率指标(ATR):反映幅度但无法预判方向。

2. 核心痛点

  • 维度单一:仅考虑价格或成交量;
  • 噪声干扰:震荡市中假信号频发;
  • 缺乏能量视角:未衡量市场多空力量的“积蓄-爆发-衰竭”过程。

二、能量场理论:重新定义市场动力学

1.理论基础与创新点

能量守恒定律的金融化:

将价格动能(K)、成交量势能(V)、波动率热能(H)视为市场能量的三大来源,三者相互转化,形成「能量场」。

  • 价格动能(K):价格变化的加速度(二阶导数),代表趋势惯性。
  • 成交量势能(V):成交量对价格变化的支撑强度,类似“燃料”。
  • 波动率热能(H):市场情绪的热度,高波动率加速能量释放。

核心逻辑:

  • 能量积累阶段:价格缓涨+缩量+低波动 → 能量场积蓄。
  • 能量爆发阶段:价格陡升+放量+高波动 → 能量释放,进入主升浪。
  • 能量衰竭阶段:价格滞涨+量能背离 → 能量场衰减,趋势反转。

2.指标公式与计算步骤

能量场强度(Energy Field Intensity, EFI)

E F I t = α ⋅ K t + β ⋅ V t + γ ⋅ H t EFI_t=α⋅K _t+β⋅V_t+γ⋅H_t EFIt=αKt+βVt+γHt

  • 参数:
    • α,β,γ 为权重系数(默认各1/3,可优化)。
    • K t = d 2 P / d t 2 K_t=d^2P/dt^2 Kt=d2P/dt2(价格二阶导数,反映加速度)。
    • V t = 成交 量 t / E M A ( 成交量 , N ) V_t=成交量_t/EMA(成交量,N) Vt=成交t/EMA(成交量,N)(成交量相对强度)。
    • H t = A T R t / E M A ( A T R , N ) H_t=ATR_t/EMA(ATR,N) Ht=ATRt/EMA(ATR,N)(波动率相对强度)。
  • 动态调整权重:
    • V t V_t Vt>1(放量)时,提高 β 权重,强化量能影响;
    • H t H_t Ht>1(高波动)时,降低γ 权重,避免噪声干扰。
  • 信号规则
    • 买入信号:
      EFI > 0.6 且能量方向向上,成交量突破前高。
    • 卖出信号:
      EFI < 0.4 且能量方向向下,价格-EFI顶背离。

3.Python代码实现1.0(核心逻辑)

import yfinance as yf
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import gridspec


# 计算ATR(平均真实波幅)
def calculate_ATR(df, period=14):
    df['H-L'] = df['High'] - df['Low']
    df['H-PC'] = abs(df['High'] - df['Close'].shift(1))
    df['L-PC'] = abs(df['Low'] - df['Close'].shift(1))
    df['TR'] = df[['H-L', 'H-PC', 'L-PC']].max(axis=1)
    df['ATR'] = df['TR'].rolling(period).mean()
    return df.drop(['H-L', 'H-PC', 'L-PC', 'TR'], axis=1)


# 市场能量潮(MET)指标计算
def calculate_MET(df, period=14):
    # 价格二阶导数(使用5日均线的加速度)
    df['MA5'] = df['Close'].rolling(5).mean()
    df['Price_Derivative2'] = df['MA5'].diff().diff()

    # 成交量势能
    df['Volume_EMA'] = df['Volume'].ewm(span=period).mean()
    df['V_t'] = df['Volume'] / df['Volume_EMA']

    # 波动率热能(ATR相对强度)
    df = calculate_ATR(df, period)
    df['ATR_EMA'] = df['ATR'].ewm(span=period).mean()
    df['H_t'] = df['ATR'] / df['ATR_EMA']

    # 动态权重调整
    df['Beta'] = np.where(df['V_t'] > 1, 0.5, 0.3)
    df['Gamma'] = np.where(df['H_t'] > 1, 0.2, 0.3)
    df['Alpha'] = 1 - df['Beta'] - df['Gamma']

    # 标准化处理(消除量纲影响)
    df['Price_Derivative2_norm'] = (df['Price_Derivative2'] - df['Price_Derivative2'].rolling(50).mean()) / df[
        'Price_Derivative2'].rolling(50).std()
    df['V_t_norm'] = (df['V_t'] - df['V_t'].rolling(50).mean()) / df['V_t'].rolling(50).std()
    df['H_t_norm'] = (df['H_t'] - df['H_t'].rolling(50).mean()) / df['H_t'].rolling(50).std()

    # 计算能量场强度EFI
    df['EFI'] = df['Alpha'] * df['Price_Derivative2_norm'] + df['Beta'] * df['V_t_norm'] + df['Gamma'] * df['H_t_norm']

    # 计算MET方向(3日EMA平滑)
    df['MET_Direction'] = df['EFI'].diff().ewm(span=3).mean()

    # 生成交易信号
    df['Buy_Signal'] = (df['EFI'] > 0.6) & (df['MET_Direction'] > 0)
    df['Sell_Signal'] = (df['EFI'] < 0.4) & (df['MET_Direction'] < 0)

    return df


# 可视化函数
def visualize_MET(df, ticker):
    plt.figure(figsize=(16, 12))
    gs = gridspec.GridSpec(3, 1, height_ratios=[3, 1, 2])

    # 价格走势和交易信号
    ax1 = plt.subplot(gs[0])
    ax1.plot(df['Close'], label='Price', linewidth=1)
    ax1.scatter(df.index[df['Buy_Signal']], df['Close'][df['Buy_Signal']],
                marker='^', color='g', s=100, label='Buy Signal')
    ax1.scatter(df.index[df['Sell_Signal']], df['Close'][df['Sell_Signal']],
                marker='v', color='r', s=100, label='Sell Signal')
    ax1.set_title(f'{ticker} Price with MET Signals')
    ax1.legend()

    # 能量场强度EFI
    ax2 = plt.subplot(gs[1])
    ax2.plot(df['EFI'], label='Energy Field Intensity', color='purple')
    ax2.axhline(0.6, linestyle='--', color='orange')
    ax2.axhline(0.4, linestyle='--', color='blue')
    ax2.fill_between(df.index, df['EFI'], 0.6, where=(df['EFI'] >= 0.6),
                     facecolor='red', alpha=0.3)
    ax2.fill_between(df.index, df['EFI'], 0.4, where=(df['EFI'] <= 0.4),
                     facecolor='green', alpha=0.3)
    ax2.set_ylim(0, 1)
    ax2.legend()

    # MET方向
    ax3 = plt.subplot(gs[2])
    ax3.bar(df.index, df['MET_Direction'], color=np.where(df['MET_Direction'] > 0, 'g', 'r'))
    ax3.set_title('MET Direction (Energy Flow)')

    plt.tight_layout()
    plt.show()


# 主程序
if __name__ == "__main__":
    # 参数设置
    ticker = '002364.yahoo'  # 改为你要分析的股票代码
    start_date = '2025-01-01'
    end_date = '2025-03-02'

    # 获取数据
    print(f"Downloading {ticker} data...")
    df = yf.download(ticker, start=start_date, end=end_date)

    # 计算指标
    print("Calculating MET indicators...")
    df = calculate_MET(df)

    # 可视化结果
    print("Generating visualization...")
    visualize_MET(df, ticker)

    # 显示最近20天的EFI值
    print("\nRecent EFI Values:")
    print(df[['Close', 'EFI', 'MET_Direction']].tail(20))

4.Python代码优化2.0

# 导入必要的库
import tushare as ts
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import gridspec

# 初始化pro接口
pro = ts.pro_api('token')  # 请替换为您的Tushare token


# 计算ATR(平均真实波幅)
def calculate_ATR(df, period=14):
    df['H-L'] = df['high'] - df['low']
    df['H-PC'] = abs(df['high'] - df['close'].shift(1))
    df['L-PC'] = abs(df['low'] - df['close'].shift(1))
    df['TR'] = df[['H-L', 'H-PC', 'L-PC']].max(axis=1)
    df['ATR'] = df['TR'].rolling(period).mean()
    return df.drop(['H-L', 'H-PC', 'L-PC', 'TR'], axis=1)


# 市场能量潮(MET)指标计算
def calculate_MET(df, period=14):
    # 价格二阶导数(优化为3日均线加速度)
    df['MA3'] = df['close'].rolling(3).mean()
    df['Price_Derivative2'] = df['MA3'].diff().diff()

    # 成交量势能(增加异常值处理)
    df['Volume_EMA'] = df['vol'].ewm(span=period, min_periods=5).mean()
    df['V_t'] = np.clip(df['vol'] / df['Volume_EMA'], 0.5, 2.0)  # 限制在0.5-2之间

    # 波动率热能(优化EMA计算周期)
    df = calculate_ATR(df, period)
    df['ATR_EMA'] = df['ATR'].ewm(span=period * 2).mean()  # 延长EMA周期
    df['H_t'] = df['ATR'] / df['ATR_EMA']

    # 动态权重系统(三段式分配)
    conditions_gamma = [
        df['H_t'] < 0.3,  # 低波动
        (df['H_t'] >= 0.3) & (df['H_t'] < 0.6),  # 中波动
        (df['H_t'] >= 0.6) & (df['H_t'] < 1.0),  # 高波动
        df['H_t'] >= 1.0  # 极端波动
    ]
    choices_gamma = [0.2, 0.35, 0.5, 0.65]  # 最高权重提升至0.65
    df['Gamma'] = np.select(conditions_gamma, choices_gamma, default=0.4)

    conditions_beta = [
        df['V_t'] < 0.8,
        (df['V_t'] >= 0.8) & (df['V_t'] < 1.2),
        df['V_t'] >= 1.2
    ]
    choices_beta = [0.15, 0.3, 0.45]
    df['Beta'] = np.select(conditions_beta, choices_beta, default=0.3)

    df['Alpha'] = 1 - df['Beta'] - df['Gamma']

    # 自适应标准化(动态窗口)
    volatility_window = df['ATR'].rolling(20).mean() * 10  # 根据波动率调整窗口
    df['Price_Derivative2_norm'] = (df['Price_Derivative2'] - df['Price_Derivative2'].rolling(50).mean()) / df[
        'Price_Derivative2'].rolling(50).std()
    df['V_t_norm'] = (df['V_t'] - df['V_t'].rolling(50).mean()) / df['V_t'].rolling(50).std()
    df['H_t_norm'] = (df['H_t'] - df['H_t'].rolling(50).mean()) / df['H_t'].rolling(50).std()

    # 能量场计算(增加非线性变换)
    df['EFI'] = (
            df['Alpha'] * np.tanh(df['Price_Derivative2_norm']) +
            df['Beta'] * np.log1p(df['V_t_norm']) +
            df['Gamma'] * (df['H_t_norm'] ** 2)
    )

    # MET方向计算(带波动率加权)
    df['MET_Direction'] = df['EFI'].diff().ewm(
        span=3,
        adjust=False
    ).mean() * (1 + df['H_t'] / 10)  # 波动越大方向信号越强

    # 动态阈值系统
    atr_ratio = df['ATR'] / df['ATR'].rolling(20).mean()
    df['Buy_Threshold'] = 0.55 + 0.15 * atr_ratio
    df['Sell_Threshold'] = 0.45 - 0.15 * atr_ratio

    # 动量过滤系统
    df['Momentum_3'] = df['close'].pct_change(3)
    df['Momentum_5'] = df['close'].pct_change(5)
    df['Trend_EMA21'] = df['close'].ewm(span=21).mean()

    # 复合交易信号
    df['Buy_Signal'] = (
            (df['EFI'] > df['Buy_Threshold']) &
            (df['MET_Direction'] > 0) &
            (df['Momentum_3'] > 0) &
            (df['Momentum_5'] > 0) &
            (df['close'] > df['Trend_EMA21'])
    )

    df['Sell_Signal'] = (
            (df['EFI'] < df['Sell_Threshold']) &
            (df['MET_Direction'] < 0) &
            (df['Momentum_3'] < 0)
    )

    return df.drop(['MA3', 'Trend_EMA21'], axis=1)  # 清理中间列


# 可视化函数
def visualize_MET(df, ticker):
    plt.figure(figsize=(16, 12))
    gs = gridspec.GridSpec(3, 1, height_ratios=[3, 1, 2])

    # 价格走势和交易信号
    ax1 = plt.subplot(gs[0])
    ax1.plot(df['trade_date'], df['close'], label='Price', linewidth=1)
    ax1.scatter(df['trade_date'][df['Buy_Signal']], df['close'][df['Buy_Signal']],
                marker='^', color='g', s=100, label='Buy Signal')
    ax1.scatter(df['trade_date'][df['Sell_Signal']], df['close'][df['Sell_Signal']],
                marker='v', color='r', s=100, label='Sell Signal')
    ax1.set_title(f'{ticker} Price with MET Signals')
    ax1.set_xlabel('Date')
    ax1.set_ylabel('Price')
    ax1.legend()

    # 能量场强度EFI
    ax2 = plt.subplot(gs[1])
    ax2.plot(df['trade_date'], df['EFI'], label='Energy Field Intensity', color='purple')
    ax2.axhline(0.6, linestyle='--', color='orange')
    ax2.axhline(0.4, linestyle='--', color='blue')
    ax2.fill_between(df['trade_date'], df['EFI'], 0.6, where=(df['EFI'] >= 0.6),
                     facecolor='red', alpha=0.3)
    ax2.fill_between(df['trade_date'], df['EFI'], 0.4, where=(df['EFI'] <= 0.4),
                     facecolor='green', alpha=0.3)
    ax2.set_ylim(0, 1)
    ax2.set_xlabel('Date')
    ax2.set_ylabel('EFI')
    ax2.legend()

    # MET方向
    ax3 = plt.subplot(gs[2])
    ax3.bar(df['trade_date'], df['MET_Direction'], color=np.where(df['MET_Direction'] > 0, 'g', 'r'))
    ax3.set_title('MET Direction (Energy Flow)')
    ax3.set_xlabel('Date')
    ax3.set_ylabel('MET Direction')

    plt.tight_layout()
    plt.show()


# 主程序
if __name__ == "__main__":
    # 参数设置
    ticker = '603118.SH'  # 改为你要分析的股票代码
    start_date = '20241001'
    end_date = '20250303'

    # 获取数据
    print(f"Downloading {ticker} data...")
    df = pro.daily(ts_code=ticker, start_date=start_date, end_date=end_date)

    # 确保数据按日期升序排列
    df['trade_date'] = pd.to_datetime(df['trade_date'], format='%Y%m%d')
    df = df.sort_values(by='trade_date')

    # 检查数据是否有缺失值
    if df.isnull().values.any():
        print("数据包含缺失值,需要处理缺失值")
        df.dropna(inplace=True)

    # 确保amount和close是数值类型
    df['vol'] = pd.to_numeric(df['vol'], errors='coerce')
    df['close'] = pd.to_numeric(df['close'], errors='coerce')
    df['high'] = pd.to_numeric(df['high'], errors='coerce')
    df['low'] = pd.to_numeric(df['low'], errors='coerce')

    # 计算指标
    print("Calculating MET indicators...")
    df = calculate_MET(df)

    # 可视化结果
    print("Generating visualization...")
    visualize_MET(df, ticker)

    # 显示指定日期范围内的EFI值
    print("\nEFI Values from {} to {}:".format(start_date, end_date))
    print(df[['close', 'EFI', 'MET_Direction']])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值