Rewards Tracker
Horizon provides tools to track and estimate Polymarket liquidity rewards. Market makers earn USDC rebates on qualifying orders. The rewards module fetches eligible markets, checks order scoring status, and estimates earnings from fill data.
Polymarket pays liquidity rewards daily as USDC. There is no historical rewards API, so Horizon estimates earnings locally from fill data at a configurable rebate rate.
Overview
Reward Markets hz.fetch_reward_markets() - fetch all reward-eligible markets from Polymarket.
Order Scoring engine.check_order_scoring() - check if a specific order qualifies for rewards.
Rewards Tracker hz.RewardsTracker - track maker fills and estimate rebates with deduplication.
Pipeline hz.rewards_tracker() - pipeline function for automatic reward tracking in hz.run().
Fetching Reward Markets
Fetch all markets currently eligible for liquidity rewards (unauthenticated).
import horizon as hz
markets = hz.fetch_reward_markets()
for m in markets[: 5 ]:
print ( f " { m.question } " )
if m.rewards:
print ( f " max_spread= { m.rewards.max_spread } , min_size= { m.rewards.min_size } " )
RewardMarket Fields
Field Type Description market_idstrMarket/condition identifier condition_idstrPolymarket condition ID questionstrMarket question text rewards`RewardConfig None` Reward parameters if eligible
RewardConfig Fields
Field Type Description max_spreadfloatMaximum allowed spread to qualify min_sizefloatMinimum order size to qualify ratesstrRaw JSON of rate tiers from the API
Checking Order Scoring
Check if a live order qualifies for rewards (authenticated, Polymarket only).
engine = hz.Engine( exchange = "polymarket" , ... )
scoring = engine.check_order_scoring( "order-id-123" )
print ( f "Order qualifies for rewards: { scoring } " )
Returns False for non-Polymarket exchanges.
RewardsTracker Class
Track maker fills and estimate rebates locally.
from horizon import RewardsTracker
tracker = RewardsTracker( rebate_rate = 0.0002 ) # 2bps
# Record fills as they come in
rebate = tracker.record_fill(
market_id = "0x123..." ,
fill_id = "fill-001" ,
notional = 10000.0 , # price * size
is_maker = True ,
scoring = True ,
)
print ( f "Rebate: \$ { rebate :.2f} " ) # $2.00
# Check totals
print ( f "Total USDC earned: \$ { tracker.total_usdc :.2f} " )
print ( f "Markets: { len (tracker.epoch_rewards) } " )
# Reset for new epoch
old_epoch = tracker.reset_epoch()
Features
Deduplication : duplicate fill IDs are automatically rejected
Per-market tracking : separate EpochRewards per market
Epoch reset : clear per-market accumulators while preserving lifetime totals
Configurable rate : default 2bps, adjustable via rebate_rate
EpochRewards Fields
Field Type Description market_idstrMarket identifier fills_scoredintNumber of qualifying fills estimated_usdcfloatEstimated rebate USDC total_notionalfloatTotal notional volume
Pipeline Function
The hz.rewards_tracker() pipeline function automatically tracks fills from the engine during hz.run().
import horizon as hz
def model ( ctx ):
fair = ctx.feeds[ "poly" ].price
return hz.quotes( fair = fair, spread = 0.04 , size = 10 )
hz.run(
pipeline = [
model,
hz.rewards_tracker( rebate_rate = 0.0002 ),
],
feeds = { "poly" : hz.PolymarketBook( token_id = "0x123..." )},
markets = [hz.Market( id = "0x123..." , name = "Example" )],
exchange = "polymarket" ,
)
Parameters
Parameter Type Default Description rebate_ratefloat0.0002Rebate as fraction of notional (2bps) check_scoringboolFalseCall engine.check_order_scoring() per fill
Pipeline Output
The pipeline function returns a dict each cycle:
{
"epoch_rewards" : {
"market_id" : {
"market_id" : "0x123..." ,
"fills_scored" : 42 ,
"estimated_usdc" : 8.40 ,
"total_notional" : 42000.0 ,
}
},
"total_usdc" : 8.40 ,
"reward_markets_count" : 1 ,
}
Setting check_scoring=True makes an authenticated API call per fill, which adds latency. Only enable this for low-frequency strategies or when precise scoring data is needed.