关于 portfolio-optimization
该 Skill 指导开发者使用 Python C 扩展和 NumPy 实现并验证高性能投资组合优化算法,涵盖数值计算、边界情况和基准测试。
主要功能
- 01实现 Python C 扩展
- 02访问并验证 NumPy 数组
- 03检查数值正确性
- 04进行性能基准测试
- 05处理边界情况与错误
适用场景
- 01加速投资组合风险计算
- 02优化协方差矩阵运算
- 03验证 Python 到 C 的数值改动
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ letta-ai/ skills --skill portfolio-optimization安装后在 Claude Code 中输入/portfolio-optimization确认已加载。
详细介绍
投资组合优化
概述
本技能提供了使用 Python C 扩展实现高性能投资组合优化算法的指南。内容涵盖创建可与 NumPy 数组交互的 C 扩展的工作流程、恰当的验证策略,以及优化数值计算时应避免的常见问题。
何时应用此技能
在以下情况下应用此技能:
- 实现投资组合风险计算(方差、波动率、夏普比率)
- 优化大型资产投资组合的矩阵向量运算
- 为 Python 数值代码创建 C 扩展
- 性能要求指定了加速比(例如,>= 1.2x)
- 使用协方差矩阵和投资组合权重
推荐工作流程
阶段 1:了解代码库
编写任何代码之前:
- 完整阅读所有相关源文件 - 了解基准实现、数据结构和预期接口
- 识别数学运算 - 常见运算包括:
- 矩阵向量乘法(协方差矩阵乘以权重)
- 点积(权重乘以收益率)
- 平方根运算(根据方差计算波动率)
- 了解测试套件 - 明确正确性容差(例如,1e-10)以及必须达到的性能基准
- 记录输入/输出约定 - 数组形状、数据类型(通常为 float64)和返回值规范
阶段 2:规划实现
实现之前考虑以下因素:
-
C 提供加速的原因:
- 消除 Python 解释器开销
- 允许直接访问内存,无需边界检查
- 支持编译器优化(向量化、循环展开)
- 减少临时数组分配
-
需要做出的设计决策:
- 是否使用 NumPy C API 实现零拷贝数组访问
- 内存布局假设(C 连续布局还是 Fortran 连续布局)
- 类型不匹配和维度错误的错误处理策略
-
潜在的算法优化:
- 利于缓存的内存访问模式(C 数组按行优先迭代)
- SIMD 向量化机会
- 尽量减少 Python 到 C 的数据转换开销
阶段 3:实现 C 扩展
实现 C 扩展时:
-
包含正确的头文件:
Python.h(必须放在首位)- 用于访问 NumPy 数组的
numpy/arrayobject.h
-
在模块初始化函数中初始化 NumPy:
- 调用
import_array()初始化 NumPy C API
- 调用
-
使用 NumPy C API 访问数组:
- 使用
PyArray_DATA()获取数据指针 - 使用
PyArray_DIM()获取维度 - 使用
PyArray_STRIDE()获取内存步长 - 使用
PyArray_IS_C_CONTIGUOUS()检查内存布局
- 使用
-
实现可靠的错误处理:
- 验证数组维度是否与预期形状一致
- 检查数据类型(双精度应为
NPY_FLOAT64) - 处理非连续数组(拒绝此类数组或处理步长)
- 出错时设置适当的 Python 异常
阶段 4:实现 Python 封装器
创建一个 Python 模块,使其能够:
- 导入 C 扩展模块
- 提供与基准 API 匹配的简洁接口
- 处理必要的数组预处理(确保数组连续)
- 清晰地记录接口文档
阶段 5:验证策略
关键:彻底验证每项更改
-
编辑文件后,请重新阅读 - 确认更改已正确应用,尤其是多行更改
-
逐步测试:
- 先构建 C 扩展并确认其编译成功
- 在运行完整基准测试前,先测试各个函数
- 先用小型测试用例验证正确性,再逐步扩大规模
-
正确性验证:
- 将输出与基线实现进行比较
- 使用适当的数值容差(双精度通常为 1e-10)
- 使用已知输入进行测试,以便手动计算预期输出
-
性能验证:
- 使用具有代表性的数据规模运行基准测试
- 验证不同投资组合规模下的加速效果均符合要求
- 测试边界情况:小型投资组合(n=1、n=10)、大型投资组合(n=5000+)
需要处理的边界情况
确保实现能够处理:
- 空投资组合(n=0)- 返回适当的默认值或错误
- 单资产投资组合(n=1)- 协方差的退化情况
- 维度不匹配 - 权重向量长度与协方差矩阵维度不一致
- 无效输入:
- 非方阵协方差矩阵
- 输入中包含 NaN 或无穷值
- 负方差(数学上无效)
- 内存相关问题:
- 非连续的 NumPy 数组
- C 代码中的内存分配失败
- 可能导致内存压力的大型投资组合
应避免的常见陷阱
代码完整性
- 在编辑操作中绝不要截断代码——务必提供完整实现
- 编辑后验证文件内容,确认更改已正确应用
- 明确记录所有设计决策
测试方法
- 避免从实现直接跳到完整基准测试
- 集成测试前,先单独测试每个函数
- 不要仅凭“测试通过”进行验证——要理解测试为何通过
C 扩展特定事项
- 访问数据前,务必检查 NumPy 数组类型
- 正确处理引用计数,避免内存泄漏
- 在模块初始化中使用
import_array()初始化 NumPy API - 出错时使用
PyErr_SetString()设置异常
性能验证
- 验证不同输入规模下的加速效果是否稳定
- 如果可能需要进一步优化,请进行性能分析
- 考虑小型输入时 Python 到 C 的转换开销
构建和测试命令
典型工作流命令:
# Build the C extension
python setup.py build_ext --inplace
# Run correctness tests
python -c "from portfolio_optimized import *; # test calls"
# Run benchmark
python benchmark.py
# Run full test suite
pytest test_portfolio.py -v
验证清单
任务完成前,请确认:
- 已阅读并理解所有源文件
- C 扩展编译成功且无警告
- 已单独测试各个函数的正确性
- 数值结果在容差范围内与基线一致
- 性能达到加速要求
- 已明确测试或处理边界情况
- 已为无效输入实现错误处理
- 所有编辑完成后均已验证文件内容
- C 代码中没有内存泄漏(引用计数处理正确)
评论
支持 Markdown