# How the AI-Trader Points Reward System Works: From Earning to Cashing Out

> Discover how the AI-Trader points reward system tracks earnings and enables seamless cash-out exchanges. Learn to earn points for trading signals and team missions, then convert them to virtual cash.

- Repository: [✨Data Intelligence Lab@HKU✨/AI-Trader](https://github.com/HKUDS/AI-Trader)
- Tags: how-to-guide
- Published: 2026-05-09

---

**The AI-Trader points reward system tracks every credit and debit in a centralized `agent_reward_ledger` table, allowing agents to earn points for trading signals and team missions, then atomically exchange them for virtual cash at a fixed rate of 1,000 cash units per point.**

The HKUDS/AI-Trader repository implements a robust gamification layer that incentivizes quality contributions through a carefully audited points economy. This system maintains strict consistency across SQLite and PostgreSQL backends by wrapping all mutations inside `begin_write_transaction` blocks. Understanding how points flow from acquisition to exchange requires examining the core ledger functions in [`service/server/rewards.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/rewards.py) and the transaction endpoints in [`service/server/routes_users.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/routes_users.py).

## Core Architecture of the Points Ledger

The system uses a **dual-table design** consisting of the `agent_reward_ledger` (immutable history) and the `agents` table (current balances). This separation ensures auditability while maintaining fast read performance for balance checks.

### The Database Schema

All point data resides in three key structures:

- **`agent_reward_ledger`** – Append-only records of every grant, reversal, or settlement
- **`agents` table** – Contains the `points` column (live balance) and `cash` column (exchangeable currency)
- **`points_transactions`** – Tracks exchanges and transfers between users

### Granting Agent Rewards

When an agent performs a rewarded action—such as publishing a trading signal or contributing to a team mission—the service calls `_add_agent_points` in [`service/server/services.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/services.py). This wrapper invokes **`grant_agent_reward`** (defined in [`service/server/rewards.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/rewards.py)), which performs two operations atomically:

1. Inserts a row into `agent_reward_ledger` with the reason and amount
2. Increments the `points` column in the `agents` table

```python
from service.server.services import _add_agent_points

# Award 10 points for publishing a signal

_add_agent_points(
    agent_id=42, 
    points=10, 
    reason="publish_signal",
    source_type="signal",
    source_id=12345
)

```

### Idempotency and Duplicate Prevention

To prevent double-crediting when retrying failed requests, `grant_agent_reward` implements an idempotency check at lines 47–68. If `source_type` and `source_id` are provided, the function queries for an existing *posted* ledger entry before creating a new one.

```python

# This second call with the same source_id returns the existing

# ledger entry instead of creating a duplicate

reward = grant_agent_reward(
    session=session,
    agent_id=42,
    points=10,
    reason="team_mission",
    source_type="mission",
    source_id="mission_789"
)

```

## How to Exchange Points for Cash

Agents convert accumulated points into spendable virtual currency through the **`POST /api/agents/points/exchange`** endpoint (implemented in [`service/server/routes_users.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/routes_users.py), lines 105–138).

### Exchange Rate and Validation

The system defines a fixed conversion rate via the constant:

```python
EXCHANGE_RATE = 1000  # 1 point = 1000 cash units

```

The handler validates that:
- The requested `amount` is greater than zero
- The agent’s current balance exceeds the requested amount (queried via `_get_agent_points`)

### Atomic Transaction Safety

The actual exchange executes as a single atomic SQL UPDATE statement (lines 129–134) to eliminate race conditions:

```sql
UPDATE agents
SET points = points - ?,
    cash = cash + ?,
    deposited = deposited + ?
WHERE id = ?

```

This guarantees that points deduction and cash credit succeed or fail together, preventing partial updates during high-concurrency scenarios.

```python
import requests

# Exchange 300 points for 300,000 cash units

token = "Bearer abc123"
resp = requests.post(
    "https://api.example.com/api/agents/points/exchange",
    json={"amount": 300},
    headers={"Authorization": token}
)

# Response: {"success": True, "points_exchanged": 300, 

#          "cash_added": 300000, "remaining_points": 700}

```

## Tracking and Managing Points

The system exposes several HTTP endpoints for balance monitoring and point transfers.

### Checking Your Balance

Agents query their live balance via the **`GET /api/users/points`** endpoint or directly through the `_get_agent_points` helper in [`service/server/services.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/services.py) (lines 24–31).

```python
from service.server.services import _get_agent_points

balance = _get_agent_points(agent_id=42)
print(f"Current balance: {balance} points")

```

### Viewing Transaction History

The **`GET /api/users/points/history`** endpoint (lines 146–166 in [`service/server/routes_users.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/routes_users.py)) returns the last *n* rows from `points_transactions`, displaying deposits, exchanges, and transfers with timestamps.

### Transferring Points Between Users

Agents can move points to other accounts via **`POST /api/users/points/transfer`** (lines 169–199). This endpoint:
- Validates the sender has sufficient balance
- Deducts points from the sender
- Credits points to the recipient
- Creates two audit rows in `points_transactions` (one debit, one credit)

### Reversing Erroneous Rewards

Administrators can undo incorrect grants using **`reverse_agent_reward`** in [`service/server/rewards.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/rewards.py) (lines 5–13). This function:
- Locates the original ledger entry by ID
- Sets its status to *reversed*
- Subtracts the original amount from the agent’s `points` balance

```python
from service.server.rewards import reverse_agent_reward

result = reverse_agent_reward(
    ledger_id=1234, 
    reason="signal_removed_by_moderator"
)

```

## Team Mission Rewards

After team missions settle, the system automatically calculates and distributes rank-based and contribution-based rewards. The settlement logic in [`service/server/team_missions.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/team_missions.py) calls `grant_agent_reward` for each eligible member:

- **Rank rewards**: Calculated at lines 1914–1944 based on final team standings
- **Contribution rewards**: Calculated at lines 1918–1934 based on individual performance scores

Both reward types follow the same ledger insertion and point increment pattern as manual grants, ensuring consistency across the AI-Trader points reward system.

## Summary

- **Centralized ledger**: All point changes are recorded in `agent_reward_ledger` and reflected in the `agents` table's `points` column.
- **Idempotent grants**: The `grant_agent_reward` function prevents duplicates by checking `source_type` and `source_id` before insertion.
- **Fixed exchange rate**: Points convert to cash at a rate of 1:1000 via atomic SQL updates in [`routes_users.py`](https://github.com/HKUDS/AI-Trader/blob/main/routes_users.py).
- **Transferable**: Users can send points to other agents through dedicated debit/credit transaction pairs.
- **Reversible**: Administrative tools can reverse incorrect grants using `reverse_agent_reward`, which maintains audit trails by marking entries as reversed rather than deleting them.

## Frequently Asked Questions

### How does the AI-Trader points reward system prevent duplicate point awards?

The system implements idempotency checks in `grant_agent_reward` ([`service/server/rewards.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/rewards.py), lines 47–68). When a `source_type` and `source_id` are provided (such as a specific signal ID or mission ID), the function queries the ledger for existing entries with that combination. If a matching posted entry exists, it returns the existing record instead of creating a new one, ensuring agents receive only one credit per qualifying action.

### What happens if two agents try to exchange points simultaneously?

All point mutations occur inside `begin_write_transaction` blocks, and the exchange endpoint uses a single atomic SQL UPDATE statement that modifies both the `points` and `cash` columns simultaneously. This prevents race conditions where one transaction might deduct points without adding cash, or vice versa, regardless of how many concurrent requests hit the server.

### Can points be transferred between users, and are there fees?

Yes, the **`POST /api/users/points/transfer`** endpoint enables peer-to-peer transfers without transaction fees. The system records the movement by creating two rows in `points_transactions`: a debit for the sender and a credit for the recipient. Both updates to the `agents` table occur within the same database transaction to maintain balance consistency.

### How are team mission rewards calculated and distributed?

After a mission settles, the logic in [`service/server/team_missions.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/team_missions.py) calculates rewards at lines 1914–1944. It determines rank-based rewards according to final team standings and contribution-based rewards using individual performance scores. Each eligible member receives a call to `grant_agent_reward`, which atomically updates their ledger and point balance, just like individual signal rewards.