In [10]:
Copied!
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
In [11]:
Copied!
import matplotlib.pyplot as plt
# 1. 设置系统自带的中文字体(这里使用黑体 SimHei)
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'PingFang SC', 'STHeiti', 'sans-serif']
# 2. 解决更换字体后,负号(-)显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False
import matplotlib.pyplot as plt
# 1. 设置系统自带的中文字体(这里使用黑体 SimHei)
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'PingFang SC', 'STHeiti', 'sans-serif']
# 2. 解决更换字体后,负号(-)显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False
1. 主要资产类别¶
金融市场里有各种「标的」可以交易。对初学者来说,最常接触的是股票和 ETF;更进阶的是期货和期权。
先知道有哪些选择,以及它们的核心差别:
| 资产 | 通俗理解 | 特点 | 示例 |
|---|---|---|---|
| 股票 (Stock) | 买了公司的一小块所有权 | 高风险高收益,日内可多次交易 | AAPL(苹果), 贵州茅台 |
| ETF | 一篮子股票打包成一只基金 | 分散化、低费率,比买单只股票风险低 | SPY(标普500), 510050 |
| 期货 (Futures) | 约定以某价格在未来某天买/卖东西 | 有杠杆(风险倍增)、有到期日、可做空 | ES(标普500期货), IF |
| 期权 (Options) | 花少量钱买一个「选择权」,但不是义务 | 收益不对称(最多亏权利金),灵活对冲 | SPY Put(看跌期权) |
| 债券 (Bonds) | 借给政府/公司钱,收固定利息 | 风险低,收益稳定,与股票相关性低 | 国债, TLT |
| 外汇 (FX) | 两种货币之间互换 | 24小时交易、流动性极高 | EUR/USD(欧元兑美元) |
| 加密货币 | 去中心化数字资产 | 极高波动率、永不休市(7×24h) | BTC, ETH |
初学者建议: 先从股票和 ETF 开始,规则最清晰、监管最完善。期货和期权有杠杆,搞懂之前不要碰。
In [ ]:
Copied!
import yfinance as yf
import mplfinance as mpf
import pandas as pd
ticker = 'AAPL'
# 下载数据时直接禁用多级索引
df = yf.download(ticker, period='60d', progress=False, multi_level_index=False)
if isinstance(df.columns, pd.MultiIndex):
# 找到包含 'Open', 'High' 等关键词的那一层级
df.columns = df.columns.get_level_values(0 if 'Open' in df.columns.get_level_values(0) else 1)
print("当前列名:", df.columns.tolist())
# 确保索引是日期格式(mplfinance 的硬性要求)
df.index = pd.to_datetime(df.index)
df_plot = df.tail(30)
# (红涨绿跌)
mc = mpf.make_marketcolors(up='red', down='green', edge='inherit', wick='inherit', volume='inherit')
my_style = mpf.make_mpf_style(base_mpf_style='binance', marketcolors=mc)
mpf.plot(df_plot,
type='candle',
style=my_style,
title=f'\n{ticker} Analysis',
ylabel='Price (USD)',
volume=True,
mav=(5, 10),
figsize=(12, 8))
import yfinance as yf
import mplfinance as mpf
import pandas as pd
ticker = 'AAPL'
# 下载数据时直接禁用多级索引
df = yf.download(ticker, period='60d', progress=False, multi_level_index=False)
if isinstance(df.columns, pd.MultiIndex):
# 找到包含 'Open', 'High' 等关键词的那一层级
df.columns = df.columns.get_level_values(0 if 'Open' in df.columns.get_level_values(0) else 1)
print("当前列名:", df.columns.tolist())
# 确保索引是日期格式(mplfinance 的硬性要求)
df.index = pd.to_datetime(df.index)
df_plot = df.tail(30)
# (红涨绿跌)
mc = mpf.make_marketcolors(up='red', down='green', edge='inherit', wick='inherit', volume='inherit')
my_style = mpf.make_mpf_style(base_mpf_style='binance', marketcolors=mc)
mpf.plot(df_plot,
type='candle',
style=my_style,
title=f'\n{ticker} Analysis',
ylabel='Price (USD)',
volume=True,
mav=(5, 10),
figsize=(12, 8))
当前列名: ['Close', 'High', 'Low', 'Open', 'Volume']
3. 订单类型¶
为什么下单方式很重要?¶
想象你在农贸市场买苹果:
- 市价单(Market Order):「老板,给我来一斤,你说多少钱就多少钱!」——保证买到,但价格未知(在流动性差的市场里可能多付很多)
- 限价单(Limit Order):「老板,苹果 3.5 元/斤我就买,贵了我不买」——价格有保障,但可能买不到(价格没跌到那里)
- 止损单(Stop Order):「如果苹果跌到 3 元以下,我就赶快买!」(或做空时:「如果涨到 10 元以上,我就赶快割肉!」)
| 订单类型 | 通俗理解 | 优点 | 缺点 |
|---|---|---|---|
| 市价单 (Market Order) | 「立刻成交,价格随便」 | 保证成交,速度最快 | 价格不可控,高波动时滑点大 |
| 限价单 (Limit Order) | 「这个价格成交,否则不买」 | 控制价格,不会多付 | 可能等不到,错过交易机会 |
| 止损单 (Stop Order) | 「跌破某价格就触发,马上卖」 | 自动保护,控制最大损失 | 触发后变市价单,极端行情滑点大 |
| 止损限价单 | 止损触发后变限价单 | 结合两者 | 极端行情可能根本无法成交 |
量化交易的实践: 回测时通常用收盘价成交(理想化),实盘时要考虑滑点(Slippage),实际成交价会比预想的差一点。
In [13]:
Copied!
# 模拟交易成本对策略的影响
np.random.seed(42)
n_trades = 200
# 假设每笔交易有 55% 的胜率,盈亏比 1:1
win_rate = 0.55
win_amount = 0.01 # 每次盈利 1%
loss_amount = -0.01 # 每次亏损 1%
outcomes = np.random.choice([win_amount, loss_amount],
size=n_trades, p=[win_rate, 1 - win_rate])
# 不同手续费率
commission_rates = [0, 0.001, 0.002, 0.005]
labels = ['无成本(理想回测)', '0.1%(低佣金)', '0.2%(常见水平)', '0.5%(偏高,会亏钱)']
fig, ax = plt.subplots(figsize=(12, 5))
for rate, label in zip(commission_rates, labels):
net = outcomes - rate # 每笔扣除手续费
cum = (1 + net).cumprod() * 10000
ax.plot(cum, label=label, linewidth=1.5)
ax.axhline(10000, color='gray', linestyle='--', alpha=0.5)
ax.set_title(f'200笔交易 × 胜率{win_rate:.0%} × 盈亏比1:1:交易成本的侵蚀', fontsize=13)
ax.set_xlabel('交易次数')
ax.set_ylabel('资产价值')
ax.legend()
ax.grid(alpha=0.3)
plt.tight_layout()
plt.show()
print('💡 结论:高频策略对手续费极其敏感;频率越高,成本的影响越大!')
print('💡 量化回测时必须加入真实的手续费假设,否则回测结果毫无参考价值。')
# 模拟交易成本对策略的影响
np.random.seed(42)
n_trades = 200
# 假设每笔交易有 55% 的胜率,盈亏比 1:1
win_rate = 0.55
win_amount = 0.01 # 每次盈利 1%
loss_amount = -0.01 # 每次亏损 1%
outcomes = np.random.choice([win_amount, loss_amount],
size=n_trades, p=[win_rate, 1 - win_rate])
# 不同手续费率
commission_rates = [0, 0.001, 0.002, 0.005]
labels = ['无成本(理想回测)', '0.1%(低佣金)', '0.2%(常见水平)', '0.5%(偏高,会亏钱)']
fig, ax = plt.subplots(figsize=(12, 5))
for rate, label in zip(commission_rates, labels):
net = outcomes - rate # 每笔扣除手续费
cum = (1 + net).cumprod() * 10000
ax.plot(cum, label=label, linewidth=1.5)
ax.axhline(10000, color='gray', linestyle='--', alpha=0.5)
ax.set_title(f'200笔交易 × 胜率{win_rate:.0%} × 盈亏比1:1:交易成本的侵蚀', fontsize=13)
ax.set_xlabel('交易次数')
ax.set_ylabel('资产价值')
ax.legend()
ax.grid(alpha=0.3)
plt.tight_layout()
plt.show()
print('💡 结论:高频策略对手续费极其敏感;频率越高,成本的影响越大!')
print('💡 量化回测时必须加入真实的手续费假设,否则回测结果毫无参考价值。')
💡 结论:高频策略对手续费极其敏感;频率越高,成本的影响越大! 💡 量化回测时必须加入真实的手续费假设,否则回测结果毫无参考价值。
🎯 练习¶
- 观察 K 线图中的长上影线和长下影线分别意味着什么样的多空博弈?
- 将上方模拟中
win_rate改为 0.50(完全随机),观察不同手续费下的结果。在没有信息优势的情况下,手续费本身就决定了你一定会亏钱。 - 思考:如果一个策略每天交易 10 次,手续费 0.1%,需要多高的日胜率才能覆盖成本?(提示:每天成本 = 10 × 0.2% = 2%,每笔需要净盈利 0.2% 才能回本)
下一模块 → ../02_data/01_data_sources.ipynb
In [ ]:
Copied!
In [ ]:
Copied!