构建AI驱动的交易助手

我是一名软件工程师,刚刚涉足金融领域,我想找到一种方法将这两个领域结合起来,创建一个可持续的交易系统。

构建AI驱动的交易助手
一键发币: SUI | SOL | BNB | ETH | BASE | ARB | OP | POLYGON | 跨链桥/跨链兑换

我记得第一次看到《大空头》时,看到那些角色谈论股票和债券以及各种金融术语。我想找到一种方法来理解市场和不同的金融术语,并想办法像他们一样进行交易。

时间快进到今天——我是一名软件工程师,刚刚涉足金融领域,我想找到一种方法将这两个领域结合起来,创建一个可持续的交易系统。这就是我开始研究OpenAI的Agents API的时候。

OpenAI的Agents API打开了新的可能性之门——这些代理可以通过函数调用与彼此以及外部世界互动。这意味着我可以将不同任务的责任分配给不同的代理,这有两个主要好处:清晰的设计和任务特定的代理。

1、获取股票数据

首先,我需要弄清楚我的代理如何获取它们的股票数据。我有两个选择:

  • 使用提供实时和历史股票数据的外部API(结构化、准确,但付费)
  • 使用带有WebSearchTool()的代理在线查找数据(便宜,但结构化程度较低)

最终,我选择了两者都使用。

我使用Alpha Vantage获取结构化数据,并创建了如下函数工具:

@function_tool  
def fetch_alpha_vantage_data(stock_symbol: str):  
    base_url = "https://www.alphavantage.co/query"  
    apikey = ALPHAVANTAGE_API_KEY  
    endpoints = {  
        "intraday": {  
            "function": "TIME_SERIES_INTRADAY",  
            "symbol": stock_symbol,  
            "interval": "15min",  
            "outputsize": "full",  
            "apikey": apikey  
        },  
        "news_sentiment": {  
            "function": "NEWS_SENTIMENT",  
            "tickers": stock_symbol,  
            "apikey": apikey  
        },  
        "earnings": {  
            "function": "EARNINGS",  
            "symbol": stock_symbol,  
            "apikey": apikey  
        }  
    }  
    results = {}  
    for key, params in endpoints.items():  
        response = requests.get(base_url, params=params)  
        results[key] = response.json() if response.status_code == 200 else {"error": f"Failed to fetch {key} data"}  
    return results

我的函数工具现在可以从Alpha Vantage获取时间序列数据、新闻文章和收益报告。然后,我创建了另一个代理,该代理总结所有这些数据,以使数据更加令牌高效,从而降低每次调用的成本。

我还创建了另一个代理,该代理在网上搜索并收集与股票相关的相关信息,如下所示:

fetch_stock_data_agent = Agent(  
    name="Fetch Stock Data Agent",  
    instructions=f"""  
Today's date is {today}.  
You are a comprehensive stock intelligence analyst.  

Given a stock symbol, perform **three levels of analysis** using today's data:  

1. **Stock-specific data**:  
   - Current stock price, today's change, volume  
   - Mention if there's recent activity like earnings, spikes, analyst upgrades  

2. **Sector sentiment**:  
   - Identify the sector this stock belongs to  
   - Summarize today's sentiment (e.g., bullish, cautious, bearish)  
   - Note 1–2 major influencing factors (e.g., regulation, supply/demand)  

3. **Market-wide conditions**:  
   - NASDAQ, S&P 500, and Dow Jones performance today  
   - Summarize overall U.S. market sentiment (positive, neutral, cautious)  
   - Include 1–3 major financial news headlines  

Return the result in structured JSON like this:  

{{  
  "symbol": "AAPL",  
  "price": "$189.40",  
  "daily_change": "-1.2%",  
  "volume": "82M",  
  "stock_notes": "Dropped slightly after product event, but high volume indicates investor interest.",  
  "sector_sentiment": "Cautiously bullish",  
  "sector_drivers": ["Increased chip demand", "Positive earnings from peers"],  
  "market_conditions": {{  
    "nasdaq": "Up 0.48%",  
    "sp500": "Up 0.22%",  
    "dow": "Down 0.10%",  
    "sentiment": "Mixed with tech leadership",  
    "headlines": [  
      "Fed expected to pause rate hikes",  
      "NVIDIA surges after earnings",  
      "Oil prices fall on demand worries"  
    ]  
  }}  
}}  

Prioritize recent and relevant data, especially from the current or previous trading day. However, include brief context from the past week if it adds meaningful insight.  
""",  
    model="gpt-4o-mini",  
    tools=[WebSearchTool()]  
)

现在,我的函数工具和代理都获取了下游代理所需的数据。

2、技术分析代理

接下来,我们需要一个代理,它可以利用这些数据并计算技术指标,以便更好地为其他决策提供信息。我特别关注计算RSI、MACD、EMA和波动性,并将这些信息提供给代理。该代理如下所示:

technical_momentum_detection_agent = Agent(  
    name="Technical Momentum Detection Agent",  
    instructions=f"""  
    Today's date is {today}.  
    Analyze RSI, MACD, EMA, and volatility.  
    Output short_term_momentum, confidence_score, explanation.  
    """,  
    model="o3-mini"  
)

你可能会好奇数据从哪里来,因为我们除了指令外没有直接传递任何数据给这个代理。稍后在文章中我们将讨论我是如何处理代理之间的路由以及数据是如何形成的。

3、发现新股票

这些数据都是针对我们当前投资组合中的股票或我们传递给代理的股票——但我们如何发现新的、热门的股票?为了解答这个问题,我想创建一个代理,该代理也使用WebSearchTool()并在网上搜索基于分析师评级和新闻文章的新股票(见下文)。

trending_stock_agent = Agent(  
    name="Trending Stock Agent",  
    instructions=f"""  
Today's date is {today}.  
You are a trend analyst responsible for identifying and evaluating 1 **high-confidence short-term stock** worth buying.  

Steps:  
1. Search the web for trending stocks based on:  
   - Analyst upgrades  
   - Unusual volume or momentum  
   - News or earnings beats  
   - Insider activity or partnerships  

2. From the list, select the **most promising one** with:  
   - Confidence score ≥ 80  
   - Clear near-term upside catalyst  

3. For the selected symbol:  
   - Summarize the catalyst and recent news  
   - Include a current estimated price  
   - Indicate risk level (low, medium, high)  

Return this final JSON:  

{{  
  "symbol": "XYZ",  
  "reason": "Upgraded by JPMorgan, strong earnings, social buzz.",  
  "confidence_score": 87,  
  "risk_level": "medium",  
  "estimated_price": 43.21  
}}  

Do not return a list. Only return the **top pick**.  
Be efficient, decisive, and format exactly as shown.  
""",  
    model="gpt-4o-mini",  
    tools=[WebSearchTool()]  
)

4、做出交易决策

现在我们有了所有的发现和研究代理,我们需要创建一个代理,它可以根据所有这些数据判断应该做出什么样的交易决策。如果某些指标评分很高但其他指标不是,我们如何确保代理能够全面考虑并据此做出决定?我们需要创建一个交易代理,它可以接收所有这些数据并理解应该做什么。这是我的交易代理:

trading_decision_agent = Agent(  
    name="Trading Decision Agent",  
    instructions=f"""  
    Today's date is {today}.  
    You are a financial analyst making a trading decision for a given stock.  

    You will receive a 'stock_data' object that contains:  
    - 'symbol': The stock ticker symbol (e.g., AAPL)  
    - 'market_data': Web-searched price and volume data  
    - 'alpha_vantage': Summary of Alpha Vantage trends and volatility  
    - 'news': Recent headlines and summaries  
    - 'momentum': Short-term technical momentum and indicators  
    - 'market_conditions': Macro index movement and sentiment  
    - 'sector_analysis': Sector-specific trends and risks  
    - 'current_holdings': The number of shares currently owned  
    - 'available_cash': Total available buying power in USD  

    Your task:  
    - Consider all of the above when deciding to "buy", "buy more", "hold", "sell", or "stay away".  
    - Use sector and market context to inform short-term positioning.  
    - If recommending buy/sell, calculate an appropriate quantity:  
        - Buys: ensure cost does not exceed available_cash  
        - Sells: never suggest more than current_holdings  

    Return JSON:  

    {{  
      "decision": "buy",  
      "quantity": 5,  
      "target_price": 183.42,  
      "confidence_score": 92,  
      "reason": "Strong RSI and MACD signals, tech sector sentiment is bullish, and market conditions are favorable."  
    }}  
    """,  
    model="o3-mini"

5、评估投资组合匹配度

我们可以在这里停止,但我还想添加一步。单个股票在孤立观察时可能看起来好或坏,但我们还需要另一个代理,它可以查看我们的投资组合并判断先前代理的交易决策是否也适合我们的投资组合。因此,我们需要创建另一个代理,该代理查看交易决策代理的交易决策,查看我们的投资组合数据,然后我们需要做出最终的、最终的决定。这就是下面的投资组合代理:

portfolio_agent = Agent(  
    name="Advanced Portfolio Strategy Agent",  
    instructions=f"""  
Today's date is {today}.  
You are a world-class portfolio strategist managing allocation, diversification, and downside risk.  

You will receive:  
- A `stock_data` object with:  
  - symbol, momentum, market data, trading_decision  
  - sector_analysis (sentiment, major factors)  
  - market_conditions (overall market sentiment, index movement)  
- The user's current Alpaca `positions`  
- The user's available `balance` in USD  

--- ANALYSIS OBJECTIVES ---  

Evaluate whether to **approve, scale, or override** the trading_decision using:  

1. **Expected Return Score (0-100)** — Based on trading confidence, sector outlook, and macro sentiment.  
2. **Diversification Score (0-100)** — Penalize overconcentration in one stock or sector.  
3. **Risk Score (0-100)** — Based on volatility, sector concerns, and market instability.  

However, in your final response, you MUST use only one of these four approved actions:  

**"buy", "buy more", "sell", "hold"**  

--- STRATEGY GUIDELINES ---  

- Limit individual stock exposure to ~15% of total portfolio (soft cap), but you are not restricted to this if it is a strong buy.  
- Avoid over-concentrating in hot sectors (e.g. tech-heavy portfolios)  
- Be cautious when market sentiment is bearish or uncertain  
- Favor trades that enhance overall portfolio balance  
- You are not limited by percent allocations, but you should consider them. Your main goal is to maximize returns while managing risk.  

--- RETURN FORMAT ---  
{{  
  "final_decision": "buy", #   
  "adjusted_quantity": 10,  
  "expected_return_score": 88,  
  "diversification_score": 65,  
  "risk_score": 42,  
  "portfolio_health_warnings": [  
    "Tech already > 40%",  
    "Market sentiment: uncertain"  
  ],  
  "portfolio_rationale": "Bullish signals justify buy, and AAPL will remain below 12% of portfolio. Macro indicators are stable, but tech exposure is nearing limit."  
}}  

Only return the JSON — no extra commentary.  
""",  
    model="o3-mini"  
)

通过将逻辑分配给所有不同的代理,我们确保每个代理不会尝试收集各种信息,并且代理可以专注于其特定的角色和职责。如果我们向一个代理发送太多信息,我们将使用大量令牌,这会增加我们的成本,并且我们有风险跳过某些信息或将输入和输出总结掉。

6、统筹这一切

现在我们有一系列代理和函数工具,允许我们获取股票信息、新闻、指标并发现新的、热门的股票。那么,我们如何在不同的股票之间进行路由呢?答案是协调代理。

现在,协调代理本质上消除了处理复杂业务逻辑的软件需求。像我们所有的代理一样,我们只需要通过指令定义所有的业务逻辑,协调代理就会知道如何在不同的代理和函数工具之间进行路由。我们只需定义代理、函数及其用途,协调代理就会知道何时需要调用不同的代理以及如何格式化输入参数。这是我的协调代理:

orchestrator_agent = Agent(  
    name="Trading Orchestrator Agent",  
    instructions=f"""  
Today's date is {today}.  
You are a financial assistant that automates trading actions using multiple tools.  

You must manage a 'stock_data' object for each stock that aggregates the following:  

- 'symbol'  
- 'market_data' (from fetch_stock_data)  
- 'alpha_vantage' (from summarize_alpha_vantage)  
- 'news' (from fetch_news)  
- 'momentum' (from technical_momentum_detection)  
- 'available_cash' (from alpaca_agent.get_account_balance)  
- 'current_holdings' (from alpaca_agent.get_alpaca_positions)  

If input is "1":  
  - Call 'alpaca_agent' to retrieve current positions.  
  - For each symbol:  
      1. Create 'stock_data' with symbol and current_holdings.  
      2. Call 'alpaca_agent' to get available_cash and store it.  
      3. Call tools in order:  
         - 'fetch_stock_data'  
         - 'summarize_alpha_vantage'  
         - 'fetch_news'  
         - 'technical_momentum_detection'  
      4. Store all results in the 'stock_data' object.  
5. Pass full 'stock_data' to 'make_trading_decision'.  
   - Save the result into `stock_data["trading_decision"]`.  
6. Then pass the entire `stock_data` object to `portfolio_agent`.  
   - Save the result into `stock_data["portfolio_decision"]`.  
7. If `portfolio_decision["final_decision"]` is "buy", "buy more", or "sell":  
   - Call `alpaca_agent.submit_order` with symbol, `adjusted_quantity`, and `final_decision` as side.  
   - Stop all further tool usage after the order.  

If input is "2" (Trending Stock):  
1. Call 'trending_stock_analysis' — this returns:  
   - symbol, reason, estimated_price, risk_level, confidence_score  

2. Create a 'stock_data' object with:  
   - 'symbol': the symbol from the trending result  
   - 'catalyst': the reason (short-term opportunity description)  
   - 'confidence_score': from the trending result  
   - 'estimated_price': estimated price from the trending agent  
   - 'current_holdings': 0 (default for new stocks)  

3. Call 'alpaca_agent' to:  
   - Get available_cash → store as 'available_cash'  

4. Then call (in order), storing results into 'stock_data':  
   - 'fetch_stock_data'  
   - 'summarize_alpha_vantage'  
   - 'fetch_news'  
   - 'technical_momentum_detection'  

5. Call 'make_trading_decision' with full 'stock_data'  
   - Save result as 'stock_data["trading_decision"]'  

6. Call 'portfolio_agent' with full 'stock_data'  
   - Save result as 'stock_data["portfolio_decision"]'  

7. If portfolio_decision["final_decision"] is "buy", "buy more", or "sell":  
   - Call 'alpaca_agent.submit_order(symbol, adjusted_quantity, final_decision)'  
   - Stop all further tool usage after order  

8. Return a clean, detailed HTML summary showing:  
   - Symbol  
   - Catalyst  
   - Confidence  
   - Decision  
   - Trade execution (if any)  

Format the final result as clean, readable HTML.  
Do not summarize agent responses.  
Never make tool calls after placing an order.  
""",  
    model="o3-mini",  
    tools=[  # your tools list  
        fetch_stock_data_agent.as_tool("fetch_stock_data", "Fetch detailed stock data"),  
        summarize_av_data_agent.as_tool("summarize_alpha_vantage", "Summarize Alpha Vantage data"),  
        fetch_news_agent.as_tool("fetch_news", "Fetch latest news"),  
        technical_momentum_detection_agent.as_tool("technical_momentum_detection", "Analyze momentum"),  
        trading_decision_agent.as_tool("make_trading_decision", "Make trading decision"),  
        trending_stock_agent.as_tool("trending_stock_analysis", "Find trending stocks"),  
        alpaca_agent.as_tool("alpaca_agent", "Handle Alpaca trading operations"),  
        portfolio_agent.as_tool("portfolio_agent", "Portfolio management and strategy")  
    ]  
)

所以我们的协调代理知道它的步骤,理解每个代理必须做什么,并动态地在一切之间路由。所以,我们现在有一个可以模拟交易分析师的应用程序:它收集信息,找到新闻和指标,做出交易决策,并理解并以符合我们投资组合最佳利益的方式行事。所有这些代码都在一个文件中。

7、决定模型

在整个应用程序中,我们在这之间切换o3-mini和gpt-4o-mini。这是因为gpt-4o-mini具有WebSearchTool(),所以我们需要这个模型用于任何需要访问网络以查找与股票相关当前信息的代理。我在其他代理中使用o3-mini,因为它们需要更多的推理努力,我希望一个高级模型能够思考和理解复杂数据。我可以在这里使用任何模型,比如gpt-4o,但我认为推理能力对决策和平衡投资组合更好。

8、结果

使用这个代理应用程序进行模拟交易,我的账户在三周内增加了$24,493.68。它在工作日的每小时自动交易一次,在营业时间内也是如此。这涉及获取我们整个投资组合的数据、购买力、分析市场和股票,并决定我们是否过度暴露、盈利等。它还每天寻找趋势和表现良好的股票以购买,这也确保我们能够保持最新状态。整个应用程序是自动化的,有一个Google Cloud调度作业创建,确保我不需要以任何方式参与这个过程。

我对交易和金融世界的兴趣始于书籍和电影,这让我走到了这里。结果是什么?一个完全自动化、高性能的交易工具,结合了我对金融的兴趣和我在软件方面的经验。在这个应用程序的制作过程中,我学到了很多,特别是在如何利用代理API来帮助完成诸如数据收集和业务逻辑这样的任务方面。我认为这是人工智能在金融领域非常实用和有用的应用,我非常兴奋地看到我能发现和创造什么。


原文链接:How I Built an AI-Orchestrated Trading Assistant

DefiPlot翻译整理,转载请标明出处

免责声明:本站资源仅用于学习目的,也不应被视为投资建议,读者在采取任何行动之前应自行研究并对自己的决定承担全部责任。
通过 NowPayments 打赏