How to Implement a Reward Points System for Signal Adoption in AI-Trader

To implement a reward points system for signal adoption in AI-Trader, integrate the grant_agent_reward function from service/server/rewards.py into the follower copy-trade flow in routes_signals.py, using source_type='signal_adoption' to ensure idempotent ledger entries.

AI-Trader is an open-source trading intelligence platform that tracks agent performance through a generic reward ledger. Adding a reward points system for signal adoption allows leaders to earn points whenever followers copy-trade their real-time signals. This implementation leverages the existing ledger infrastructure to record adoption rewards without requiring custom SQL updates.

Architecture of the AI-Trader Reward Ledger

The reward system centers on the grant_agent_reward function defined in service/server/rewards.py (lines 18-30). This helper manages the agent_reward_ledger table while automatically updating the agents.points column, eliminating the need for manual balance adjustments.

The ledger stores reward metadata as JSON via the _json_dumps utility (lines 11-16), enabling flexible storage of complex adoption context. The database schema in service/server/database.py (lines 670-682) defines the agent_reward_ledger structure with critical columns source_type and source_id that enforce idempotency.

Detecting Signal Adoption Events

Signal adoption occurs when a follower creates a trade derived from a leader's real-time signal. In service/server/routes_signals.py, this happens around lines 44-55 where the system reserves a new signal_id for the follower, and again at lines 119-124 where the follower signal is persisted to the database. You will inject the reward logic immediately after the successful INSERT operation that creates the follower signal, ensuring the copy-trade transaction completed before granting points.

Configuring the Adoption Reward Amount

Define a static constant to control the reward value. In service/server/config.py, add:


# service/server/config.py

# Points awarded to signal authors when followers copy-trade

ADOPTION_REWARD = 5

This constant centralizes reward economics, making it easy to adjust payout rates without modifying business logic throughout the codebase.

Granting Points on Successful Copy-Trades

After the follower signal is successfully inserted in routes_signals.py (around line 119-124), call grant_agent_reward to credit the original leader. The function requires agent_id (the leader), amount, reason, and critically source_type and source_id for deduplication.


# service/server/routes_signals.py

from rewards import grant_agent_reward
from config import ADOPTION_REWARD
from experiment_events import record_reward_event

# Inside the follower-copy loop, after cursor.execute INSERT into signals

if action_lower in ['buy', 'short']:
    grant_agent_reward(
        agent_id=agent_id,                     # Leader's agent ID

        amount=ADOPTION_REWARD,
        reason='adoption_reward',
        source_type='signal_adoption',
        source_id=signal_id,                  # Original signal that was copied

        metadata={
            'adopted_by': follower_id,
            'original_signal_id': signal_id,
            'reward_type': 'adoption',
        },
    )
    
    # Optional: Emit analytics event

    record_reward_event(
        cursor,
        agent_id=agent_id,
        amount=ADOPTION_REWARD,
        reason='adoption_reward',
        source_type='signal_adoption',
        source_id=signal_id,
    )

Ensuring Idempotency and Preventing Duplicates

The ledger prevents double-paying for the same adoption through the source_type and source_id composite key. In service/server/rewards.py (lines 47-60), grant_agent_reward queries existing entries with status posted matching these fields. If found, it returns the existing ledger ID instead of creating a duplicate row. Always use source_type='signal_adoption' and set source_id to the original leader's signal_id to leverage this protection.

For advanced use cases, you can also call _add_agent_points from service/server/services.py (lines 102-113), though grant_agent_reward is the preferred entry point as it handles both ledger insertion and balance updates atomically.

Optional Analytics Integration

For downstream analytics, invoke record_reward_event from service/server/experiment_events.py (lines 70-84). This emits a structured reward_granted event without blocking the transaction flow, feeding data pipelines for monitoring adoption rates and reward distributions.

Querying Adoption Rewards

Verify granted points by querying the agent_reward_ledger table directly:

def get_adoption_rewards(agent_id: int) -> list[dict]:
    conn = get_db_connection()
    cur = conn.cursor()
    cur.execute(
        """
        SELECT *
        FROM agent_reward_ledger
        WHERE agent_id = ? AND source_type = 'signal_adoption'
        ORDER BY created_at DESC
        """,
        (agent_id,),
    )
    return [dict(r) for r in cur.fetchall()]

Summary

  • grant_agent_reward in service/server/rewards.py provides the core ledger functionality for tracking adoption rewards.
  • Idempotency is enforced via source_type and source_id, preventing duplicate payouts for the same signal adoption.
  • Configuration is managed through constants in config.py, allowing easy adjustment of reward amounts.
  • Metadata such as adopted_by and original_signal_id is serialized via _json_dumps and stored in agent_reward_ledger.metadata_json.
  • Analytics can be captured using record_reward_event from experiment_events.py for comprehensive reward tracking.

Frequently Asked Questions

Where is the reward ledger function defined in AI-Trader?

The grant_agent_reward function is defined in service/server/rewards.py (lines 18-30). It handles inserting records into agent_reward_ledger and updating the agents.points column atomically, ensuring consistency between the ledger history and the current balance.

How does the system prevent duplicate adoption rewards?

The system checks for existing entries with the same source_type and source_id combination in service/server/rewards.py (lines 47-60). If a record with status posted already exists, the function returns the existing ledger ID instead of creating a new entry, making the operation naturally idempotent.

Can I modify the metadata stored with each reward?

Yes. The metadata parameter accepts a Python dictionary that is serialized using _json_dumps (lines 11-16 in rewards.py). You can include custom fields such as mission_key, follower performance metrics, or market conditions. The JSON is stored in the metadata_json column of agent_reward_ledger.

What is the difference between grant_agent_reward and _add_agent_points?

grant_agent_reward is the high-level function that creates ledger entries and updates points, designed for most reward flows including adoption. _add_agent_points in service/server/services.py (lines 102-113) is a lower-level helper used internally for specific publishing-related rewards. For signal adoption, use grant_agent_reward to ensure proper ledger tracking and idempotency.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →