Python 中的 VWAP 算法策略

[文献精汇]Python 中的 VWAP 算法策略

使用 Python 中的 VWAP 和移动平均线策略进行比特币算法交易回测。我们将深入探讨算法交易的 VWAP(成交量加权平均价格)和移动平均线 (MA) 指标的详细比较。

VWAP 和移动平均线是交易者中流行的工具,每种工具都提供独特的见解。移动平均线提供了简单的价格平均值,而 VWAP 通过结合交易量提供了更微妙的视角。这种区别对于确定证券是被高估还是被低估至关重要。我们将讨论为什么 VWAP 经常受到交易者的青睐,以及它如何作为动态支撑位和阻力位。

我将指导您完成 VWAP 的计算,强调由于其成交量加权性质,它相对于移动平均线的重要性。

第 1 步:数据导入和预处理

第一步,我们导入并预处理比特币交易数据,为分析做准备。该过程涉及以下操作:

import pandas as pd

# Load the Bitcoin trading data from a CSV file
df = pd.read_csv("BTCUSD_Candlestick_15_M_ASK_05.08.2019-29.04.2022.csv")

# Clean the "Gmt time" column by removing the ".000" suffix
df["Gmt time"] = df["Gmt time"].str.replace(".000", "")

# Convert the "Gmt time" column to datetime format
df['Gmt time'] = pd.to_datetime(df['Gmt time'], format='%d.%m.%Y %H:%M:%S')

# Set the "Gmt time" column as the index of the DataFrame
df.set_index("Gmt time", inplace=True)

# Remove rows where the high and low prices are equal
df = df[df.High != df.Low]
  • Clean the "Gmt time" column 清理时间列:通过从时间戳字符串中删除".000"后缀来清理"Gmt 时间"列,以确保日期时间格式正确。
  • Convert the "Gmt time" column 转换为日期时间:使用 pd.to_datetime 函数将清理后的"Gmt 时间"列转换为日期时间格式,并指定正确的解析格式。
  • Remove rows 过滤数据:从 DataFrame 中删除最高价和最低价相等的行,以确保交易数据有意义。

第 2 步:计算指标

第二步,我们使用 pandas_ta 库计算 VWAP (成交量加权平均价格) 和 EMA (指数移动平均线) 指标。

import pandas_ta as ta

# Calculate VWAP (Volume Weighted Average Price) and add it to the DataFrame
df["VWAP"] = ta.vwap(df.High, df.Low, df.Close, df.Volume)

# Calculate EMA (Exponential Moving Average) with a length of 100 periods and add it to the DataFrame
df["EMA"] = ta.ema(df.Close, length=100)
  • 计算 VWAP:VWAP 指标使用最高价、最低价、收盘价和成交量数据计算。VWAP 将作为名为 "VWAP" 的新列添加到 DataFrame 中。
  • 计算 EMA:EMA 指标是针对指定长度为 100 个周期的收盘价计算的。EMA 将作为名为 "EMA" 的新列添加到 DataFrame 中。

第 3 步:生成 EMA 信号

在第三步中,我们根据指数移动平均线 (EMA) 生成交易信号。这些信号将帮助我们确定潜在的买入和卖出机会。我们根据指定回溯期内的最高价、最低价和 EMA 值之间的关系来识别潜在的交易信号。

该信号检查回溯期内的所有蜡烛是否完全高于或完全低于 EMA。如果它们都在上方,则表明上升趋势;如果它们都低于下方,则表明 backcandles 窗口内出现下降趋势。

# Initialize the EMASignal list with zeros
emasignal = [0] * len(df)

# Define the lookback period
backcandles = 6

# Loop through the DataFrame starting from the lookback period to the end
for row in range(backcandles, len(df)):
    upt = 1
    dnt = 1
    # Check the conditions for the past backcandles periods
    for i in range(row - backcandles, row + 1):
        if df.High[i] >= df.EMA[i]:
            dnt = 0
        if df.Low[i] <= df.EMA[i]:
            upt = 0
    # Set the EMASignal based on the conditions
    if upt == 1and dnt == 1:
        emasignal[row] = 3
    elif upt == 1:
        emasignal[row] = 2
    elif dnt == 1:
        emasignal[row] = 1

# Add the EMASignal to the DataFrame
df['EMASignal'] = emasignal

/var/folders/d9/rbb57jqn3g133_ynk3vgz02c0000gn/T/ipykernel_38122/1407699409.py:13: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  if df.High[i] >= df.EMA[i]:
/var/folders/d9/rbb57jqn3g133_ynk3vgz02c0000gn/T/ipykernel_38122/1407699409.py:15: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  if df.Low[i] <= df.EMA[i]:
  • 初始化信号列表:我们创建一个名为 emasignal 的列表,其中填充了零,对应于 DataFrame 的长度。
  • 设置回溯周期: 我们定义一个变量 backcandles 来指定我们将回溯以检查信号条件的周期数。
  • 遍历数据:我们从 backcandles 索引开始遍历 DataFrame,直到 DataFrame 的末尾。
  • 检查条件:对于每一行,我们将两个变量 upt 和 dnt 初始化为 1,分别表示上升和下降趋势。然后,我们遍历过去的 backcandles 周期以检查以下条件:
  • 如果当前蜡烛的最高价大于或等于 EMA,则将 dnt 设置为 0。
  • 如果当前蜡烛的最低价小于或等于 EMA,则设置为 0。
  • 设置信号:
  • 如果 upt 和 dnt 都保持 1,则将信号设置为 3(表示没有明显的趋势)。
  • 如果只有 upt 为 1,则将信号设置为 2 (表示潜在的上升趋势)。
  • 如果只有 dnt 为 1,则将信号设置为 1(表示潜在的下降趋势)。

向 DataFrame 添加信号:最后,我们将生成的信号添加到 DataFrame 中名为 EMASignal 的新列中。

python 代码也可以使用切片编写,这更像是一种 python 编码方式:

# Initialize the EMASignal list with zeros
emasignal = [0] * len(df)

# Define the lookback period
backcandles = 6

# Loop through the DataFrame starting from the lookback period to the end
for row in range(backcandles, len(df)):
    # Slicing the relevant window of high, low, and EMA values
    high_slice = df.High[row - backcandles: row + 1]
    low_slice = df.Low[row - backcandles: row + 1]
    ema_slice = df.EMA[row - backcandles: row + 1]

    # Check the conditions for uptrend and downtrend
    upt = all(high_slice >= ema_slice)
    dnt = all(low_slice <= ema_slice)

    # Set the EMASignal based on the conditions
    if upt and dnt:
        emasignal[row] = 3
    elif upt:
        emasignal[row] = 2
    elif dnt:
        emasignal[row] = 1

# Add the EMASignal to the DataFrame
df['EMASignal'] = emasignal
相关推荐
wjs202415 分钟前
Ruby 中文编码
开发语言
山语山27 分钟前
C#多线程精解
开发语言·数据库·后端·c#
海绵波波10728 分钟前
RAG(Retrieval-Augmented Generation,检索增强生成)流程
python·语言模型
froginwe1138 分钟前
SQLite AND/OR 运算符
开发语言
我是唐青枫41 分钟前
C# Lambda 表达式详解
开发语言·c#·.net
ADwwC1 小时前
已知n找最小正整数x使n*x为一个平方数
算法
CharlesC++1 小时前
JAVA类和对象练习
java·开发语言
编码浪子1 小时前
进军AI大模型-Langchain程序部署
linux·python·langchain
huluang1 小时前
构建JS全栈开发的CMS系统——从零开始搭建前后端
开发语言·javascript·ecmascript
北极糊的狐1 小时前
vue2框架配置路由设计打印单
开发语言·前端·javascript