| """Task factory functions with dependencies for CrewAI Task instances.""" |
|
|
| from typing import Optional |
|
|
| from crewai import Task, Agent |
|
|
| from crew.config import TradePreferences |
|
|
|
|
| def create_market_scan_task(agent: Agent, ticker: str) -> Task: |
| """Create the market scanning task.""" |
| return Task( |
| description=( |
| f"Analyze the current market conditions for {ticker}. " |
| f"Search for recent news, check price changes, and identify volume anomalies. " |
| f"Summarize any significant market events that could affect the stock." |
| ), |
| expected_output=( |
| f"A summary of market conditions for {ticker} including: " |
| f"key news events, price change magnitude and direction, " |
| f"and whether volume is normal or unusual." |
| ), |
| agent=agent, |
| ) |
|
|
|
|
| def create_fundamental_task(agent: Agent, ticker: str) -> Task: |
| """Create the fundamental analysis task.""" |
| return Task( |
| description=( |
| f"Perform a fundamental analysis of {ticker}. " |
| f"Retrieve financial metrics, recent earnings data, and peer comparisons. " |
| f"Assess whether the stock is overvalued, undervalued, or fairly valued." |
| ), |
| expected_output=( |
| f"A valuation assessment for {ticker} including: " |
| f"key financial metrics (P/E, margins, growth), " |
| f"earnings trend and surprises, peer comparison, " |
| f"and an overall fundamental outlook (bullish/bearish/neutral)." |
| ), |
| agent=agent, |
| ) |
|
|
|
|
| def create_technical_task(agent: Agent, ticker: str) -> Task: |
| """Create the technical analysis task.""" |
| return Task( |
| description=( |
| f"Perform a technical analysis of {ticker}. " |
| f"Retrieve price history and calculate technical indicators. " |
| f"Identify the current trend, support/resistance levels, " |
| f"and recommend entry and target prices." |
| ), |
| expected_output=( |
| f"A technical analysis for {ticker} including: " |
| f"current trend direction, RSI/MACD/Bollinger signals, " |
| f"recommended entry price, and target price." |
| ), |
| agent=agent, |
| ) |
|
|
|
|
| def create_risk_task( |
| agent: Agent, |
| ticker: str, |
| context: list, |
| preferences: Optional[TradePreferences] = None, |
| ) -> Task: |
| """Create the risk assessment task. |
| |
| Args: |
| agent: Risk Manager agent |
| ticker: Stock symbol |
| context: [technical_task] — depends on Technical Analyst output |
| preferences: User preferences so the risk assessment matches the |
| investor's profile (portfolio size, risk appetite). |
| """ |
| prefs = preferences or TradePreferences() |
| stop_target_pct = int(round(prefs.stop_pct * 100)) |
| target_target_pct = int(round(prefs.target_pct * 100)) |
|
|
| return Task( |
| description=( |
| f"Calculate position sizing and stop-loss levels for {ticker}. " |
| f"Use the entry price from the Technical Analyst's recommendation " |
| f"to determine optimal position size and ATR-based stop-loss.\n\n" |
| f"The user's profile:\n" |
| f"- Risk tolerance: {prefs.risk_tolerance} " |
| f"(target stop-loss distance ~{stop_target_pct}% from entry)\n" |
| f"- Trading style: {prefs.trading_style} " |
| f"(target profit distance ~{target_target_pct}% from entry)\n" |
| f"- Portfolio value: ${prefs.portfolio_value:,.0f}\n" |
| ), |
| expected_output=( |
| f"Risk parameters for {ticker} including: " |
| f"recommended position size, stop-loss price, " |
| f"take-profit target, and risk-reward ratio." |
| ), |
| agent=agent, |
| context=context, |
| ) |
|
|
|
|
| def create_strategy_task( |
| agent: Agent, |
| ticker: str, |
| context: list, |
| preferences: Optional[TradePreferences] = None, |
| ) -> Task: |
| r"""Create the strategy synthesis task. |
| |
| Args: |
| agent: Chief Strategist agent |
| ticker: Stock symbol |
| context: [market_task, fundamental_task, technical_task, risk_task] |
| preferences: User preferences that shape the final signal's |
| stop / target distances and horizon. When ``None``, falls |
| back to a Moderate / Swing Trading / \$10k profile. |
| """ |
| prefs = preferences or TradePreferences() |
| stop_pct = int(round(prefs.stop_pct * 100)) |
| target_pct = int(round(prefs.target_pct * 100)) |
|
|
| return Task( |
| description=( |
| f"Synthesize all analysis for {ticker} into a final trading " |
| f"signal for a **{prefs.risk_tolerance} " |
| f"{prefs.trading_style}** investor " |
| f"with a ${prefs.portfolio_value:,.0f} portfolio.\n\n" |
| f"Use the current price reported by get_price_change as Entry.\n" |
| f"Profile-specific stop / target distances:\n" |
| f"- Stop Loss: approximately {stop_pct}% from Entry " |
| f"(tighter for Conservative, wider for Aggressive)\n" |
| f"- Target: approximately {target_pct}% from Entry " |
| f"(smaller for Day Trading, larger for Position Trading)\n\n" |
| f"For BUY: Stop Loss below Entry, Target above Entry.\n" |
| f"For SELL: Stop Loss above Entry, Target below Entry.\n" |
| f"Keep the response concise — do not deliberate at length.\n\n" |
| f"Output EXACTLY this format on its own lines, with NO extra prose:\n" |
| f"{ticker} — BUY (Confidence: 75%)\n" |
| f"Entry: $289.00\n" |
| f"Stop Loss: $283.00\n" |
| f"Target: $298.00\n" |
| f"Reasoning:\n" |
| f"- Market: [one line]\n" |
| f"- Fundamental: [one line]\n" |
| f"- Technical: [one line]\n" |
| f"- Risk: [one line]\n\n" |
| f"(Substitute the real action, confidence, prices, and reasoning; " |
| f"keep every line on its own line; do not echo these instructions.)" |
| ), |
| expected_output=( |
| f"A trading signal in the format: " |
| f"'{ticker} — BUY/SELL/HOLD (Confidence: XX%)' " |
| f"followed by entry, stop-loss, target prices and reasoning summaries." |
| ), |
| agent=agent, |
| context=context, |
| ) |
|
|