手记

获取OpenAI API Key密钥:用ChatGPT O1生成并回测量化交易算法,探讨取代量化研究员的可能性|附完整代码

将金融研究自动化转换为可执行的交易算法 & 如何使用 OpenAI 推理模型:o1-preview/o1-Mini 模型的 API 调用

将金融研究自动化转换为可执行的交易算法

本文详细介绍了一个基于Python的工具,该工具可以自动将量化金融研究论文转换为可执行的QuantConnect交易算法。作为对先前作品“算法交易中的LLM配对编程”的补充,本文重点介绍了一种线性工作流程,并展示了该工具的初步测试结果。该工具能够从PDF文章中提取和总结关键的交易策略和风险管理技术,并生成语法正确的、带有语法高亮的QuantConnect Python代码,便于审查和理解。

初步测试表明,生成的代码基本无误,尽管尚未在所有测试中实现100%的准确性。该工具的自然语言处理(NLP)组件采用了基本技术,未来可以进一步完善。然而,为了在这个快速发展的领域提供概念验证,我们选择迅速发布代码。该项目正在进行中,未来将不断改进。本文所描述的可以被视为该工具的beta版本。

工作原理

该自动化的核心是ArticleProcessor类,它组织了从PDF提取到代码生成的整个工作流程。以下是其功能的分解:

  1. 使用pdfplumber进行PDF文本提取: 流程从使用pdfplumber库加载和提取PDF文件中的文本开始。pdfplumber以其卓越的准确性而著称,尤其是在处理学术文章中常见的复杂布局方面。

    def load_pdf(self, pdf_path: str) -> str:
        try:
            text = ""
            with pdfplumber.open(pdf_path) as pdf:
                for page in pdf.pages:
                    page_text = page.extract_text()
                    if page_text:
                        text += page_text + "\n"
            logging.info("PDF加载成功。")
            return text
        except Exception as e:
            logging.error(f"无法加载PDF:{e}")
            return ""
    
  2. 文本预处理: 提取文本后,清理和预处理至关重要。这包括使用正则表达式删除URL、页眉、页脚、独立数字(如页码)和其他无关内容。

    def preprocess_text(self, text: str) -> str:
        try:
            text = re.sub(r'https?://\S+', '', text)
            text = re.sub(r'Electronic copy available at: .*', '', text)
            text = re.sub(r'^\d+\s*, '', text, flags=re.MULTILINE)
            text = re.sub(r'\n+', '\n', text)
            text = re.sub(r'^\s*(Author|Title|Abstract)\s*, '', text, flags=re.MULTILINE | re.IGNORECASE)
            text = text.strip()
            logging.info("文本预处理成功。")
            return text
        except Exception as e:
            logging.error(f"无法预处理文本:{e}")
            return ""
    
  3. 使用SpaCy进行标题检测: 理解文章的结构至关重要。该工具利用SpaCy的NLP功能,根据句子长度和标题格式等启发式方法识别章节标题。此分段有助于更有效地组织内容进行分析。

    def detect_headings(self, text: str) -> List[str]:
        try:
            doc = self.nlp(text)
            headings = []
            for sent in doc.sents:
                sent_text = sent.text.strip()
                if len(sent_text.split()) < 10 and sent_text.istitle():
                    headings.append(sent_text)
            logging.info(f"检测到{len(headings)}个标题。")
            return headings
        except Exception as e:
            logging.error(f"无法检测标题:{e}")
            return []
    
  4. 章节拆分和关键词分析: 识别标题后,文本被拆分为相应的章节。然后,工具执行关键词分析,将句子分类为“交易信号”和“风险管理”。这种分类基于预定义的相关关键词列表,确保只有相关信息被进一步处理。

    def keyword_analysis(self, sections: Dict[str, str]) -> Dict[str, List[str]]:
        keyword_map = defaultdict(list)
    
        risk_management_keywords = [
            "drawdown", "volatility", "reduce", "limit", "risk", "risk-adjusted", 
            "maximal drawdown", "market volatility", "bear markets", "stability", 
            "sidestep", "reduce drawdown", "stop-loss", "position sizing", "hedging"
        ]
        trading_signal_keywords = [
            "buy", "sell", "signal", "indicator", "trend", "SMA", "moving average", 
            "momentum", "RSI", "MACD", "bollinger bands", "Rachev ratio", "stay long", 
            "exit", "market timing", "yield curve", "recession", "unemployment", 
            "housing starts", "Treasuries", "economic indicator"
        ]
    
        irrelevant_patterns = [
            r'figure \d+',  
            r'\[\d+\]',     
            r'\(.*?\)',     
            r'chart',       
            r'\bfigure\b',  
            r'performance chart',  
            r'\d{4}-\d{4}',  
            r'^\s*        
        ]
    
        processed_sentences = set()
    
        for section, content in sections.items():
            doc = self.nlp(content)
            for sent in doc.sents:
                sent_text = sent.text.lower().strip()
    
                if any(re.search(pattern, sent_text) for pattern in irrelevant_patterns):
                    continue
                if sent_text in processed_sentences:
                    continue
                processed_sentences.add(sent_text)
    
                if any(kw in sent_text for kw in trading_signal_keywords):
                    keyword_map['trading_signal'].append(sent.text.strip())
                elif any(kw in sent_text for kw in risk_management_keywords):
                    keyword_map['risk_management'].append(sent.text.strip())
    
        for category, sentences in keyword_map.items():
            unique_sentences = list(set(sentences))
            keyword_map[category] = sorted(unique_sentences, key=len)
    
        logging.info("关键词分析完成。")
        return keyword_map
    
  5. 使用OpenAI的GPT-4生成摘要和QuantConnect代码: 利用OpenAI的GPT-4的强大功能,工具生成了提取策略和风险管理技术的简洁摘要。更令人印象深刻的是,它将这些见解转化为功能齐全的QuantConnect Python算法,确保它们遵循最佳实践和语法正确性。

    def generate_qc_code(self, extracted_data: Dict[str, List[str]]) -> str:
        trading_signals = '\n'.join(extracted_data.get('trading_signal', []))
        risk_management = '\n'.join(extracted_data.get('risk_management', []))
    
        prompt = f"""
        你是一位专家级的QuantConnect算法开发者。将以下交易策略和风险管理描述转换为完整、无错误的QuantConnect Python算法。
    
        ### 交易策略:
        {trading_signals}
    
        ### 风险管理:
        {risk_management}
    
        ### 要求:
        1. **Initialize方法**:
            - 设置开始和结束日期。
            - 设置初始资金。
            - 定义选股逻辑。
            - 初始化所需指标。
        2. **OnData方法**:
            - 根据指标实施买/卖逻辑。
            - 确保指标正确更新。
        3. **风险管理**:
            - 实施15%的回撤限制。
            - 应用所描述的头寸规模或止损机制。
        4. **确保合规**:
            - 仅使用QuantConnect支持的指标和方法。
            - 代码必须语法正确且无错误。
    
        ### 示例结构:
        ```python
        from AlgorithmImports import *
    
        class MyAlgorithm(QCAlgorithm):
            def Initialize(self):
                self.SetStartDate(2020, 1, 1)
                self.SetEndDate(2023, 1, 1)
                self.SetCash(100000)
                # 定义选股、指标等。
    
            def OnData(self, data):
                # 交易逻辑
    
            def OnEndOfDay(self):
                # 风险管理
        ```
    
        ### 生成的代码:
        ```
        # LLM将在此行之后生成代码
        ```
        """
    
        try:
            response = openai.ChatCompletion.create(
                model="gpt-4",
                messages=[
                    {"role": "system", "content": "你是一名专门用Python生成QuantConnect算法的助理。"},
                    {"role": "user", "content": prompt}
                ],
                max_tokens=2500,
                temperature=0.3,
                n=1
            )
            generated_code = response['choices'][0]['message']['content'].strip()
            code_match = re.search(r'```python(.*?)```', generated_code, re.DOTALL)
            if code_match:
                generated_code = code_match.group(1).strip()
            logging.info("LLM生成了代码。")
            return generated_code
        except Exception as e:
            logging.error(f"无法生成代码:{e}")
            return ""
    
  6. 使用Tkinter和Pygments显示结果: 为了提供用户友好的体验,工具使用Tkinter在不同的窗口中显示文章摘要和生成的代码。Pygments库通过为Python代码添加语法高亮来增强可读性。

    def display_summary_and_code(self, summary: str, code: str):
        # 创建主Tkinter根
        root = tk.Tk()
        root.withdraw()  # 隐藏主窗口
    
        # 摘要窗口
        summary_window = tk.Toplevel()
        summary_window.title("文章摘要")
        summary_window.geometry("800x600")
    
        summary_text = scrolledtext.ScrolledText(summary_window, wrap=tk.WORD, font=("Arial", 12))
        summary_text.pack(expand=True, fill='both')
        summary_text.insert(tk.END, summary)
        summary_text.configure(state='disabled')  # 设为只读
    
        # 代码窗口
        code_window = tk.Toplevel()
        code_window.title("生成的QuantConnect代码")
        code_window.geometry("1000x800")
    
        code_text = scrolledtext.ScrolledText(code_window, wrap=tk.NONE, font=("Consolas", 12), bg="#2B2B2B", fg="#F8F8F2")
        code_text.pack(expand=True, fill='both')
    
        # 应用语法高亮
        self.apply_syntax_highlighting(code, code_text)
    
        code_text.configure(state='disabled')  # 设为只读
    
        # 启动Tkinter事件循环
        root.mainloop()
    

初步测试

我们使用了L. Durian和R. Vojtko在Quantpedia上发表的文章“使用市场时机策略避免熊市”进行测试。

首次运行时生成的代码产生了以下回测结果:

我们可以看到,该算法在2020年处于空仓状态,正如预期的那样,避免了新冠疫情引发的熊市。该文章提出的策略似乎成功地管理了熊市的规避,绝对值得进一步研究。

结论

将量化金融研究转化为可执行的交易算法的自动化可以显著提高效率。通过集成强大的库,如pdfplumber、SpaCy、OpenAI的GPT-4、Tkinter和Pygments,这个基于Python的工具提供了一个无缝的解决方案,弥合了研究和实施之间的差距。

讨论

  • 将金融论文转化为交易算法的当前过程耗时且容易出错,这突显了自动化的必要性。
  • 该工具仍处于初步阶段,虽然生成的代码基本无误,但实现完全准确性仍然是未来开发的目标。
  • 该工具能够将句子分类为交易信号和风险管理,这被视为一项关键特性,确保只有相关信息用于代码生成。
  • 使用GPT-4生成代码被认为特别具有创新性,展示了人工智能在量化金融领域的潜力。
  • 我们对项目的持续改进和其成为量化分析师和交易员的宝贵资产的潜力持乐观态度。

如何使用 OpenAI 推理模型:o1-preview/o1-Mini 模型的 API 调用

在快速发展的人工智能领域,OpenAI 推出了 o1 系列模型(草莓),包括 o1-preview 和 o1-Mini。这些模型旨在执行复杂的推理任务,成为开发人员和研究人员的强大工具。本文将介绍如何使用这些模型进行 API 调用。

1. openai api key获取

首先,您需要一个 OpenAI API 密钥。您可以在 OpenAI 的官方网站openai.com 上注册并获取。或者,您也可以使用第三方API代理服务商,例如:uiuiapi.com

2. 安装 OpenAI 客户端库

使用 Python 进行 API 调用时,您可以安装 OpenAI 的 Python 客户端库:

pip install openai

3. 编写代码进行 API 调用

以下是一个简单的示例代码,展示如何调用 o1-preview 或 o1-Mini 模型:

import openai

# openai.api_key = 开发者快速获取参考/uiuiapi.com

openai.api_key = 'sk-xxxxxx'  # 替换为您的API Key

# openai.base_url = url # 如果您使用第三方API代理服务,请替换为相应的API Base URL

openai.base_url = 'https://sg.uiuiapi.com/v1/' # 例如,使用uiuiapi.com的API Base URL

response = openai.Completion.create(

model="o1-preview", # 或 "o1-mini"

prompt="请解释一下量子力学的基本原理。",

max_tokens=150

)

print(response.choices[0].text.strip())

4. 管理上下文窗口

o1 模型具有较大的上下文窗口(128.000 个标记),但要注意管理好这个上下文以避免达到标记限制。

5. 设置参数

您可以根据需要设置不同的参数,例如 max_tokens 来控制生成的标记数量。

6. 处理响应

处理 API 返回的响应,并根据需要进行进一步处理或显示。

OpenAI o1 模型的特点

  • **高级推理:**o1 模型在科学推理方面表现出色,在竞争编程和学术基准测试中取得了令人印象深刻的结果。

  • **两个变体:**OpenAI 提供两个版本的 o1 模型:

    • o1-preview:早期版本,利用广泛的常识来解决难题。
    • o1-mini:更快且更具成本效益,适合不需要广泛常识的编码、数学和科学任务。
  • **上下文窗口:**o1 模型具有 128.000 个标记的上下文窗口,允许进行广泛的输入和推理。

    使用最佳实践

  • **保持提示简单直接:**当模型接收到简短、清晰的指令时,效果最佳。

  • **避免链式思维提示:**由于这些模型内部处理推理,因此无需提示它们“逐步思考”或“解释你的推理”。

  • **使用分隔符以提高清晰度:**使用三重引号、XML 标签或章节标题等分隔符来清晰地定义输入的不同部分。

总结

OpenAI 的 o1 系列模型代表了人工智能领域的重大进展,特别是在执行复杂推理任务的能力方面。通过了解它们的能力、局限性和使用最佳实践,开发人员可以利用这些模型的力量来创建创新的应用程序。

**备注:**以上代码和示例仅供学习和参考,实际应用中需考虑更多因素和细节。

0人推荐
随时随地看视频
慕课网APP