레시피: 거래소의 일별 스테이블코인 흐름 추적하기
레시피 · 한 거래소의 90일 시계열을 읽어 순유입과 잔액 변화를 보고하고, 가장 많이 움직인 자체 지갑을 나열하는 일일 작업
- API 가이드
- 8분
- 고급
- 개발자
- entities → daily → addresses
하루에 작업 하나, 조회 세 번입니다. 네 가지 기간, 네트워크별 잔액, as_of_day를 위한 /v1/entities/{slug}. 시계열을 위한 /v1/entities/{slug}/daily — 프로그램은 여기서 최근 7일의 순유입을 출력하고, 90일 기준 표준편차 2배를 벗어난 날을 표시합니다. 30일 회전량 순으로 정렬된 자체 지갑을 위한 /v1/entities/{slug}/addresses?chain=&group=own. 모든 수치는 마감된 UTC 날짜(as_of_day)에서 읽으므로, 작업은 야간 빌드(built_at, 약 08:00 UTC) 후 한 번 실행하며, 보고하는 모든 기간 옆에 complete 플래그를 유지합니다.
curl
#!/bin/sh
# flows.sh <slug> — last 7 days of net flow and the 30d balance change
B=https://stablescan.achivx.com; SLUG=$1
curl -sf "$B/v1/entities/$SLUG" | jq -r '
"\(.name) as of \(.as_of_day) (built \(.built_at))",
(.flows[] | "\(.window): in $\(.inflow_usd6/1e9|round)B out $\(.outflow_usd6/1e9|round)B net $\(.netflow_usd6/1e9*10|round/10)B \(if .complete then "" else "(\(.days_measured)/\(.window_days) days)" end)"),
(.networks[] | " \(.network): balance $\(.balance_usd6/1e9|round)B (prev $\(.prev_balance_usd6/1e9|round)B on \(.prev_as_of_day))")'
curl -sf "$B/v1/entities/$SLUG/daily" | jq -r '.daily[-7:][] | "\(.day) net $\((.inflow_usd6 - .outflow_usd6)/1e6|round)"'Python
import json, statistics, sys, urllib.parse, urllib.request
BASE = "https://stablescan.achivx.com"
def scan(path, **params):
url = BASE + path + ("?" + urllib.parse.urlencode(params) if params else "")
with urllib.request.urlopen(urllib.request.Request(url, headers={"Accept": "application/json", "User-Agent": "flows/1.0"}), timeout=30) as r:
return json.load(r)
def report(slug):
ex = scan(f"/v1/entities/{slug}")
print(f'{ex["name"]} — as of {ex["as_of_day"]}, built {ex["built_at"]}, {ex["addresses"]["total"]:,} addresses ({ex["addresses"]["own"]} own)')
for f in ex["flows"]:
note = "" if f["complete"] else f' ({f["days_measured"]} of {f["window_days"]} days measured)'
print(f' {f["window"]:>3}: in ${f["inflow_usd6"]/1e9:7.1f}B out ${f["outflow_usd6"]/1e9:7.1f}B net ${f["netflow_usd6"]/1e9:+6.1f}B{note}')
for n in ex["networks"]:
delta = (n["balance_usd6"] - n["prev_balance_usd6"]) / 1e6
print(f' {n["network"]:10} balance ${n["balance_usd6"]/1e9:6.1f}B ({delta:+,.0f} vs {n["prev_as_of_day"]}; {n["balances_read"]}/{n["balances_total"]} wallets read)')
daily = scan(f"/v1/entities/{slug}/daily")["daily"]
nets = [(d["day"], (d["inflow_usd6"] - d["outflow_usd6"]) / 1e6) for d in daily]
mu, sd = statistics.mean(v for _, v in nets), statistics.pstdev(v for _, v in nets)
print(f" daily net flow over {len(nets)} measured days: mean ${mu:,.0f}, sd ${sd:,.0f}")
for day, v in nets[-7:]:
flag = " <-- outside 2 sd" if sd and abs(v - mu) > 2 * sd else ""
print(f" {day} ${v:+,.0f}{flag}")
own = scan(f"/v1/entities/{slug}/addresses", chain=1, group="own", limit=5)["items"]
print(f' busiest own wallets on Ethereum (of {scan(f"/v1/entities/{slug}/addresses", chain=1, group="own", limit=1)["total"]}):')
for w in own:
print(f' {w["address"]} in ${w["in_30d_usd6"]/1e6:,.0f} out ${w["out_30d_usd6"]/1e6:,.0f} balance ${(w["balance_usd6"] or 0)/1e6:,.0f}')
if __name__ == "__main__":
report(sys.argv[1] if len(sys.argv) > 1 else "binance")Go
package main
import (
"encoding/json"
"fmt"
"math"
"net/http"
"os"
)
const base = "https://stablescan.achivx.com"
type flow struct {
Window string `json:"window"`
Complete bool `json:"complete"`
DaysMeasured int `json:"days_measured"`
WindowDays int `json:"window_days"`
InflowUSD6 int64 `json:"inflow_usd6"`
OutflowUSD6 int64 `json:"outflow_usd6"`
NetflowUSD6 int64 `json:"netflow_usd6"`
}
type entity struct {
Name string `json:"name"`
AsOfDay string `json:"as_of_day"`
BuiltAt string `json:"built_at"`
Flows []flow `json:"flows"`
Networks []struct {
Network string `json:"network"`
BalanceUSD6 int64 `json:"balance_usd6"`
PrevBalance int64 `json:"prev_balance_usd6"`
PrevAsOfDay string `json:"prev_as_of_day"`
} `json:"networks"`
}
type daily struct {
Daily []struct {
Day string `json:"day"`
InflowUSD6 int64 `json:"inflow_usd6"`
OutflowUSD6 int64 `json:"outflow_usd6"`
} `json:"daily"`
}
func get(path string, out any) error {
res, err := http.Get(base + path)
if err != nil {
return err
}
defer res.Body.Close()
if res.StatusCode != 200 {
return fmt.Errorf("%s: HTTP %d", path, res.StatusCode)
}
return json.NewDecoder(res.Body).Decode(out)
}
func main() {
slug := "binance"
if len(os.Args) > 1 {
slug = os.Args[1]
}
var ex entity
if err := get("/v1/entities/"+slug, &ex); err != nil {
panic(err)
}
fmt.Printf("%s — as of %s, built %s\n", ex.Name, ex.AsOfDay, ex.BuiltAt)
for _, f := range ex.Flows {
note := ""
if !f.Complete {
note = fmt.Sprintf(" (%d of %d days measured)", f.DaysMeasured, f.WindowDays)
}
fmt.Printf(" %3s: in $%.1fB out $%.1fB net $%+.1fB%s\n", f.Window, float64(f.InflowUSD6)/1e15, float64(f.OutflowUSD6)/1e15, float64(f.NetflowUSD6)/1e15, note)
}
for _, n := range ex.Networks {
fmt.Printf(" %-10s balance $%.1fB (%+.0f vs %s)\n", n.Network, float64(n.BalanceUSD6)/1e15, float64(n.BalanceUSD6-n.PrevBalance)/1e6, n.PrevAsOfDay)
}
var d daily
if err := get("/v1/entities/"+slug+"/daily", &d); err != nil {
panic(err)
}
nets := make([]float64, len(d.Daily))
var sum float64
for i, row := range d.Daily {
nets[i] = float64(row.InflowUSD6-row.OutflowUSD6) / 1e6
sum += nets[i]
}
mean := sum / float64(len(nets))
var sq float64
for _, v := range nets {
sq += (v - mean) * (v - mean)
}
sd := math.Sqrt(sq / float64(len(nets)))
for i := max(0, len(nets)-7); i < len(nets); i++ {
flag := ""
if sd > 0 && math.Abs(nets[i]-mean) > 2*sd {
flag = " <-- outside 2 sd"
}
fmt.Printf(" %s $%+.0f%s\n", d.Daily[i].Day, nets[i], flag)
}
}/1e15는 usd6를 한 번에 10억 단위로 바꿉니다(달러로 10^6, 10억 단위로 10^9).
TypeScript
const BASE = "https://stablescan.achivx.com";
type Flow = { window: string; complete: boolean; days_measured: number; window_days: number; inflow_usd6: number; outflow_usd6: number; netflow_usd6: number };
type Entity = { name: string; as_of_day: string; built_at: string; addresses: { total: number; own: number }; flows: Flow[]; networks: { network: string; balance_usd6: number; prev_balance_usd6: number; prev_as_of_day: string }[] };
type Daily = { daily: { day: string; inflow_usd6: number; outflow_usd6: number }[] };
const scan = async <T>(path: string, params: Record<string, string | number> = {}): Promise<T> => {
const q = new URLSearchParams(Object.entries(params).map(([k, v]) => [k, String(v)])).toString();
const res = await fetch(`${BASE}${path}${q ? `?${q}` : ""}`, { headers: { accept: "application/json" } });
if (!res.ok) throw new Error(`${path}: HTTP ${res.status}`);
return (await res.json()) as T;
};
const B = (usd6: number) => `$${(usd6 / 1e15).toFixed(1)}B`;
export async function report(slug = "binance") {
const ex = await scan<Entity>(`/v1/entities/${slug}`);
console.log(`${ex.name} — as of ${ex.as_of_day}, built ${ex.built_at}, ${ex.addresses.total.toLocaleString()} addresses (${ex.addresses.own} own)`);
for (const f of ex.flows) console.log(` ${f.window.padStart(3)}: in ${B(f.inflow_usd6)} out ${B(f.outflow_usd6)} net ${B(f.netflow_usd6)}${f.complete ? "" : ` (${f.days_measured} of ${f.window_days} days measured)`}`);
for (const n of ex.networks) console.log(` ${n.network.padEnd(10)} balance ${B(n.balance_usd6)} (${((n.balance_usd6 - n.prev_balance_usd6) / 1e6).toLocaleString()} vs ${n.prev_as_of_day})`);
const nets = (await scan<Daily>(`/v1/entities/${slug}/daily`)).daily.map((d) => [d.day, (d.inflow_usd6 - d.outflow_usd6) / 1e6] as const);
const mean = nets.reduce((s, [, v]) => s + v, 0) / nets.length;
const sd = Math.sqrt(nets.reduce((s, [, v]) => s + (v - mean) ** 2, 0) / nets.length);
for (const [day, v] of nets.slice(-7)) console.log(` ${day} $${v.toLocaleString(undefined, { maximumFractionDigits: 0 })}${sd && Math.abs(v - mean) > 2 * sd ? " <-- outside 2 sd" : ""}`);
}
await report(process.argv[2]);2026-10-24의 보고 내용
2026-10-23 기준 바이낸스(Binance): 24시간 유입 $2.7B, 유출 $2.8B, 순 −$0.05B. 7일 유입 $16.2B, 유출 $16.7B. 30일 유입 $65.9B, 유출 $67.6B (30일 중 28일 측정). 이더리움(Ethereum) 잔액 $33.7B, 당일 $74M 증가. 2026-09-26 이후 일별 행 28개, 표준편차 2배를 벗어난 날 없음. 30일 기간은 시계열이 보여 주는 이유로 불완전하다고 표시됩니다. 가장 최근 이틀이 아직 모든 네트워크에서 측정되지 않았기 때문이며, 프로그램은 그 표시를 반올림해 없애지 않고 그대로 전달합니다.
일정과 캐시
엔티티는 마감된 UTC 날짜를 바탕으로 하루에 한 번, 약 08:00 UTC(built_at)에 생성됩니다. Cache-Control: max-age=600. 빌드 후 작업을 한 번 실행하고, 실행 시각이 아니라 as_of_day로 날짜별 비교를 하십시오.
Stablecoin scanner ACHIVX에서
- 조회: /v1/entities/binance, /daily, /addresses?chain=1&group=own&limit=5.
- 시계열 차트가 있는 페이지로 본 같은 거래소: /entity/binance.
출처
더 알아보기
관련 질문
- 거래소 전체를 어떻게 읽습니까: 주소, 흐름, 잔액
- 한 스테이블코인의 가장 큰 주소와 가장 바쁜 경로를 얻으려면 어떻게 합니까?
- 코드에서 피드를 페이지 단위로 읽고 응답을 캐시하려면 어떻게 합니까?
레시피 · entities → daily → addresses · 2026-10-24 작성, openapi.json, agents.md 및 당일 실제 호출 기반. 구조는 인용한 것이며, 수치는 날짜 기준이고 인덱스에 따라 바뀝니다.
이 페이지는 ACHIVX Academy 영어 원문을 한국어로 옮긴 것입니다. 번역과 원문이 다르면 영어 원문이 기준입니다.