Skip to main content
skill CX Codex

trading-expert — Claude Code skill: what it does, how to install

Equips your agent to build algorithmic trading logic, write Python strategies, and run backtests. Useful when designing execution algorithms or risk metrics.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add personamanagmentlayer/pcl --skill trading-expert -a claude-code
Open on GitHub

What trading-expert does

This skill guides the agent through market systems architecture, order book processing, and execution methods like TWAP or VWAP. It provides boilerplate implementations for moving average crossovers, Bollinger Bands mean reversion, and RSI momentum signals.

A basic backtesting harness runs on pandas and numpy. The script evaluates portfolio drawdown, Sharpe ratio, and overall returns. Order entities track status, quantity, and trade side.

The order routing method send_to_venue is strictly an abstract placeholder. You will need to write custom integration code for your exchange broker. Running the strategy code requires Python execution permissions under Bash.

What it helps with

  • Calculate performance metrics including Sharpe ratio and maximum drawdown
  • Generate trading signals using moving averages, Bollinger Bands, or RSI
  • Model order lifecycle structures for market and limit execution
  • Design execution logic to minimize slippage with TWAP or VWAP

Example prompts for the agent

  • Implement a mean reversion strategy with Bollinger Bands in Python and evaluate historical returns.
  • Build an OrderManager class that handles state transitions for limit and stop orders.
  • Calculate the Sharpe ratio and maximum drawdown from a portfolio equity series.

How to install trading-expert

1Skills CLI (Vercel)

npx skills add personamanagmentlayer/pcl --skill trading-expert -a claude-code

2Manually: put the files in place

~/.claude/skills/trading-expert/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/trading-expert/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about trading-expert

How to install trading-expert in Claude Code?

Run npx skills add personamanagmentlayer/pcl --skill trading-expert -a claude-code in your terminal. This writes the configuration to ~/.claude/skills/trading-expert/SKILL.md.

What does trading-expert do?

It acts as a domain guide for quantitative finance, helping the agent generate backtesting code, quantitative indicators, and execution algorithms.

Does trading-expert execute live market orders?

No, because send_to_venue is deliberately an abstract method. Real broker connectivity must be wired separately.

Source text

SKILL.md · Apache-2.0
---
name: trading-expert
version: 1.1.0
description: >-
  Expert-level algorithmic trading, market systems, quantitative analysis, and trading
  platforms. Use when the user mentions algorithmic trading, quant, markets, finance, or
  high-frequency trading, or when the task involves Trading Systems, Market Data, or
  Execution.
category: domains
tags: [trading, algorithmic-trading, quant, markets, finance, hft]
allowed-tools:
  - Read
  - Write
  - Edit
  - Bash(python:*)
---

# Trading Expert

Expert guidance for algorithmic trading systems, quantitative analysis, market data processing, and trading platform development.

## Core Concepts

### Trading Systems

- Algorithmic trading strategies
- High-frequency trading (HFT)
- Market making
- Arbitrage strategies
- Portfolio optimization
- Risk management

### Market Data

- Order book processing
- Tick data analysis
- Market microstructure
- Real-time data feeds
- Historical data analysis

### Execution

- Order routing
- Smart order routing (SOR)
- Execution algorithms (TWAP, VWAP)
- Slippage minimization
- Transaction cost analysis

## Trading Strategy Implementation

```python
import pandas as pd
import numpy as np
from typing import Optional

class TradingStrategy:
    def __init__(self, symbol: str, capital: float = 100000):
        self.symbol = symbol
        self.capital = capital
        self.position = 0
        self.cash = capital
        self.trades = []

    def moving_average_crossover(self, data: pd.DataFrame,
                                  short_window: int = 50,
                                  long_window: int = 200) -> pd.Series:
        """Simple Moving Average Crossover Strategy"""
        data['SMA_short'] = data['close'].rolling(window=short_window).mean()
        data['SMA_long'] = data['close'].rolling(window=long_window).mean()

        # Generate signals
        data['signal'] = 0
        data.loc[data['SMA_short'] > data['SMA_long'], 'signal'] = 1
        data.loc[data['SMA_short'] < data['SMA_long'], 'signal'] = -1

        return data['signal']

    def mean_reversion(self, data: pd.DataFrame,
                       window: int = 20,
                       num_std: float = 2.0) -> pd.Series:
        """Mean Reversion Strategy using Bollinger Bands"""
        data['MA'] = data['close'].rolling(window=window).mean()
        data['STD'] = data['close'].rolling(window=window).std()
        data['upper_band'] = data['MA'] + (data['STD'] * num_std)
        data['lower_band'] = data['MA'] - (data['STD'] * num_std)

        # Generate signals
        data['signal'] = 0
        data.loc[data['close'] < data['lower_band'], 'signal'] = 1  # Buy
        data.loc[data['close'] > data['upper_band'], 'signal'] = -1  # Sell

        return data['signal']

    def momentum_strategy(self, data: pd.DataFrame, period: int = 14) -> pd.Series:
        """Momentum Strategy using RSI"""
        delta = data['close'].diff()
        gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
        loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()

        rs = gain / loss
        data['RSI'] = 100 - (100 / (1 + rs))

        # Generate signals
        data['signal'] = 0
        data.loc[data['RSI'] < 30, 'signal'] = 1  # Oversold - Buy
        data.loc[data['RSI'] > 70, 'signal'] = -1  # Overbought - Sell

        return data['signal']

class Backtester:
    def __init__(self, initial_capital: float = 100000):
        self.initial_capital = initial_capital
        self.capital = initial_capital
        self.position = 0
        self.trades = []

    def run(self, data: pd.DataFrame, signals: pd.Series) -> dict:
        """Run backtest on historical data"""
        portfolio_value = []

        for i in range(len(data)):
            if signals.iloc[i] == 1 and self.position == 0:  # Buy signal
                shares = self.capital // data['close'].iloc[i]
                cost = shares * data['close'].iloc[i]
                self.capital -= cost
                self.position = shares
                self.trades.append({
                    'type': 'BUY',
                    'price': data['close'].iloc[i],
                    'shares': shares,
                    'date': data.index[i]
                })

            elif signals.iloc[i] == -1 and self.position > 0:  # Sell signal
                proceeds = self.position * data['close'].iloc[i]
                self.capital += proceeds
                self.trades.append({
                    'type': 'SELL',
                    'price': data['close'].iloc[i],
                    'shares': self.position,
                    'date': data.index[i]
                })
                self.position = 0

            # Calculate portfolio value
            current_value = self.capital + (self.position * data['close'].iloc[i])
            portfolio_value.append(current_value)

        return self.calculate_metrics(portfolio_value, data)

    def calculate_metrics(self, portfolio_value: list, data: pd.DataFrame) -> dict:
        """Calculate performance metrics"""
        returns = pd.Series(portfolio_value).pct_change()

        total_return = (portfolio_value[-1] - self.initial_capital) / self.initial_capital
        sharpe_ratio = returns.mean() / returns.std() * np.sqrt(252)
        max_drawdown = self.calculate_max_drawdown(portfolio_value)

        return {
            'total_return': total_return,
            'sharpe_ratio': sharpe_ratio,
            'max_drawdown': max_drawdown,
            'total_trades': len(self.trades),
            'final_value': portfolio_value[-1]
        }

    def calculate_max_drawdown(self, portfolio_value: list) -> float:
        """Calculate maximum drawdown"""
        peak = portfolio_value[0]
        max_dd = 0

        for value in portfolio_value:
            if value > peak:
                peak = value
            dd = (peak - value) / peak
            if dd > max_dd:
                max_dd = dd

        return max_dd
```

## Order Execution

```python
from enum import Enum
from decimal import Decimal
from datetime import datetime

class OrderSide(Enum):
    BUY = "BUY"
    SELL = "SELL"

class OrderType(Enum):
    MARKET = "MARKET"
    LIMIT = "LIMIT"
    STOP = "STOP"
    STOP_LIMIT = "STOP_LIMIT"

class Order:
    def __init__(self, symbol: str, side: OrderSide, order_type: OrderType,
                 quantity: int, price: Optional[Decimal] = None):
        self.id = self.generate_order_id()
        self.symbol = symbol
        self.side = side
        self.type = order_type
        self.quantity = quantity
        self.price = price
        self.filled_quantity = 0
        self.status = "NEW"
        self.created_at = datetime.now()

    def generate_order_id(self) -> str:
        import uuid
        return str(uuid.uuid4())

class OrderManager:
    """Order lifecycle and routing.

    `send_to_venue` is deliberately left abstract: connecting it to a live
    broker or exchange is the point at which this becomes a system that can
    lose money. Implement it against a paper-trading endpoint first, and see
    [Execution guardrails](#execution-guardrails) before pointing it at a real
    venue.
    """

    def __init__(self, risk_manager: "RiskManager", portfolio: dict, live: bool = False):
        self.orders = {}
        self.positions = {}
        self.risk_manager = risk_manager
        self.portfolio = portfolio
        # Live routing is opt-in. Defaulting to paper trading means a
        # misconfiguration costs nothing.
        self.live = live

    def place_order(self, order: Order) -> str:
        """Place a new order, after pre-trade risk checks.

        Risk is checked before routing, never after: an order that has reached
        the venue cannot be un-sent, and a fill can arrive in microseconds.
        """
        if order.id in self.orders:
            # Same client order id - already submitted, do not duplicate.
            return order.id

        self.risk_manager.validate_order(order, self.portfolio)

        self.orders[order.id] = order
        self.route_order(order)
        return order.id

    def cancel_order(self, order_id: str) -> bool:
        """Cancel an existing order.

        Returns False both when the order is unknown and when it is no longer
        cancellable; callers that need to tell those apart should inspect the
        order status rather than rely on the boolean.
        """
        order = self.orders.get(order_id)
        if order is None:
            return False
        if order.status in ("NEW", "PARTIALLY_FILLED"):
            order.status = "CANCELLED"
            return True
        return False

    def route_order(self, order: Order):
        """Smart order routing."""
        venues = self.get_venue_quotes(order.symbol)
        best_venue = self.select_best_venue(venues, order)
        self.send_to_venue(order, best_venue)
```

## Risk Management

```python
class RiskLimitExceeded(Exception):
    """Raised when a pre-trade check rejects an order."""


class RiskManager:
    def __init__(self, max_position_size: float = 0.1,
                 max_portfolio_risk: float = 0.02,
                 stop_loss_pct: float = 0.05):
        self.max_position_size = max_position_size
        self.max_portfolio_risk = max_portfolio_risk
        self.stop_loss_pct = stop_loss_pct

    def calculate_position_size(self, capital: float, price: float,
                                volatility: float) -> int:
        """Calculate optimal position size using Kelly Criterion"""
        max_position_value = capital * self.max_position_size
        shares = int(max_position_value / price)

        # Adjust for volatility
        risk_adjusted_shares = int(shares * (1 - volatility))

        return max(0, risk_adjusted_shares)

    def validate_order(self, order, portfolio: dict) -> None:
        """Pre-trade check. Raises rather than returning a boolean.

        A rejected order must stop the caller. Returning False invites a
        caller that ignores the result and routes anyway, so this fails closed.
        """
        if order.quantity <= 0:
            raise ValueError("order quantity must be positive")
        if order.type.name in ("LIMIT", "STOP_LIMIT") and order.price is None:
            raise ValueError("%s order requires a price" % order.type.name)
        if not self.check_risk_limits(portfolio):
            raise RiskLimitExceeded("portfolio risk limit exceeded; order rejected")

        notional = order.quantity * float(order.price or portfolio["last_price"][order.symbol])
        total_value = portfolio["cash"] + sum(p["value"] for p in portfolio["positions"])
        if notional > total_value * self.max_position_size:
            raise RiskLimitExceeded(
                "order notional %.2f exceeds max position size" % notional
            )

    def check_risk_limits(self, portfolio: dict) -> bool:
        """Check if portfolio is within risk limits"""
        total_value = portfolio['cash'] + sum(p['value'] for p in portfolio['positions'])
        total_risk = sum(p['risk'] for p in portfolio['positions'])

        if total_risk / total_value > self.max_portfolio_risk:
            return False

        return True

    def calculate_var(self, returns: pd.Series, confidence: float = 0.95) -> float:
        """Calculate Value at Risk"""
        return returns.quantile(1 - confidence)
```

## Market Data Processing

```python
class MarketDataProcessor:
    def __init__(self):
        self.order_book = {'bids': [], 'asks': []}

    def process_tick(self, tick: dict):
        """Process real-time tick data"""
        if tick['type'] == 'trade':
            self.process_trade(tick)
        elif tick['type'] == 'quote':
            self.update_order_book(tick)

    def update_order_book(self, quote: dict):
        """Update order book with new quote"""
        if quote['side'] == 'bid':
            self.order_book['bids'] = sorted(
                self.order_book['bids'] + [(quote['price'], quote['size'])],
                key=lambda x: x[0],
                reverse=True
            )[:100]  # Keep top 100
        else:
            self.order_book['asks'] = sorted(
                self.order_book['asks'] + [(quote['price'], quote['size'])],
                key=lambda x: x[0]
            )[:100]

    def calculate_vwap(self, trades: list) -> float:
        """Calculate Volume Weighted Average Price"""
        total_volume = sum(t['volume'] for t in trades)
        vwap = sum(t['price'] * t['volume'] for t in trades) / total_volume
        return vwap

    def calculate_spread(self) -> float:
        """Calculate bid-ask spread"""
        if self.order_book['bids'] and self.order_book['asks']:
            best_bid = self.order_book['bids'][0][0]
            best_ask = self.order_book['asks'][0][0]
            return best_ask - best_bid
        return 0
```

## Execution guardrails

The order-execution example above stops short of venue connectivity on
purpose. `send_to_venue` is where an illustration becomes a system that can
lose money, and a Snyk audit flags this skill as W009 (direct money access) on
that basis. Before wiring it to a broker or exchange:

- **Paper trade first.** Default to a simulated or paper endpoint and make live
  routing an explicit, reviewed configuration change. `OrderManager(live=True)`
  should never be the default in any environment.
- **Check risk before routing, never after.** A routed order cannot be
  un-sent, and a fill can arrive in microseconds. Pre-trade checks that raise
  are safer than checks that return a boolean a caller may ignore.
- **Enforce a kill switch.** A single operator action must halt all new order
  submission and cancel resting orders, independently of strategy logic.
- **Bound everything.** Maximum order notional, maximum position per symbol,
  maximum daily loss, and maximum message rate. Breach means stop, not clamp.
- **Use client order IDs idempotently.** A retried submission must not create a
  second order; reject a reused ID rather than routing it again.
- **Never hardcode broker credentials.** Load them from a secrets manager, use
  the narrowest permission the strategy needs, and keep read-only market-data
  credentials separate from execution credentials.
- **Audit every submission, amendment, cancellation, and fill** with timestamp,
  symbol, side, quantity, price, and the decision that produced it. Most
  jurisdictions require this, and reconstruction after a bad session is
  impossible without it.
- **Understand the regulatory perimeter.** Algorithmic order routing is a
  regulated activity in most markets (MiFID II RTS 6 in the EU, SEC Rule 15c3-5
  in the US, among others), with obligations on pre-trade controls, testing,
  and record keeping.

## Best Practices

- Always backtest strategies on historical data
- Implement proper risk management
- Monitor execution quality (slippage, fill rates)
- Use limit orders to control execution price
- Implement circuit breakers for risk control
- Log all trades and orders for audit
- Test in paper trading before live deployment
- Monitor latency in real-time systems
- Implement failover mechanisms
- Regular strategy performance review

## Anti-Patterns

❌ No backtesting before live trading
❌ Ignoring transaction costs
❌ Over-optimization (curve fitting)
❌ No risk management
❌ Trading without stop losses
❌ Ignoring market microstructure
❌ No position sizing strategy

## Resources

- QuantConnect: https://www.quantconnect.com/
- Zipline: https://www.zipline.io/
- Backtrader: https://www.backtrader.com/
- Interactive Brokers API: https://interactivebrokers.github.io/

© personamanagmentlayer · Apache-2.0 · personamanagmentlayer/pcl

Similar skills

All skills for Finance and business →

From the same set15

finance-expert A skill for any task that touches an amount of money: balances, refunds, payouts, reconciliation, reporting. It carries a money model and double-entry rules. CX Codex +1 6,400installs telecommunications-expert A skill that gives your agent telecom expertise: OSS/BSS, 5G, SDN/NFV, standards and charging. Useful when you design a system or work out billing logic. CX Codex +1 1,900installs banking-expert Gives the agent a reference on core banking, KYC/AML, payments and banking regulation. Useful when accounts, transfers or customer checks come up. CX Codex +1 800installs insurance-expert Gives your agent insurance domain knowledge: underwriting, claims processing, actuarial analysis, risk assessment and fraud detection. CX Codex +1 714installs data-science-expert A skill for analytics, statistics and visualization that kicks in when a task mentions pandas, NumPy or exploratory data analysis. CX Codex +1 573installs gcp-expert A skill that hands your agent working GCP examples: Cloud Functions, BigQuery, Firestore, Pub/Sub and gcloud commands. Useful when the code targets Google Cloud. CX Codex +1 547installs argocd-expert A skill that turns your agent into an ArgoCD operator: GitOps deploys, app sync, AppProject and ApplicationSet. Useful when your deployment lives in Git. CX Codex +1 509installs automotive-expert A skill that gives your agent automotive domain knowledge: connected vehicles, telemetry, ADAS, OBD-II diagnostics. Useful when the project touches fleet software or in-vehicle systems. CX Codex +1 467installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor