布林带(Bollinger Bands)也称为布林通道、保力加通道,是由约翰·布林格(John Bollinger)发明的技术分析指标。布林通道通常被用来确认资产价格波动范围。
布林通道是由三条平滑的曲线组成的趋势线图表,中线为均线,上/下线为中线±2个标准差。
在上一个章节没有自己造轮子,直接使用 Pandas 函数计算 MACD,非常方便的实现了计算和绘图。
本次使用更快捷的方式,直接上飞机:使用 AI 来写代码。
我在上篇文章《利用AI快速跨过新手区:用DevChat编写Python程序》 介绍了如何使用 DevChat 编写程序。
这次直接借助 DevChat 来编写布林带并绘图。
目录
- AI 编程
- 程序优化
- 进阶
- 题外话
AI 编程
因为数据源来源不一致,对程序进行修改,直接套用之前的代码。
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import requests
import json
from requests.auth import HTTPBasicAuth
import datetime
import numpy as np
import fun
## def global variables
global dbname
global stbname
global username
global password
global tdurl
global logfile
dbname = 'trade_data_a'
stbname = 'tdata'
username = 'root'
password = 'taosdata'
## 如果是本地数据库将地址修改为localhost
tdurl = 'http://10.7.7.14:6041/rest/sql/trade_data_a?tz=Asia/Shanghai'
logfile = 'error.log'
##SQL
st = '2022-06-01'
et = '2022-10-01'
sql = 'select tdate,close from trade_data_c.tdata where fcode="000001" and tdate>="'+st+'" and tdate<="'+et+'"'
## Get data to DataFrame
def request_get_d(resInfo):
load_data = json.loads(resInfo)
data = load_data.get("data")
df = pd.DataFrame(data)
df.rename(columns={0:'tdate',1:'close'},inplace=True)
return df
if __name__ == '__main__':
# 指定默认字体
matplotlib.rcParams['font.sans-serif'] = ['SimHei']
matplotlib.rcParams['font.family']='sans-serif'
# 解决保存图像是负号'-'显示为方块的问题
matplotlib.rcParams['axes.unicode_minus'] = False
rt = fun.request_post(tdurl,sql,username,password)
scode = fun.check_return(rt)
if scode != 'error':
df = request_get_d(rt)
# 计算20日移动平均线、标准差、布林上线和布林下线
df['20日MA'] = df['close'].rolling(window=20).mean()
df['20日STD'] = df['close'].rolling(window=20).std()
df['布林上线'] = df['20日MA'] + (df['20日STD'] * 2)
df['布林下线'] = df['20日MA'] - (df['20日STD'] * 2)
# 绘制布林带
df[['close','20日MA','布林上线','布林下线']].plot(figsize=(12,6))
plt.title('平安银行布林带')
plt.ylabel('价格 (人民币)')
plt.show()
运行脚本,图形可以正常绘制,但是中文显示有问题。不过不急,直接问AI。
修改后图形就显示正常了。
程序优化
利用 DevChat 对程序进行进一步优化:
import pandas as pd
import matplotlib.pyplot as plt
import requests
import json
from matplotlib import font_manager
# Global variables
DB_NAME = 'trade_data_a'
STB_NAME = 'tdata'
USERNAME = 'root'
PASSWORD = 'taosdata'
TD_URL = 'http://10.7.7.14:6041/rest/sql/trade_data_a?tz=Asia/Shanghai'
LOG_FILE = 'error.log'
# Constants
START_DATE = '2022-06-01'
END_DATE = '2022-10-01'
SQL = f'select tdate,close from trade_data_c.tdata where fcode="000001" and tdate>="{START_DATE}" and tdate<="{END_DATE}"'
# Specify default font
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.family'] = 'sans-serif'
# Resolve issue with negative numbers being displayed as a square
plt.rcParams['axes.unicode_minus'] = False
def request_get_d(resInfo):
load_data = json.loads(resInfo)
data = load_data.get("data")
df = pd.DataFrame(data)
df.rename(columns={0: 'tdate', 1: 'close'}, inplace=True)
return df
if __name__ == '__main__':
rt = fun.request_post(TD_URL, SQL, USERNAME, PASSWORD)
scode = fun.check_return(rt)
if scode != 'error':
df = request_get_d(rt)
# Calculate 20-Day Moving Average, Standard Deviation, Upper Band and Lower Band
df['20 Day MA'] = df['close'].rolling(window=20).mean()
df['20 Day STD'] = df['close'].rolling(window=20).std()
df['Upper Band'] = df['20 Day MA'] + (df['20 Day STD'] * 2)
df['Lower Band'] = df['20 Day MA'] - (df['20 Day STD'] * 2)
# Draw Bollinger Bands
df[['close', '20 Day MA', 'Upper Band', 'Lower Band']].plot(figsize=(12, 6))
plt.title('Ping An Bank Bollinger Bands')
plt.ylabel('Price')
plt.show()
别的不说,起码看上去挺漂亮的。不过有两个小问题:
import fun
被删除了,这是我的一个存储函数的文件,不引用这个,很多自定义函数会报错。- 中文名称变英文了。
进阶
直接让 DevChat 编写完整的程序。
import taos
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
# 连接到 TDengine 数据库
conn = taos.connect(host='10.7.7.14', user='root', password='taosdata', database='trade_data_c')
# 查询一段时间内的收盘价
query = "select tdate,close from trade_data_c.tdata where fcode='000001' and tdate>= '2022-03-01' AND tdate <= '2023-02-28'"
result = conn.query(query)
df = pd.DataFrame(result.fetch_all(), columns=['Timestamp', 'Close'])
df['Timestamp'] = pd.to_datetime(df['Timestamp'])
df.set_index('Timestamp', inplace=True)
# 计算20日均线和标准差
df['20 Day MA'] = df['Close'].rolling(window=20).mean()
df['20 Day STD'] = df['Close'].rolling(window=20).std()
# 计算布林带上线和下线
df['Upper Band'] = df['20 Day MA'] + (df['20 Day STD'] * 2)
df['Lower Band'] = df['20 Day MA'] - (df['20 Day STD'] * 2)
# 绘制布林带图形
plt.figure(figsize=(12, 6))
plt.plot(df.index, df['Close'], label='Close')
plt.plot(df.index, df['Upper Band'], label='Upper Band')
plt.plot(df.index, df['Lower Band'], label='Lower Band')
plt.title('Bollinger Bands')
plt.xlabel('Timestamp')
plt.ylabel('Price')
plt.legend()
plt.show()
# 提示买卖信号
last_close = df['Close'].iloc[-1]
last_upper_band = df['Upper Band'].iloc[-1]
last_lower_band = df['Lower Band'].iloc[-1]
if last_close > last_upper_band:
print('做空')
elif last_close < last_lower_band:
print('做多')
else:
print('继续观察')
有一种要失业的预感!!
题外话
布林带或者叫布林通道,顾名思义,绘制了一条以均线为中心,4倍标准差宽度的通道。
和 MACD 一样,布林带依然是对价格趋势的描述,只是相较于 MACD 描述趋势的变化程度,布林带更关注于价格的异常波动。
要搞懂布林带,就需要从定义入手,除了之前提到的均线,另一个重要的概念就是标准差。
标准差是反映一组数据离散程度最常用的一种量化形式,是表示精确度的重要指标。标准差的计算步骤如下:
- 求平均:计算数据集中数值的平均值。
- 计算每个数值与平均值的差:从每个数值中减去平均值,然后求差的平方。
- 求结果的平均:将所有差的平方相加,然后除以数据集中的数值个数,再取平方根。
由此看出,布林带绘制了一条价格变化的通道,在绝大多数情况下,价格会处于通道内,并围绕中线上下波动。
对于单边趋势(如上涨),价格如果突破布林带,说明开始了加速行情。
对于震荡趋势,价格如果突破了布林带,说明要开始回调或突破。
世界上并不存在圣杯和银弹,像盲人摸象一样,任何指标都只能反应市场的一部分,而且计算的过程越复杂,离真是可能越远。