1. 为什么选择Python作为CZSC入门语言
在量化交易领域,Python已经成为事实上的标准语言。作为CZSC(缠中说禅)技术分析体系的学习工具,Python具有几个不可替代的优势:
- 丰富的技术分析库:TA-Lib、Pandas、NumPy等专业库可以直接处理K线数据
- 可视化能力强大:Matplotlib、Plotly等库可以完美呈现分型、笔、线段等缠论要素
- 社区生态完善:GitHub上有大量缠论相关的开源项目可以参考
- 开发效率极高:相比C++/Java等语言,Python可以用更少的代码实现复杂逻辑
我最初接触缠论时尝试过用Excel手工画图,后来改用MT4,最终发现Python才是最高效的工具。下面分享我总结的Python快速入门路径。
2. 开发环境配置
2.1 基础环境安装
推荐使用Miniconda管理Python环境:
bash复制# 下载Miniconda安装包(Python3.9版本)
wget https://repo.anaconda.com/miniconda/Miniconda3-py39_4.12.0-Linux-x86_64.sh
# 安装到~/miniconda3目录
bash Miniconda3-py39_4.12.0-Linux-x86_64.sh -b -p ~/miniconda3
# 初始化conda
~/miniconda3/bin/conda init
注意:不要使用系统自带的Python,conda可以创建隔离的环境,避免包冲突。
2.2 创建专用环境
bash复制# 创建名为czsc的Python环境
conda create -n czsc python=3.9 -y
# 激活环境
conda activate czsc
# 安装基础包
pip install numpy pandas matplotlib ta-lib jupyterlab
2.3 解决TA-Lib安装问题
TA-Lib是技术分析核心库,但直接pip安装可能失败。推荐以下安装方式:
- Windows系统:到https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib 下载对应版本的whl文件
- Mac系统:先用brew安装ta-lib:
brew install ta-lib - Linux系统:
bash复制wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz tar -xzf ta-lib-0.4.0-src.tar.gz cd ta-lib/ ./configure --prefix=/usr make sudo make install
3. Python基础语法速成
3.1 数据结构精要
缠论分析最常用的四种数据结构:
- List(列表) - 存储K线序列
python复制bars = [
{'dt': '2023-01-01', 'open': 10.2, 'high': 10.5, 'low': 10.1, 'close': 10.3},
{'dt': '2023-01-02', 'open': 10.3, 'high': 10.8, 'low': 10.2, 'close': 10.6}
]
- Dict(字典) - 存储分型/笔/线段特征
python复制fx = {
'type': 'top', # 分型类型:top/bottom
'dt': '2023-01-01', # 分型时间
'price': 10.5, # 分型价格
'confirmed': True # 是否确认
}
- Pandas DataFrame - 处理表格数据
python复制import pandas as pd
df = pd.DataFrame(bars)
print(df[['dt', 'close']].head())
- NumPy数组 - 数值计算
python复制import numpy as np
close_prices = np.array([x['close'] for x in bars])
ma5 = close_prices[-5:].mean()
3.2 关键控制结构
- 条件判断 - 用于分型确认
python复制def is_fx_confirmed(fx):
if fx['type'] == 'top':
return fx['price'] > max(fx['left']['high'], fx['right']['high'])
else:
return fx['price'] < min(fx['left']['low'], fx['right']['low'])
- 循环处理 - 遍历K线找分型
python复制for i in range(1, len(bars)-1):
left, middle, right = bars[i-1], bars[i], bars[i+1]
if middle['high'] > max(left['high'], right['high']):
print(f"顶分型出现在 {middle['dt']}")
- 函数封装 - 笔识别算法
python复制def find_bi(bars):
bis = []
temp_fx = None
for bar in bars:
# 分型识别逻辑
...
return bis
4. 缠论核心功能实现
4.1 K线数据处理
python复制def load_kline_from_csv(filepath):
"""从CSV文件加载K线数据"""
df = pd.read_csv(filepath)
df['dt'] = pd.to_datetime(df['dt'])
df = df.sort_values('dt').reset_index(drop=True)
return df.to_dict('records')
# 示例:计算MACD指标
def calculate_macd(df, fast=12, slow=26, signal=9):
df['EMA12'] = df['close'].ewm(span=fast).mean()
df['EMA26'] = df['close'].ewm(span=slow).mean()
df['DIF'] = df['EMA12'] - df['EMA26']
df['DEA'] = df['DIF'].ewm(span=signal).mean()
df['MACD'] = (df['DIF'] - df['DEA']) * 2
return df
4.2 分型识别算法
python复制def detect_fenxing(bars):
"""识别顶底分型"""
fenxings = []
for i in range(1, len(bars)-1):
left, mid, right = bars[i-1], bars[i], bars[i+1]
# 顶分型条件
if (mid['high'] > left['high'] and
mid['high'] > right['high'] and
mid['low'] > left['low'] and
mid['low'] > right['low']):
fenxings.append({
'type': 'top',
'dt': mid['dt'],
'high': mid['high'],
'index': i
})
# 底分型条件(类似逻辑)
...
return fenxings
4.3 笔划分实现
python复制def find_bi(fenxings):
"""根据分型识别笔"""
bis = []
current_bi = None
for fx in fenxings:
if not current_bi:
current_bi = fx.copy()
continue
# 向上笔延续条件
if (current_bi['type'] == 'bottom' and
fx['type'] == 'top' and
fx['high'] > current_bi['high']):
current_bi['end'] = fx
# 向下笔延续条件
elif (current_bi['type'] == 'top' and
fx['type'] == 'bottom' and
fx['low'] < current_bi['low']):
current_bi['end'] = fx
# 笔破坏条件
else:
if current_bi.get('end'):
bis.append(current_bi)
current_bi = fx
return bis
5. 可视化分析
5.1 使用Matplotlib绘图
python复制import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter
def plot_kline(bars, bis=None):
fig, ax = plt.subplots(figsize=(12, 6))
# 绘制K线
dates = [bar['dt'] for bar in bars]
opens = [bar['open'] for bar in bars]
highs = [bar['high'] for bar in bars]
lows = [bar['low'] for bar in bars]
closes = [bar['close'] for bar in bars]
for i in range(len(dates)):
color = 'red' if closes[i] > opens[i] else 'green'
ax.plot([dates[i], dates[i]], [lows[i], highs[i]], color=color)
ax.plot([dates[i], dates[i]], [opens[i], closes[i]], color=color, linewidth=3)
# 绘制笔
if bis:
for bi in bis:
start = bi['dt']
end = bi['end']['dt']
price_start = bi['high'] if bi['type'] == 'top' else bi['low']
price_end = bi['end']['high'] if bi['end']['type'] == 'top' else bi['end']['low']
ax.plot([start, end], [price_start, price_end],
color='blue' if bi['type'] == 'bottom' else 'red',
linewidth=2)
# 格式化
ax.xaxis.set_major_formatter(DateFormatter('%m-%d'))
plt.xticks(rotation=45)
plt.grid(True)
plt.show()
5.2 交互式可视化(Plotly)
python复制import plotly.graph_objects as go
def plot_kline_interactive(bars):
fig = go.Figure()
# 添加K线
fig.add_trace(go.Candlestick(
x=[bar['dt'] for bar in bars],
open=[bar['open'] for bar in bars],
high=[bar['high'] for bar in bars],
low=[bar['low'] for bar in bars],
close=[bar['close'] for bar in bars],
name='K线'
))
# 添加均线
df = pd.DataFrame(bars)
fig.add_trace(go.Scatter(
x=df['dt'],
y=df['close'].rolling(5).mean(),
name='MA5',
line=dict(color='orange')
))
fig.update_layout(
title='缠论K线分析',
xaxis_rangeslider_visible=False
)
fig.show()
6. 实战技巧与常见问题
6.1 性能优化技巧
- 向量化计算:避免循环,使用Pandas/Numpy内置方法
python复制# 不好的写法
ma5_list = []
for i in range(len(df)):
ma5_list.append(df['close'][i-4:i+1].mean())
# 好的写法
df['MA5'] = df['close'].rolling(5).mean()
- 使用Numba加速:
python复制from numba import jit
@jit(nopython=True)
def calculate_ema(prices, period):
ema = np.zeros(len(prices))
ema[0] = prices[0]
for i in range(1, len(prices)):
ema[i] = prices[i] * (2/(period+1)) + ema[i-1] * (1-2/(period+1))
return ema
6.2 常见错误排查
-
分型识别错误:
- 检查K线数据是否按时间排序
- 确认分型确认条件是否严格(包含包含关系的处理)
-
笔划分异常:
- 检查是否漏掉了中间分型
- 确认笔的破坏条件是否合理
-
可视化问题:
- 时间格式转换是否正确
- 数据索引是否对齐
6.3 数据源推荐
-
免费数据源:
- AKShare(Python库)
- Yahoo Finance API
- Tushare(需要注册)
-
付费数据源:
- Wind(机构常用)
- 通联数据
- 东方财富Choice
提示:初学者建议先用模拟数据练习,熟悉算法后再接入实时数据。可以先用以下代码生成测试数据:
python复制def generate_test_data(days=100):
np.random.seed(42)
prices = np.cumsum(np.random.randn(days)) + 100
dates = pd.date_range('2023-01-01', periods=days)
return [{
'dt': dates[i],
'open': prices[i] - np.random.rand(),
'high': prices[i] + np.random.rand(),
'low': prices[i] - 1 - np.random.rand(),
'close': prices[i]
} for i in range(days)]