Get a trader's PnL windows, win/loss, ROI distribution and daily PnL calendar
Returns the trader profile’s analysis panel: realized PnL and buy count over the 1D, 7D, 30D and ALL windows (whole UTC days ending today; 1D is today only), lifetime winning/losing closed positions and win rate, the distribution of closed positions by ROI (realized PnL over the cost bought for the position), and daily realized PnL for the last 90 UTC days that have activity. Only venues whose trades flow through the lot allocator (Predict.fun) are supported; for any other venue supported is false and no figures are returned. Public endpoint — no authentication required (trader data is public). Rate-limited per client IP. Cached per wallet for up to a minute.
curl --request GET \
--url https://data.kairos.trade/trader-stats/analysis/{wallet_address}import requests
url = "https://data.kairos.trade/trader-stats/analysis/{wallet_address}"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://data.kairos.trade/trader-stats/analysis/{wallet_address}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://data.kairos.trade/trader-stats/analysis/{wallet_address}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://data.kairos.trade/trader-stats/analysis/{wallet_address}"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://data.kairos.trade/trader-stats/analysis/{wallet_address}")
.asString();require 'uri'
require 'net/http'
url = URI("https://data.kairos.trade/trader-stats/analysis/{wallet_address}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"wallet_address": "0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b",
"supported": true,
"windows": [
{
"window": "1D",
"realized_pnl": 15.3,
"buy_count": 16
}
],
"daily": [
{
"day": "2026-09-28",
"realized_pnl": -25.82
}
],
"win_loss": {
"winning_positions": 13,
"losing_positions": 11,
"win_rate": 0.5417
},
"roi_distribution": {
"gt_500": 1,
"between_200_500": 1,
"between_0_200": 1,
"between_neg_50_0": 1,
"lt_neg_50": 1
},
"provider": "predictfun"
}{
"detail": [
{}
]
}{
"error": "Rate limit exceeded: 100 per 1 minute"
}Path Parameters
Ethereum or Solana wallet address.
Query Parameters
Provider override (polymarket, kalshi, opinion, predictfun). Auto-detected if omitted.
Response
The analysis panel, or supported false for a venue without allocator data.
A trader profile's analysis panel. supported is false, with empty windows and daily and null win_loss and roi_distribution, for a venue whose trades do not flow through the lot allocator.
"0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b"
Show child attributes
Show child attributes
The last 90 UTC days that have activity, oldest first.
Show child attributes
Show child attributes
Lifetime closed-position counts. win_rate is winning over winning plus losing, 0 when none has closed.
Show child attributes
Show child attributes
Null when unsupported, or when the ROI read failed and the rest of the panel was served without it.
Show child attributes
Show child attributes
"predictfun"
Was this page helpful?
curl --request GET \
--url https://data.kairos.trade/trader-stats/analysis/{wallet_address}import requests
url = "https://data.kairos.trade/trader-stats/analysis/{wallet_address}"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://data.kairos.trade/trader-stats/analysis/{wallet_address}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://data.kairos.trade/trader-stats/analysis/{wallet_address}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://data.kairos.trade/trader-stats/analysis/{wallet_address}"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://data.kairos.trade/trader-stats/analysis/{wallet_address}")
.asString();require 'uri'
require 'net/http'
url = URI("https://data.kairos.trade/trader-stats/analysis/{wallet_address}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"wallet_address": "0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b",
"supported": true,
"windows": [
{
"window": "1D",
"realized_pnl": 15.3,
"buy_count": 16
}
],
"daily": [
{
"day": "2026-09-28",
"realized_pnl": -25.82
}
],
"win_loss": {
"winning_positions": 13,
"losing_positions": 11,
"win_rate": 0.5417
},
"roi_distribution": {
"gt_500": 1,
"between_200_500": 1,
"between_0_200": 1,
"between_neg_50_0": 1,
"lt_neg_50": 1
},
"provider": "predictfun"
}{
"detail": [
{}
]
}{
"error": "Rate limit exceeded: 100 per 1 minute"
}
