VeighNa量化社区
你的开源社区量化交易平台 | vn.py | vnpy
Member
avatar
加入于:
帖子: 2
声望: 1

听完了VNPY课程,脑袋一片浆糊,感觉要做点什么,把课程目录给了AI,出了十道题,希望可以掌握课程的初步学习,立贴共勉之

  • 题目1:环境搭建与数据获取
    ```python
    """
  • 使用vnpy的REST API获取A股000001.SZ最近30天的日线数据
  • 将数据存储到MySQL数据库,表名为stock_daily
  • 用Pandas计算5日/20日均线并可视化(使用Plotly)
    """
    ```

  • 题目2:NumPy向量化计算
    ```python
    """

  • 加载期货主力合约的分钟级数据(文件:期货分钟数据获取.ev4a
  • 使用NumPy实现向量化的MACD指标计算(12,26,9)
  • 对比循环计算与向量化的性能差异(使用%%timeit)
    """
    ```

  • 题目3:CTA策略回测系统
    ```python
    """

  • 基于DoubleMAStrategy模板实现双均线策略
  • 使用2019-2023年沪深300股指期货数据进行回测
  • 分析回测结果:年化收益、最大回撤、夏普比率
  • 生成资金曲线图(使用Plotly 3D曲面图展示参数平原)
    """
    ```

  • 题目4:数据库进阶操作
    ```python
    """

  • 建立MySQL连接池,实现高频Tick数据的批量写入
  • 使用SQLAlchemy查询2024年波动率>30%的交易日
  • 实现数据缓存机制:当本地存在数据时不重复下载
    """
    ```

  • 题目5:量化数据清洗
    ```python
    """

  • 处理包含缺失值的期货tick数据(前向填充+线性插值)
  • 检测并修正异常价格(涨跌幅超过10%的数据点)
  • 使用向量化字符串操作处理合约代码转换(如RB2310 → rb2310)
    """
    ```

  • 题目6:统计套利策略
    ```python
    """

  • 选取螺纹钢/热卷主力合约计算价差(课时46)
  • 使用statsmodels进行协整性检验(课时45)
  • 实现价差Z-Score交易信号:
    • Z>2时做空价差
    • Z<-2时做多价差
    • |Z|<0.5时平仓
  • 进行跨品种套利回测
    """
    ```

  • 题目7:参数优化实战
    ```python
    """

  • 对双均线策略进行参数扫描:
    • 短周期范围[3,10]
    • 长周期范围[20,60]
  • 使用并行计算加速优化过程(课时53)
  • 可视化参数平原(课时34)
  • 选择夏普比率最高的参数组合
    """
    ```

  • 题目8:时间序列分析
    ```python
    """

  • 将Tick数据重采样为15分钟K线(课时41)
  • 计算滚动波动率(窗口=20)(课时44)
  • 实现波动率突破策略:
    • 当价格突破前N根K线振幅时开仓
  • 进行日内策略回测
    """
    ```

  • 题目9:实盘交易系统
    ```python
    """

  • 配置CTP仿真账户(SimNow)
  • 实现策略的自动启停机制:
    • 开盘自动初始化
    • 收盘自动保存状态
  • 添加风控模块:
    • 单笔最大亏损1%
    • 每日最大亏损5%
  • 编写实时日志监控系统
    """
    ```

  • 题目10:全栈分析报告
    ```python
    """

  • 对某CTA策略进行深度分析:
    • 逐笔对冲分析(课时28)
    • 交易行为统计(滑点、成交率等)
  • 使用Plotly制作交互式报告:
    • 资金曲线与回撤热力图
    • 参数敏感性3D图(课时33)
    • 品种相关性矩阵
  • 输出PDF格式的绩效报告
    """
    ```

这些题目覆盖了您课程目录中的关键知识点,从数据获取(课时08-11)、NumPy/Pandas操作(课时12-21)、数据库管理(课时22-23)、策略开发(课时51-53)到实盘部署(课时49),形成完整的学习闭环。建议按照数字顺序完成,每完成一题可对照相关课程视频深化理解。

Member
avatar
加入于:
帖子: 2
声望: 1

import sqlite3
from datetime import datetime, timedelta
import requests
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots

数据库配置

DB_FILE = 'stock_data.db'

def init_database():
"""初始化数据库,确保表结构正确"""
conn = sqlite3.connect(DB_FILE)
cursor = conn.cursor()

# 检查表是否存在
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='stock_daily'")
table_exists = cursor.fetchone()

if table_exists:
    # 检查表结构是否完整
    cursor.execute("PRAGMA table_info(stock_daily)")
    columns = [col[1] for col in cursor.fetchall()]
    required_columns = ['symbol', 'exchange', 'datetime', 'open', 'high', 'low', 'close', 'volume']

    if not all(col in columns for col in required_columns):
        # 表结构不完整,重建表
        print("检测到旧表结构,重建表中...")
        cursor.execute("DROP TABLE IF EXISTS stock_daily")
        conn.commit()
        table_exists = False

if not table_exists:
    # 创建新表
    cursor.execute('''
    CREATE TABLE stock_daily (
        symbol TEXT NOT NULL,
        exchange TEXT NOT NULL,
        datetime TEXT NOT NULL,
        open REAL NOT NULL,
        high REAL NOT NULL,
        low REAL NOT NULL,
        close REAL NOT NULL,
        volume REAL NOT NULL,
        PRIMARY KEY (symbol, exchange, datetime)
    )
    ''')
    print("创建新表成功")

conn.commit()
conn.close()

def fetch_stock_data(symbol, exchange='SZ', start_date="2010-01-01", end_date=None):
"""从腾讯财经获取股票日线数据"""
if end_date is None:
end_date = datetime.now().strftime("%Y-%m-%d")

exchange_code = exchange.lower()
bar_data = []
current_date = datetime.strptime(start_date, "%Y-%m-%d")
end_date = datetime.strptime(end_date, "%Y-%m-%d")

print(f"开始获取 {exchange}{symbol} 数据,时间范围: {start_date} 至 {end_date.date()}")

while current_date <= end_date:
    chunk_end = min(current_date + timedelta(days=365), end_date)
    start_str = current_date.strftime("%Y-%m-%d")
    end_str = chunk_end.strftime("%Y-%m-%d")

    print(f"获取数据: {start_str} 至 {end_str}")

    url = f"http://web.ifzq.gtimg.cn/appstock/app/fqkline/get?param={exchange_code}{symbol},day,{start_str},{end_str},2000,qfq"
    print(url)
    try:
        response = requests.get(url, timeout=10)
        data = response.json()

        if not data.get('data') or f"{exchange_code}{symbol}" not in data['data']:
            print(f"获取数据失败,响应: {data}")
            current_date = chunk_end + timedelta(days=1)
            continue

        for record in data["data"][f"{exchange_code}{symbol}"]["qfqday"]:
            if len(record) < 6:
                continue

            bar_data.append({
                'symbol': symbol,
                'exchange': exchange,
                'datetime': datetime.strptime(record[0], "%Y-%m-%d"),
                'open': float(record[1]),
                'high': float(record[3]),
                'low': float(record[4]),
                'close': float(record[2]),
                'volume': float(record[5])
            })

    except Exception as e:
        print(f"获取数据出错: {e}")

    current_date = chunk_end + timedelta(days=1)

print(f"共获取到 {len(bar_data)} 条数据")
return bar_data

def save_to_database(data):
"""保存数据到数据库"""
if not data:
print("没有数据需要保存")
return

conn = sqlite3.connect(DB_FILE)
cursor = conn.cursor()

inserted = 0
for bar in data:
    try:
        cursor.execute('''
        INSERT OR IGNORE INTO stock_daily 
        (symbol, exchange, datetime, open, high, low, close, volume)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        ''', (
            bar['symbol'],
            bar['exchange'],
            bar['datetime'].strftime("%Y-%m-%d"),
            bar['open'],
            bar['high'],
            bar['low'],
            bar['close'],
            bar['volume']
        ))
        inserted += cursor.rowcount
    except sqlite3.Error as e:
        print(f"保存数据出错: {e}")

conn.commit()
conn.close()
print(f"成功保存 {inserted} 条新数据,跳过 {len(data)-inserted} 条已存在数据")

def get_last_record_date(symbol, exchange):
"""获取数据库中某只股票的最后记录日期"""
conn = sqlite3.connect(DB_FILE)
cursor = conn.cursor()

cursor.execute('''
SELECT MAX(datetime) 
FROM stock_daily 
WHERE symbol=? AND exchange=?
''', (symbol, exchange))

result = cursor.fetchone()
conn.close()

if result and result[0]:
    return datetime.strptime(result[0], "%Y-%m-%d") + timedelta(days=1)
return None

def load_stock_data(symbol, exchange):
"""从数据库加载股票数据"""
conn = sqlite3.connect(DB_FILE)

query = '''
SELECT datetime, open, high, low, close, volume 
FROM stock_daily 
WHERE symbol=? AND exchange=?
ORDER BY datetime
'''

df = pd.read_sql_query(query, conn, params=(symbol, exchange))
conn.close()

if not df.empty:
    df['datetime'] = pd.to_datetime(df['datetime'])
    df.set_index('datetime', inplace=True)

return df

def calculate_technical_indicators(df):
"""计算技术指标"""
if df.empty:
return df

# 计算均线
df['ma5'] = df['close'].rolling(5, min_periods=1).mean()
df['ma20'] = df['close'].rolling(20, min_periods=1).mean()

return df

def visualize_stock_data(df, symbol, exchange):
"""可视化股票数据"""
if df.empty:
print("没有数据可可视化")
return

# 创建子图布局
fig = make_subplots(
    rows=2, cols=1,
    shared_xaxes=True,
    vertical_spacing=0.05,
    row_heights=[0.7, 0.3],
    specs=[[{"type": "scatter"}], [{"type": "bar"}]]
)

# 添加K线图
fig.add_trace(
    go.Candlestick(
        x=df.index,
        open=df['open'],
        high=df['high'],
        low=df['low'],
        close=df['close'],
        name='K线',
        increasing_line_color='red',
        decreasing_line_color='green'
    ),
    row=1, col=1
)

# 添加均线
fig.add_trace(
    go.Scatter(
        x=df.index,
        y=df['ma5'],
        line=dict(color='blue', width=1),
        name='5日均线'
    ),
    row=1, col=1
)

fig.add_trace(
    go.Scatter(
        x=df.index,
        y=df['ma20'],
        line=dict(color='orange', width=1.5),
        name='20日均线'
    ),
    row=1, col=1
)

# 添加成交量
fig.add_trace(
    go.Bar(
        x=df.index,
        y=df['volume'],
        name='成交量',
        marker_color='gray',
        opacity=0.5
    ),
    row=2, col=1
)

# 更新布局
fig.update_layout(
    title=f'{exchange}{symbol} 股票数据 (更新至 {df.index[-1].date()})',
    xaxis_rangeslider_visible=False,
    height=800,
    template='plotly_white',
    hovermode='x unified'
)

# 更新y轴标题
fig.update_yaxes(title_text="价格", row=1, col=1)
fig.update_yaxes(title_text="成交量", row=2, col=1)

fig.show()

def main():

# 股票代码和交易所
symbol = "600519"  # 平安银行
exchange = "sh"    # 深圳交易所

# 1. 初始化数据库
print("初始化数据库...")
init_database()

# 2. 获取最后记录日期,确定下载范围
last_date = get_last_record_date(symbol, exchange)
start_date = "2010-01-01" if last_date is None else last_date.strftime("%Y-%m-%d")

print(f"最后记录日期: {last_date.date() if last_date else '无记录'}")
print(f"将从 {start_date} 开始获取数据")

# 3. 获取股票数据
stock_data = fetch_stock_data(symbol, exchange, start_date=start_date)

# 4. 保存到数据库
save_to_database(stock_data)

# 5. 从数据库加载完整数据
df = load_stock_data(symbol, exchange)

if df.empty:
    print("没有获取到数据")
    return

# 6. 计算技术指标
df = calculate_technical_indicators(df)

# 7. 可视化
visualize_stock_data(df, symbol, exchange)

if name == "main":
main()

Member
avatar
加入于:
帖子: 1909
声望: 142

感谢分享,用实践题目作为最后学习效果的检验是个挺好的方法啊

© 2015-2022 上海韦纳软件科技有限公司
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

【用户协议】
【隐私政策】
【免责条款】