欢迎来到这个教程,学习如何使用Python进行算法交易。今天,我们将重点介绍如何结合相对强弱指数(RSI)和支持阻力位来生成高质量的交易信号和入场点提醒。在本文结束时,您将了解如何在Python中结合使用这些技术指标,以及如何仅使用Python语言在历史数据上对您的策略进行可视化展示。
你将学到的内容- 检测支撑位和阻力位
- 利用RSI进行趋势分析
- 结合RSI与支撑位和阻力位进行分析
- 用Python编写自定义指标
- 可视化并分析结果
优惠券算法交易 https://bit.ly/CouponAlgorithmicTrading
https://bit.ly/CouponMachineLearningTrading (机器学习交易优惠券)
在本教程中,我使用的Jupyter笔记本和数据文件,以及完整视频中的详细说明,都可以下载使用。
步骤 1:导入库文件和加载数据:首先,我们从导入所需的库并加载数据集文件开始。我们将使用pandas
库进行数据操作,以及使用pandas_ta
库来计算技术分析指标。
import pandas as pd
import pandas_ta as ta
# 加载 EUR/USD 每小时蜡烛图数据
df = pd.read_csv("EURUSD_Candlestick_1_Hour_BID_04.05.2003-15.04.2023.csv")
# 移除成交量为零的行
df = df[df['volume'] != 0]
# 删除行后使用 drop=True 和 inplace=True 参数重置索引
df.reset_index(drop=True, inplace=True)
# 检查数据集中是否有 NA 值
df.isna().sum()
# 计算相对强弱指标 (RSI),长度为 12
df['RSI'] = ta.rsi(df['close'], length=12)
# 显示数据框的最后一部分
df.tail()
解释:
导入所需的库:
pandas as pd
: 用于数据操作。pandas_ta as ta
: 用于技术分析的指标。
加载数据这一步:
- 数据是从名为
EURUSD_Candlestick_1_Hour_BID_04.05.2003-15.04.2023.csv
的 CSV 文件中加载的数据集。 - 这个文件包含 EUR/USD 货币对的每小时蜡烛图,包括开盘、最高、最低和收盘价,以及成交量。
数据清理:即将数据中的错误和不一致之处移除或修正的过程。
- 删除体积为零的行记录,以确保数据质量的准确性。
- 删除这些记录后,重置索引序列以保持索引的整洁与连续性。
检查缺失值:
- 代码会检查数据集中的任何NA值,这对分析时确保数据完整性非常重要。
计算相对强弱指数(RSI):
- 相对强弱指数(RSI)是使用12的周期数来计算的。RSI是一种动量振荡器,用于衡量价格变化的速度,有助于识别出超买或超卖状态。
数据显示如下:
- 数据框尾部的几行被显示出来以验证这些RSI值是否已正确添加到数据集中。
通过遵循这些步骤,我们确保我们的数据干净整洁,准备好进行进一步分析和应用我们的交易策略。
步骤2:找出支撑位和阻力位在接下来这一步,我们定义用于检测的函数来识别数据集中的支撑位和阻力位。支撑位和阻力位对于识别关键的价格点至关重要,这些价格点通常是市场反转的地方。
wick_threshold = 0.0001 # 定义一个影线阈值 wick_threshold 为 0.0001
def support(df1, l, n1, n2): # n1 和 n2 分别代表在第 l 根烛线之前和之后的蜡烛数量
if ( df1.low[l-n1:l].min() < df1.low[l] or
df1.low[l+1:l+n2+1].min() < df1.low[l] ):
return 0
candle_body = abs(df1.open[l] - df1.close[l])
lower_wick = min(df1.open[l], df1.close[l]) - df1.low[l]
if (lower_wick > candle_body) and (lower_wick > wick_threshold):
return 1
return 0
def resistance(df1, l, n1, n2): # n1 和 n2 分别代表在第 l 根烛线之前和之后的蜡烛数量
if ( df1.high[l-n1:l].max() > df1.high[l] or
df1.high[l+1:l+n2+1].max() > df1.high[l] ):
return 0
candle_body = abs(df1.open[l] - df1.close[l])
upper_wick = df1.high[l] - max(df1.open[l], df1.close[l])
if (upper_wick > candle_body) and (upper_wick > wick_threshold):
return 1
return 0
解释:
定义 Wick 阈值(火柴芯阈值):
wick_threshold = 0.0001
:此阈值用于过滤不重要的蜡烛线的影线,只有超过此阈值的影线才会被用来确定支撑和阻力水平。
支持性的功能:
support
函数检查某个蜡烛(索引l
的蜡烛)是否可以被视为支撑位。- 它将当前蜡烛的低点与周围蜡烛(当前蜡烛之前
n1
个和之后n2
个)的低点进行比较。 - 如果当前蜡烛的低点不低于周围的低点,则返回 0(不是支撑位)。
- 如果下影线(低点与开盘价和收盘价中的较低值之间的差)大于蜡烛实体且大于影线阈值,则返回 1(表示支撑位)。
- 抗阻功能:这是一种常见的术语,用来描述系统或组件抵抗外部影响的能力。
resistance
函数判断一根蜡烛(位于索引l
)是否可以被视为阻力位。它将当前蜡烛的高与周围n1
根之前和n2
根之后的蜡烛高进行比较。如果当前蜡烛的高低于或等于周围的高,则返回 0(不是阻力)。如果上影线(高与开盘或收盘价较高值之间的差值)大于蜡烛实体且超过影线阈值,则返回 1(表示是一个阻力水平)。
这些功能使我们能够通过分析蜡烛图形态及其周围的蜡烛来检测潜在的支持位和阻力位。这为识别可能对未来的市场走势产生影响的关键价位奠定了基础。
步骤三:检查与支撑位和阻力位的接近情况在这一步中,我们定义函数来检查当前的蜡烛是否接近任何之前识别的支持或阻力位。这有助于确认价格是否会遵循这些水平。
def closeResistance(l, levels, lim, df):
如果 levels 的长度为 0, 则直接返回 0
nearest_level = min(levels, key=lambda x: abs(x - df 的最高价[l]))
c1 = 如果 df 的最高价[l] 与 nearest_level 的绝对差值小于或等于 lim
c2 = 如果 max(df 的开盘价[l], df 的收盘价[l]) 与 nearest_level 的绝对差值小于或等于 lim
c3 = 如果 min(df 的开盘价[l], df 的收盘价[l]) 小于 nearest_level
c4 = 如果 df 的最低价[l] 小于 nearest_level
如果 (c1 或 c2) 并且 c3 并且 c4, 则返回 nearest_level
否则:
返回 0
def closeSupport(l, levels, lim, df):
如果 levels 的长度为 0, 则直接返回 0
nearest_level = min(levels, key=lambda x: abs(x - df 的最低价[l]))
c1 = 如果 df 的最低价[l] 与 nearest_level 的绝对差值小于或等于 lim
c2 = 如果 min(df 的开盘价[l], df 的收盘价[l]) 与 nearest_level 的绝对差值小于或等于 lim
c3 = 如果 max(df 的开盘价[l], df 的收盘价[l]) 大于 nearest_level
c4 = 如果 df 的最高价[l] 大于 nearest_level
如果 (c1 或 c2) 并且 c3 并且 c4, 则返回 nearest_level
否则:
返回 0
解释:
接近于阻力区域 (closeResistance
函数):
参数设置:
l
: 当前蜡烛的索引。levels
: 已识别的阻力水平列表。lim
: 被认为是接近的水平的临界值。df
: 包含K线数据的DataFrame。
逻辑:
- 该函数计算距离当前蜡烛最高价最近的阻力位。
- 检查几个条件以确认接近度:
c1
:当前蜡烛的最高价是否接近最近的阻力位。c2
:开盘价或收盘价中较高的一个是否接近最近的阻力位。c3
:开盘价或收盘价中较低的一个是否低于最近的阻力位。c4
:当前蜡烛的最低价是否低于最近的阻力位。- 如果满足这些条件,则返回最近的阻力位;否则返回0。
接近支撑水平 (closeSupport
函数):
参数:
l
: 当前蜡烛图的索引。levels
: 已识别的支撑水平列表。lim
: 接近限值,用于判断某个水平是否足够接近。df
: 包含蜡烛图数据的DataFrame。
逻辑:
- 该函数计算当前蜡烛最低价最近的支撑位。
- 检查几个条件来确认接近程度:
c1
:当前蜡烛的最低价在最近支撑位的接近范围内。c2
:开盘价和收盘价中较低的那个在最近支撑位的接近范围内。c3
:开盘价和收盘价中较高的那个在最近支撑位之上。c4
:当前蜡烛的最高价在最近支撑位之上。- 如果所有条件都满足,则返回最近的支撑位;否则,返回0。
这些工具有助于识别当前的价格走势是否接近任何重要的支撑或阻力位,这可以用来生成潜在的交易信号或机会。
接下来,我们将把这些函数应用到我们的数据集上,并从数据中生成信号。
第4步:确认趋势是否符合支撑位和阻力位
在这一步里,我们定义函数来检查价格是否持续低于阻力位或高于支撑位,超过指定数量的过去蜡烛图。这有助于确认趋势方向并增强我们信号生成的可靠性。
def 判断是否在阻力位下方(l, level_backCandles, level, df):
# 判断在给定的回溯周期内最高价是否低于给定的阻力位
return df.loc[l-level_backCandles:l-1, 'high'].max() < level
def 判断是否在支撑位上方(l, level_backCandles, level, df):
# 判断在给定的回溯周期内最低价是否高于给定的支撑位
return df.loc[l-level_backCandles:l-1, 'low'].min() > level
说明:
检查价格是否在阻力线下方(如下is_below_resistance
函数)。
参数:
l
: 当前蜡烛的索引。level_backCandles
: 要考虑的过去蜡烛的数量。level
: 需要检查的阻力水平。df
: 包含蜡烛数据的DataFrame。
逻辑:
- 该函数检查过去
level_backCandles
根 K 线中的最高价格是否低于指定的阻力水平。 - 如果满足条件,即价格走势在阻力水平之下,则返回
True
,否则返回False
。
检查价格是否高于支撑位 (is_above_support
函数)
参数:
l
: 当前蜡烛的索引。level_backCandles
: 回溯检查的蜡烛数量。level
: 支撑水平。df
: 包含蜡烛图数据的数据框。
按逻辑来说:
- 该函数检查过去
level_backCandles
根 K 线的最低价是否高于支撑位。 - 如果价格高于支撑位,返回
True
,否则返回False
。
这些函数非常有用,可以验证价格行为是否在特定时间段内尊重已确认的支持和阻力水平。这一步验证有助于确保这些水平确实有效,且趋势稳定。
接下来,我们将把这些检查整合到信号生成流程中,以增强交易信号的可靠性。
第五步:生成交易指示信号在这一环节中,我们定义一个名为 check_candle_signal
的函数来根据已识别的支持和阻力水平、接近这些水平和 RSI 值生成交易信号。此函数结合了之前的所有组件以判断是否有交易信号。
def check_candle_signal(l, n1, n2, backCandles, df):
ss = []
rr = []
for subrow in range(l - backCandles, l - n2):
if support(df, subrow, n1, n2):
ss.append(df.low[subrow])
if resistance(df, subrow, n1, n2):
rr.append(df.high[subrow])
# 移除接近的支撑水平
ss.sort() # 弹出时保留较低的支撑水平
for i in range(1, len(ss)):
if i >= len(ss):
break
if abs(ss[i] - ss[i - 1]) <= 0.0001:
ss.pop(i)
# 移除接近的阻力水平
rr.sort(reverse=True) # 弹出时保留较高的阻力水平
for i in range(1, len(rr)):
if i >= len(rr):
break
if abs(rr[i] - rr[i - 1]) <= 0.0001:
rr.pop(i)
# 合并支撑和阻力水平并移除接近的水平
rrss = rr + ss
rrss.sort()
for i in range(1, len(rrss)):
if i >= len(rrss):
break
if abs(rrss[i] - rrss[i - 1]) <= 0.0001:
rrss.pop(i)
cR = closeResistance(l, rrss, 150e-5, df)
cS = closeSupport(l, rrss, 150e-5, df)
# 决定交易信号
if (cR and is_below_resistance(l, 6, cR, df) and df.RSI[l - 1:l].min() < 45): # 且 df.RSI[l] > 65
return 1
elif (cS and is_above_support(l, 6, cS, df) and df.RSI[l - 1:l].max() > 55): # 且 df.RSI[l] < 35
return 2
else:
return 0
解释:
识别支撑位和阻力位
- 该函数在指定的
backCandles
范围内进行迭代,利用support
和resistance
函数来识别支撑和阻力。 - 识别出的支撑会被添加进列表
ss
,阻力会被添加进列表rr
。
合并相近级别:
- 支撑位按照顺序进行排序,相近的支撑位通过移除在指定距离(
0.0001
)内的较近支撑位来合并。 - 阻力位也同样会经历同样的处理步骤,阻力位从高到低排序以保持最高的阻力位。
结合层次:
- 支撑和阻力水平合并到一个单一的列表
rrss
并进行排序。 - 在合并列表中,接近的点也被合并,通过移除距离小于0.0001的水平。
检查接近程度:
- 该函数使用
closeResistance
和closeSupport
检查当前K线是否接近任何合并的支持和阻力线。
生成交易信号的方法:
当满足以下条件时会生成一个上涨信号(返回 1
)。
- 蜡烛靠近一个阻力位 (
cR
)。 - 过去6根蜡烛的价格都低于这个阻力位。
- 最近一段时间内的RSI值最低低于45。
当出现以下情况时,将生成一个空头信号(返回 2
),这表明市场进入了一个看跌的状态:
- 蜡烛接近支撑位 (
cS
)。 - 过去6根蜡烛的价格都高于此支撑位。
- 最近的RSI峰值高于55。
- 如果以上两个条件都不满足,则返回
0
,表示没有信号。
该功能整合了之前的检查和计算,以决定是否根据支撑位、阻力位和RSI指标生成交易信号。
第六步:交易策略应用在这一步里,我们将使用check_candle_signal
函数逐个检查每个蜡烛,并根据定义判断它们是否符合交易信号的要求。
导入 tqdm 模块
n1 = 8
n2 = 6
backCandles = 140
signal = [0 for i in range(len(df))]
for row in tqdm(range(backCandles + n1, len(df) - n2)):
signal[row] = check_candle_signal(row, n1, n2, backCandles, df)
df["signal"] = signal
解释:
设置参数吧:
-
n1 = 8
:检查当前蜡烛前8根蜡烛是否有支撑/阻力。 -
n2 = 6
:检查当前蜡烛后6根蜡烛是否有支撑/阻力。 backCandles = 140
:生成信号时考虑过去140根蜡烛。
开始初始化信号清单:
signal = [0 for i in range(len(df))]
: 初始化一个与 DataFrame 长度相同的零列表用于存放信号。
生成信号:
tqdm
:这用于显示循环中的进度条,在处理大型数据集时特别有用。- 遍历从
backCandles + n1
到len(df) - n2
的每一行。 - 对于每一行,检查是否满足
check_candle_signal
函数定义的信号标准。 - 将结果添加到
signal
列表中。
向数据帧添加信号:
df["signal"] = signal
:把生成的信号加入到DataFrame中,新列的名字叫'signal'。
这个过程系统地将交易策略应用于整个数据集中的每个数据点,根据设定的标准为每个K线图生成信号。
接下来,我们将对结果进行分析和可视化,以评估我们的检测系统的性能。
第七步:可视化交易信号图在这一步,我们定义一个函数来确定信号生成点的位置,并将这些信息添加到DataFrame中。这有助于在价格图表上更清晰地展示信号。
import numpy as np # (即 numpy)
def pointpos(x):
if x['signal'] == 1:
return x['high'] + 1e-4
elif x['signal'] == 2:
return x['low'] - 1e-4
else:
return np.nan
df['pointpos'] = df.apply(lambda row: pointpos(row), axis=1)
解释部分
定义:pointpos
函数:
该功能决定信号标记在价格图表上的位置。
参数设置:
x
:DataFrame中的一条记录。
逻辑:
- 如果信号是
1
(看涨情况),它返回的是该蜡烛图的最高价加上一个微小偏移 (1e-4
)。 - 如果信号是
2
(看跌情况),它返回的是该蜡烛图的最低价减去一个微小偏移 (1e-4
)。 - 在其他所有情况下,它返回
np.nan
(表示没有信号)。
使用函数:
df['pointpos'] = df.apply(lambda row: pointpos(row), axis=1)
:这一行将pointpos
函数应用到 DataFrame 的每一行,并添加一个新的列pointpos
来保存结果。
将这些信息添加到DataFrame后,我们就能轻松地在价格图表上标出信号点,以直观地看到在哪产生买入和卖出信号。
接下来,我们继续绘制结果,并在图表上显示交易信号。
第8步:绘制交易信号图在这个步骤中,我们使用 plotly
库在价格图表上可视化交易信号点。我们将绘制蜡烛图来展示,然后在上面叠加信号点,以查看生成买入和卖出信号的位置。
dfpl = df[100:300]
import plotly.graph_objects as go
fig = go.Figure(data=[go.Candlestick(x=dfpl.index,
open=dfpl['open'],
high=dfpl['high'],
low=dfpl['low'],
close=dfpl['close'])])
fig.update_layout(
autosize=False,
width=1000,
height=800,
paper_bgcolor='black',
plot_bgcolor='black')
fig.update_xaxes(gridcolor='black')
fig.update_yaxes(gridcolor='black')
fig.add_scatter(x=dfpl.index, y=dfpl['pointpos'], mode="markers",
marker=dict(size=8, color="MediumPurple"),
name="Signal")
fig.show()
接下来我们将创建一个图表,使用`go.Figure`来绘制K线图,并添加一些信号点。
解释内容:
选择一个数据片段:
dfpl = df[100:300]
: 我们选择 DataFrame 的一部分进行绘制,包括从索引 100 到 300 的那些行。这有助于更好地将重点放在特定时期,以便更清晰地展示。
创建蜡烛图:
-
import plotly.graph_objects as go
:从plotly
导入必要的模块。 fig = go.Figure(data=[go.Candlestick(...)])
:根据选定的 DataFrame 段 (dfpl
) 创建一个蜡烛图。蜡烛图显示每个时间段的开盘价、最高价、最低价和收盘价。
自定义你的布局:
fig.update_layout(...)
: 调整图表布局。autosize=False
: 关闭自动调整大小,设置自定义尺寸。width=1000, height=800
: 将图表的宽度和高度设为1000和800。paper_bgcolor='black', plot_bgcolor='black'
: 将背景颜色设为黑色。fig.update_xaxes(gridcolor='black')
: 将x轴的网格线颜色设为黑色。fig.update_yaxes(gridcolor='black')
: 将y轴的网格线颜色设为黑色。
增加信号点
-
fig.add_scatter(...)
: 使用fig.add_scatter(...)
在K线图上添加散点图以覆盖信号点。 -
x=dfpl.index, y=dfpl['pointpos']
: 设置散点图的x和y坐标,使用DataFrame片段的index
和pointpos
列。 -
mode="markers"
: 将模式设置为‘markers’以显示点。 -
marker=dict(size=8, color="MediumPurple")
: 自定义标记的大小和颜色。 name="Signal"
: 为图例设置名称为‘Signal’。
展示图表的过程:
fig.show()
: 显示交互式图形。
该图表提供了由我们策略生成的交易信号的可视化表示。通过在蜡烛图表上叠加这些信号,我们可以看到买入和卖出信号出现在价格走势中的位置。
通过这个可视化,你可以分析交易策略的有效性,并做出必要的调整来提高其表现。
步骤9:以不同的方式来可视化支撑线和阻力线在这个额外的一步中,我们修改 check_candle_signal
函数以直接在蜡烛图图表上绘制支撑线和阻力线。这有助于我们看到这些线是如何被识别的,以及它们如何与价格走势互动。
def 检查蜡烛信号并绘制(l, n1, n2, backCandles, df, proximity):
ss = []
rr = []
for subrow in range(l - backCandles, l - n2):
if 支撑位(df, subrow, n1, n2):
ss.append(df.low[subrow])
if 阻力位(df, subrow, n1, n2):
rr.append(df.high[subrow])
# 移除接近的支撑位
ss.sort() # 保留最低的支撑位
i = 0
while i < len(ss) - 1:
if abs(ss[i] - ss[i + 1]) <= proximity:
del ss[i + 1]
else:
i += 1
# 移除接近的阻力位
rr.sort(reverse=True) # 保留最高的阻力位
i = 0
while i < len(rr) - 1:
if abs(rr[i] - rr[i + 1]) <= proximity:
del rr[i]
else:
i += 1
# 绘制
dfpl = df[l - backCandles - n1:l + n2 + 50]
fig = go.Figure(data=[go.Candlestick(x=dfpl.index,
open=dfpl['open'],
high=dfpl['high'],
low=dfpl['low'],
close=dfpl['close'])])
# 绘制支撑位
for level in ss:
fig.add_shape(type='line', x0=l - backCandles - n1, y0=level,
x1=l, y1=level,
line=dict(color="MediumPurple", width=2), name="Support")
# 绘制阻力位
for level in rr:
fig.add_shape(type='line', x0=l - backCandles - n1, y0=level,
x1=l, y1=level,
line=dict(color="Red", width=2), name="Resistance")
fig.update_layout(
autosize=False,
width=1000,
height=800,
)
fig.show()
# 检查接近的支撑和阻力
cR = closeResistance(l, rr, 150e-5, dfpl)
cS = closeSupport(l, ss, 150e-5, dfpl)
if (cR and is_below_resistance(l, 6, cR, dfpl)): # and df.RSI[l] > 65
return 1
elif (cS and is_above_support(l, 6, cS, dfpl)): # and df.RSI[l] < 35
return 2
else:
return 0
解释:
检测支撑位和阻力位:
和之前的 check_candle_signal
函数一样,这个函数利用 support
和 resistance
函数来识别支撑线和阻力线。
将相近的层次合并:
zh: * 支持和阻力位非常接近时合并,为了不造成冗余。
谋划:
- 选择 DataFrame 中的一个片段 (
dfpl
) 进行绘制。 - 使用
plotly
创建了一个蜡烛图表。 - 并添加了紫色的水平线来表示支撑线。
- 添加了红色的水平线来表示阻力线。
正在更新布局
- 布局设计自定义,以便更清晰地展示。
显示情节:
- 图表展示支撑位和阻力位是如何与价格相互作用的。
检查相近的层级:
- 该函数使用
closeResistance
和closeSupport
检查当前价格是否接近所有已确定的支持或阻力位。
交易信号生成:
- 如果价格低于识别到的阻力位且RSI显示为上升趋势,就会发出看涨信号。
- 如果价格高于识别到的支撑位且RSI显示为下降趋势,就会发出看跌信号。
- 若以上条件均不成立,则返回0(表示无信号)。
这种增强的可视化效果有助于理解支撑位和阻力位是如何被确定的,以及它们如何影响交易信号的表现。
步骤 10:展示修改后函数的示例图我们来运行使用特定参数的 check_candle_signal_plot
函数,看看这个函数如何检测并绘制支撑位和阻力位,以及生成的信号。
最后一步!.
感谢您跟着这篇教程一起。我们已经涵盖了从加载数据到清理数据,找出支撑和阻力水平,发出信号,到最后的结果可视化,这都是最关键的步骤。
我们的目标是提供一个稳健的框架,你可以使用并根据自己的需要调整以适应自己的交易指标。通过理解这些技术指标之间的相互作用,并利用Python的强大自动化功能,你可以开发出更有效的交易策略。
您可以随意下载提供的Python代码并尝试它。您可以调整参数,修改阈值,并尝试不同的数据集,看看该策略在不同条件下的表现如何。Python的灵活性使您可以根据自己的独特交易风格和目标自定义和优化代码。
使用这个基础作为起点,不要犹豫,大胆创新和迭代。保持灵活性是长期成功的秘诀。如果你们有任何疑问、想法或建议,请留下评论。祝你编程愉快,交易顺利!
InsiderFinance,一条消息感谢您加入我们的社区!在您离开前,还有一些事情想跟您说:
共同學習,寫下你的評論
評論加載中...
作者其他優質文章