在交易中,技术分析工具,如 价格通道突破,可以帮助交易者识别潜在的市场机会。价格通道突破可能预示着市场趋势的改变。这种方法可以用 Python 轻松地集成到算法交易系统中。
自动检测价格通道突破,并使用Python处理任何技术信号,是提高分析效率和准确性的绝佳方式。简而言之,算法会为你监控市场,一旦有机会出现就会通知你。我认为Python强大的数据处理库,如pandas、numpy和plotly,使其成为实施算法交易策略的理想工具。当图表上出现潜在机会时,你将收到通知。
在这篇文章中,我将带领你完成使用Python实现价格通道突破指标策略的过程。从设置环境到分析实时数据,本指南会为你提供所有必要的工具和知识,帮助你将这种技术融入你的交易。
好的,我们现在就开始写代码吧
步骤一:搭建您的 Python 开发环境:在详细介绍价格通道突破策略之前,需要先设置Python环境并加载所需的库和数据,这一步非常重要。我们将导入所需的库和加载EUR/USD货币对的历史价格。在这一部分,我们将完成这些任务。完整的代码和数据下载链接以及视频教程链接也都可以获得。
点击这里观看视频: https://youtu.be/Bnv7euL-FxM
导入库模块为了开始,首先我们需要导入几个Python库,这些库将帮助我们进行数据处理、计算和可视化。以下是导入这些库的代码:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pandas as pd # 导入pandas库,用于数据处理
import numpy as np # 导入numpy库,用于数值计算
import plotly.graph_objects as go # 导入plotly库,用于绘制图形
from scipy import stats # 从scipy库中导入stats模块,用于统计分析
- pandas : 该库用于数据处理和分析。它提供了处理结构化数据所需的数据结构和函数。
- numpy : 一个用于 Python 科学计算的基本包,numpy 提供了对大型多维数组和矩阵的支持,以及用于操作这些数组的数学函数集合。
- plotly.graph_objects : Plotly 是一个用于制作交互式且质量上乘的图表的绘图库。graph_objects 模块有助于为我们的数据创建可视化。
- scipy.stats : 该模块包含大量概率分布以及不断增加的统计函数库。我们将需要它来将数据点拟合到直线中……关于这一点我们稍后会详细讨论。
接下来,我们需将历史价格数据加载到pandas DataFrame中。在这个例子中,我们使用了一个包含欧元兑美元的每日烛线数据的CSV文件。这里是如何加载数据:
df = pd.read_csv("EURUSD_Candlestick_1_D_BID_04.05.2003-21.01.2023.csv") # 读取EURUSD的CSV文件
步骤2:检测枢轴点
在这一步里,我们将创建一个函数来检测价格数据中的关键点(又称分形)。关键点是技术分析中用于识别市场潜在反转点的关键指标。它们是图表上的特定价格点,表明市场可能的反转趋势,通过一根蜡烛的最高或最低价格与前后几根蜡烛的最高或最低价格比较来识别。这些点对于绘制价格区间至关重要。
实现枢轴点检测我们将定义一个名为 isPivot
的函数,用来判断我们价格数据中的一个单独的数据点(即特定的蜡烛)是高位、低位,还是两者。该函数会检查当前蜡烛前后指定窗口内的蜡烛,来决定它是否是高位、低位或两者。
下面展示 isPivot
函数的实现:
def isPivot(candle, window):
"""
函数用于检测当前蜡烛是否为顶点或底点。
参数:
candle: 当前蜡烛的索引
window: 以当前蜡烛为中心,前后考虑的蜡烛数
返回:
1 如果是顶点,2 如果是底点,3 如果既是顶点也是底点,默认为0
"""
if candle - window < 0 or candle + window >= len(df):
return 0
pivotHigh = 1
pivotLow = 2
for i in range(candle - window, candle + window + 1):
if df.iloc[candle].Low > df.iloc[i].Low:
pivotLow = 0
if df.iloc[candle].High < df.iloc[i].High:
pivotHigh = 0
if pivotHigh and pivotLow:
return 3
elif pivotHigh:
return pivotHigh
elif pivotLow:
return pivotLow
else:
return 0
弄清楚 isPivot
函数是干嘛的
争论点 :
candle
:DataFrame 中当前烛形的索引。window
:在当前烛形前后各有多少烛形,用于枢转点检测。
逻辑:
- 该函数首先检查当前蜡烛是否在DataFrame的有效范围内。如果不是,它返回0。
- 它初始化了两个变量
pivotHigh
和pivotLow
,分别用于检测高点和低点。 - 然后它在指定窗口内遍历蜡烛。如果找到一个比当前蜡烛低的蜡烛,它将
pivotLow
设置为0。类似地,如果找到一个比当前蜡烛高的蜡烛,它将pivotHigh
设置为0。 - 根据
pivotHigh
和pivotLow
的值,它确定当前蜡烛是高点、低点、两者还是都不是。
isPivot
函数 (这个函数的作用是...)
要使用此功能,您可以遍历 DataFrame 并对每个 candle 应用此功能。例如:
window = 5 # 示例窗口尺寸
df['Pivot'] = [isPivot(i, window) for i in range(len(df))]
# 这一行代码用于在数据框中标识每个枢点
这会创建一个名为 ‘Pivot’ 的新列在 DataFrame 中,该列将包含每个蜡烛的枢转状态。
通过找到这些重要点,我们可以开始画出价格通道,这有助于识别潜在突破。在后面的部分,我们会使用这些点来创建价格通道并分析突破。
步骤3:在蜡烛图上标注枢点这些紫色的点是检测到的分形图案。
在这一步,我们将可视化检测到的枢转点(分形)在蜡烛图(K线图)上。这样的可视化有助于理解潜在的反转可能出现在哪里,并有助于更有效地绘制价格通道。
实现枢转点位置功能我们将定义一个名为 pointpos
的函数来确定枢轴点的定位。此函数有助于将枢轴点稍微置于烛柱之上或之下,使其在图表上更易于看到。
以下是 pointpos
函数的实现
def 点位置(x):
if x['isPivot'] == 2:
return x['Low'] - 1e-3
elif x['isPivot'] == 1:
return x['High'] + 1e-3
else:
return np.nan
解释pointpos
函数:
争论
x
:数据框中的一行。
逻辑
- 如果该行表示一个底点(
isPivot
== 2),函数返回一个比该蜡烛最低价格稍低的值。这确保标记位于蜡烛的下方。 - 如果该行表示一个顶点(
isPivot
== 1),函数返回一个比该蜡烛最高价格稍高的值,从而使标记位于蜡烛的上方。 - 如果该行不是转折点(
isPivot
不是 1 或 2),函数返回np.nan
,这意味着没有放置任何标记。
pointpos
函数
我们对 DataFrame 中的每一行应用 pointpos
函数,以创建一个新的列 pointpos
,这一列用来存放 pivot points 的位置。
# 将每一行传递给pointpos函数并返回结果,将结果存储在新列'pointpos'中
df['pointpos'] = df.apply(lambda row: pointpos(row), axis=1)
可视化关键点
为了可视化这些关键点,我们打算用Plotly来制作一个蜡烛图,并在图上标出这些关键点作为标记。
# 从DataFrame中选取一部分数据进行可视化
dfpl = df[0:100]
# 创建一个K线图
fig = go.Figure(data=[go.Candlestick(x=dfpl.index,
open=dfpl['Open'],
high=dfpl['High'],
low=dfpl['Low'],
close=dfpl['Close'])])
# 将枢转点作为散点图标记添加进去
fig.add_scatter(x=dfpl.index, y=dfpl['pointpos'], mode="markers",
marker=dict(size=5, color="MediumPurple"),
name="pivot")
# 显示这个图表
fig.show()
可视化代码的解释
DataFrame 的子集化:
我们选择 DataFrame 的前 100 行(dfpl = df.iloc[:100]
)进行可视化,这样可以在较小的数据集上更清楚地观察到关键点。
绘制蜡烛图 :
我们使用 Plotly 的 go.Candlestick
用来显示 open
、high
、low
和 close
價格的 K 线图。
添加枢点:
我们使用 fig.add_scatter()
将关键点添加到图表中。这些关键点以指定大小和颜色(如 MediumPurple
)的散点形式显示。
显示这个图表:
最后,我们用 fig.show()
显示一下图。
在这一步里,我们实现检测高低价格通道的核心功能模块。正是在这里,所有的“魔法”发生,它将用来识别潜在的机会突破。
频道将被算法自动检测到
实施通道检测功能我们将定义一个名为 collect_channel
的函数,该函数会分析给定蜡烛图周围的蜡烛图窗口,以确定代表高和低通道的线性回归线。
下面是如何实现collect_channel
函数:
定义收集通道(candle, backcandles, window):
localdf = df[candle-backcandles-window:candle-window]
localdf['isPivot'] = localdf.apply(lambda x: isPivot(x.name, window), axis=1)
高点 = localdf[localdf['isPivot'] == 1]['High'].values
高点索引 = localdf[localdf['isPivot'] == 1]['High'].index
低点 = localdf[localdf['isPivot'] == 2]['Low'].values
低点索引 = localdf[localdf['isPivot'] == 2]['Low'].index
如果 len(低点) >= 2 and len(高点) >= 2:
sl_lows, interc_lows, r_value_l, _, _ = stats.linregress(低点索引, 低点)
sl_highs, interc_highs, r_value_h, _, _ = stats.linregress(高点索引, 高点)
返回 (sl_lows, interc_lows, sl_highs, interc_highs, r_value_l**2, r_value_h**2)
否则:
返回 (0, 0, 0, 0, 0, 0)
解释collect_channel
函数
争论点
candle
:当前K线在DataFrame中的位置。backcandles
:查找通道时需要查看的过去K线数量。window
:每个点周围考虑的K线数量,用于检测支撑和阻力点。
逻辑上:
- 该函数创建一个包含指定回溯周期(
backcandles
)内蜡烛图的DataFrame子集(localdf
),该子集包括所选窗口。 - 它将
isPivot
函数应用于子集中每一行,以识别转折点。 - 并提取这些转折点的最高价和最低价。
- 如果至少有两个最高转折点和两个最低转折点,它将对这些点进行线性回归,以确定代表最高通道和最低通道的直线的斜率和截距。
- 它返回回归线的斜率、截距和R平方值。如果转折点不足,则返回零值。
collect_channel
功能
如果你想使用这个功能,可以用合适的参数调用它来检测某个特定蜡烛周围的指标。例如:
热度 = 100 # candle
历史热度 = 20 # backcandles
窗口 = 5 # window
通道信息 = collect_channel(热度, 历史热度, 窗口) # channel_info = collect_channel(candle, backcandles, window)
这个调用会返回指定的蜡烛的高通道和低通道的斜率和截距值,以及对应的R平方值。
第5步:可视化检测到的频道在接下来的步骤中,我们将可视化检测到的高低通道线在蜡烛图上。这种可视化将帮助我们看到价格如何与这些通道相互作用,并识别潜在的突破点。
搭建可视化界面我们将利用之前实现的 collect_channel
函数来检测通道线,并将这些通道线与蜡烛图和枢轴点一起绘制出来。
以下为通道可视化完整代码如下:
candle = 75
backcandles = 40
window = 3
# 选择DataFrame的一部分数据用于可视化
dfpl = df[candle-backcandles-window-5:candle+200]
# 绘制一个蜡烛图
fig = go.Figure(data=[go.Candlestick(x=dfpl.index,
open=dfpl['Open'],
high=dfpl['High'],
low=dfpl['Low'],
close=dfpl['Close'])])
# 将枢点位置标记为散点图
fig.add_scatter(x=dfpl.index, y=dfpl['pointpos'], mode="markers",
marker=dict(size=5, color="MediumPurple"),
name="pivot")
# 利用collect_channel函数来检测通道
sl_lows, interc_lows, sl_highs, interc_highs, r_sq_l, r_sq_h = collect_channel(candle, backcandles, window)
print(f"低点R平方: {r_sq_l}, 高点R平方: {r_sq_h}")
# 生成通道线所需x值
x = np.array(range(candle-backcandles-window, candle+1))
# 将下通道线添加到图表
fig.add_trace(go.Scatter(x=x, y=sl_lows*x + interc_lows, mode='lines', name='Lower Channel'))
# 将上通道线添加到图表
fig.add_trace(go.Scatter(x=x, y=sl_highs*x + interc_highs, mode='lines', name='Upper Channel'))
# 展示图表
fig.show()
关于可视化代码的解释
选择数据子集这一步:
我们选择了一个包含围绕指定蜡烛的一段蜡烛范围的 DataFrame (dfpl
) 的子集。这段范围被选来提供足够的上下文来检测通道时使用。
制作烛台图 :
使用Plotly的go.Candlestick
来创建蜡烛图表,以显示open
、high
、low
和close
价格。
添加支点
我们使用 fig.add_scatter()
在图表上添加关键点,并用紫色的点标记它们。
检测频道 :
我们使用 collect_channel
函数来识别指定的蜡烛周围的高低通道。该函数会返回通道的斜率、截距及 R 方值。
打印R²值:
我们分别打印高频道和低频道的 R 方值,以评估回归线的拟合情况。
生成频道的内容
我们计算通道的X值,这些值涵盖了从历史期开始到指定的K线之间的时间段。
添加通道到走势图:
我们使用 fig.add_trace()
将上通道线和下通道线添加到图表中,基于检测到的斜率和截距以它们为线进行绘制。
显示一下图表:
最后,我们通过 fig.show()
显示图表,展示包含支撑和阻力位及识别出的趋势通道的蜡烛图(K线图)。
在这一步中,我们将实现一个功能来检测从已识别的价格通道的突破。当价格突破通道的高点或低点时,即发生了突破,这表明可能的趋势转变。
实现断点续传功能我们将定义一个叫作 isBreakOut
的函数,用于检查特定的蜡烛是否表示为从价格通道的突破。
以下为 isBreakOut
函数的实现:
# 定义 isBreakOut 函数来判断是否突破通道
def isBreakOut(candle, backcandles, window):
if (candle - backcandles - window) < 0:
return 0
sl_lows, interc_lows, sl_highs, interc_highs, r_sq_l, r_sq_h = collect_channel(candle, backcandles, window) # 收集通道参数
prev_idx = candle - 1
prev_high = df.iloc[candle - 1].High # 计算前一蜡烛的高点
prev_low = df.iloc[candle - 1].Low # 计算前一蜡烛的低点
prev_close = df.iloc[candle - 1].Close # 计算前一蜡烛的收盘价
curr_idx = candle
curr_high = df.iloc[candle].High # 计算当前蜡烛的高点
curr_low = df.iloc[candle].Low # 计算当前蜡烛的低点
curr_close = df.iloc[candle].Close # 计算当前蜡烛的收盘价
curr_open = df.iloc[candle].Open # 计算当前蜡烛的开盘价
if (prev_high > (sl_lows * prev_idx + interc_lows) and # 检查前一蜡烛是否高于下轨线
prev_close < (sl_lows * prev_idx + interc_lows) and # 检查前一蜡烛收盘价是否低于下轨线
curr_open < (sl_lows * curr_idx + interc_lows) and # 检查当前蜡烛开盘价是否低于下轨线
curr_close < (sl_lows * prev_idx + interc_lows)): # _r_sq_l 应大于 0.9
return 1
elif (prev_low < (sl_highs * prev_idx + interc_highs) and # 检查前一蜡烛是否低于上轨线
prev_close > (sl_highs * prev_idx + interc_highs) and # 检查前一蜡烛收盘价是否高于上轨线
curr_open > (sl_highs * curr_idx + interc_highs) and # 检查当前蜡烛开盘价是否高于上轨线
curr_close > (sl_highs * prev_idx + interc_highs)): # r_sq_h 应大于 0.9
return 2
else:
return 0
关于 isBreakOut
函数 (是否要退出的判断) 的一些解释。
观点
candle
:当前烛线在数据框中的位置索引。backcandles
:识别通道时回溯的烛线数量。window
:检测每个点的转折点时考虑的前后烛线数量。
逻辑:
- 该函数首先检查是否有足够的数据来进行分析。如果没有,返回0。
- 它调用
collect_channel
函数以获取高低通道的斜率和截距值。 - 它获取前一根和当前烛台的高低开收价。
- 然后它检查前一根和当前烛台是否符合高、低通道的突破条件。
- 如果检测到低通道下方的突破,返回1;如果检测到高通道上方的突破,返回2。否则,返回0。
isBreakOut
函数
要使用此功能,您可以遍历DataFrame中的每一根K线,并对每一根K线应用该功能。例如:
breakout_signals = [isBreakOut(i, backcandles, window) for i in range(len(df))] # 遍历df的长度
df['突破'] = breakout_signals # df['BreakOut'] = breakout_signals
这将创建一个名为BreakOut
的新列,在DataFrame中包含每个K线图的突破情况。
在这一步中,我们将可视化在K线图上检测到的突破点。这样的可视化有助于清晰地识别突破点发生在价格通道中的哪些地方。
实现突破位置功能我们将定义一个名为 breakpointpos
的函数来确定突破标记的位置。此函数会将突破标记置于蜡烛图稍上方或下方,以便在图表中更清晰地显示。
以下是指 breakpointpos
函数的实现代码:
def breakpointpos(x):
# breakpointpos 函数根据isBreakOut的值计算断点位置
# x 是包含isBreakOut, Low, High等属性的字典
if x['isBreakOut'] == 2:
# 如果isBreakOut等于2,返回低点减去0.003
return x['Low'] - 3e-3
elif x['isBreakOut'] == 1:
# 如果isBreakOut等于1,返回高点加上0.003
return x['High'] + 3e-3
else:
# 否则返回nan
return np.nan
# np.nan 表示不是一个数字(Not a Number)
破位检测与可视化
我们将isBreakOut
函数应用于选定数据范围内的每根K线,然后将这些突破与K线图和支撑点阻力点一起可视化展示。
以下是如何检测和可视化突破点的完整代码。
candle = 75
backcandles = 40
window = 3
# 选择用于可视化的数据帧子集
dfpl = df[candle-backcandles-window-5:candle+20]
# 识别选定子集中的突破点
dfpl["isBreakOut"] = [isBreakOut(candle, backcandles, window) for candle in dfpl.index]
# 确定突破点的位置
dfpl['breakpointpos'] = dfpl.apply(lambda row: breakpointpos(row), axis=1)
candle = 59
# 创建蜡烛图
fig = go.Figure(data=[go.Candlestick(x=dfpl.index,
open=dfpl['Open'],
high=dfpl['High'],
low=dfpl['Low'],
close=dfpl['Close'])])
# 将转折点作为散点图标记添加到图表中
fig.add_scatter(x=dfpl.index, y=dfpl['pointpos'], mode="markers",
marker=dict(size=5, color="MediumPurple"),
name="pivot")
# 将突破点作为散点图标记添加到图表中
fig.add_scatter(x=dfpl.index, y=dfpl['breakpointpos'], mode="markers",
marker=dict(size=8, color="Black"), marker_symbol="hexagram",
name="breakout")
# 使用collect_channel函数检测通道
sl_lows, interc_lows, sl_highs, interc_highs, r_sq_l, r_sq_h = collect_channel(candle, backcandles, window)
print(f"低点R²: {r_sq_l}, 高点R²: {r_sq_h}")
# 生成通道边界线的x值
x = np.array(range(candle-backcandles-window, candle+1))
# 将下通道边界线添加到图表中
fig.add_trace(go.Scatter(x=x, y=sl_lows*x + interc_lows, mode='lines', name='下通道'))
# 将上通道边界线添加到图表中
fig.add_trace(go.Scatter(x=x, y=sl_highs*x + interc_highs, mode='lines', name='上通道'))
# 显示图形
fig.show()
快速回顾一下这里的步骤:
我们选择 DataFrame(dfpl
)的一个子集,其中包括围绕指定蜡烛的一段范围内的蜡烛,以便可视化。正在检测。
我们使用 isBreakOut
函数来识别所选子集中每根 K 线是否突破。对于每根 K 线,该函数会判断是否发生突破。
我们将breakpointpos
函数应用于选定子集的每一行,以确定断点的位置。
我们使用Plotly的go.Candlestick
创建了一个蜡烛图图表,展示了‘open’、‘high’、‘low’和‘close’的价格信息。
我们用紫色点标记关键点,并使用 fig.add_scatter()
将其添加到图表中。
我们用 fig.add_scatter()
在图表中添加这些点,并用黑色星形标记它们(图中的星形)。
我们使用 collect_channel
函数来识别指定蜡烛图周围的高通道线和低通道线。这样,该函数会返回通道的斜率和截距。
我们创建通道线的x坐标,这些坐标覆盖了从回溯期间开始到指定蜡烛的时间段。
我们使用 fig.add_trace()
方法将这些线条添加到图表中,根据检测到的斜率和截距,将它们以线条形式绘制为上下通道的线条。
最后,我们使用 fig.show()
来显示图表,展示带有支撑点、检测到的趋势线和突破位的蜡烛图(K线图)。
我们在可能的突破位置添加了星形或六角星标记。算法会遍历数据,检测任何有效的通道,并在突破发生时进行标记。这里展示的例子与绘制的通道线有关。收盘时,该蜡烛的收盘价低于通道下部的紫色线,这是因为收盘时该蜡烛的收盘价低于通道下部的紫色线,所以我们在图表上用六角星标记了这次向下突破。
此算法可以用来检测并交易突破,我们也可以在历史数据上对策略进行全面回测……,但这留待以后再说。
感谢你这么久的陪伴!下次见之前,好好享受编程挑战,如果涉及交易,一定要注意安全哦!