ピナクルのクロージングに対するクロージングラインバリューを測定する
**クロージングラインバリュー(CLV)**は、取った価格と試合開始前の最後の市場価格を比較する指標です。ピナクルのクロージング時のフェアオッズを継続的に上回ることは、損益に表れるよりずっと前に、ご自身の手法に優位性があることを示す最も確かな初期シグナルです。ただし、利益を保証するものではありません。PinnFeedはイベント開始時に各マーケットのピナクルのクロージング価格を保存し、/v1/closing で提供しています。
ステップ 1 — 計算式#
CLV = price_taken / closing_fair_price − 1
生の価格ではなく、マージンなしのクロージング価格を使ってください。ピナクルのマージンを含んだままの価格を上回るのは簡単で、優位性を過大評価してしまいます。2.10で取り、マーケットがフェアオッズ1.95でクローズした場合、CLVは+7.7%です。
ステップ 2 — すべてのベットを記録する#
各ベットには、イベントID、マーケットのキー、結果が必要です。3つともAPIから取得できます。イベントの id、マーケットの key(s;0;m は試合全体のマネーライン、s;0;ou;2.5 は試合全体のトータル2.5)、結果の name(home、away、draw、over、under)です。
ステップ 3 — トラッカーを実行する#
requests をインストールし、スクリプトを clv.py として保存して、ベットするたびに記録します。
# clv.py: ベットを記録し、ピナクルのマージンなしクロージングに対するクロージングラインバリュー(CLV)を測定します。
# pip install requests 使い方:
# python clv.py bet <event_id> <market_key> <outcome> <price> 例: bet 1640141281 "s;0;m" home 2.10
# python clv.py report
import os, sqlite3, sys, requests
BASE = os.environ.get("PINNFEED_BASE", "https://pinnfeed.io")
KEY = os.environ["PINNFEED_KEY"]
db = sqlite3.connect(os.environ.get("CLV_DB", "bets.db"))
db.execute("CREATE TABLE IF NOT EXISTS bets (event_id INTEGER, market_key TEXT, outcome TEXT, price REAL, "
"close_fair REAL, placed_at TEXT DEFAULT CURRENT_TIMESTAMP)")
def closing_fair(event_id, market_key, outcome):
r = requests.get(f"{BASE}/v1/closing/{event_id}", headers={"x-api-key": KEY}, timeout=20)
if r.status_code == 404:
return None # まだクローズしていない(または記録されていない)
r.raise_for_status()
for rec in r.json()["markets"]:
if rec["market"]["key"] == market_key:
for o in rec["market"]["outcomes"]:
if o["name"] == outcome:
return o["fair"]
return None
if sys.argv[1:2] == ["bet"]:
_, _, event_id, market_key, outcome, price = sys.argv
db.execute("INSERT INTO bets (event_id, market_key, outcome, price) VALUES (?,?,?,?)",
(int(event_id), market_key, outcome, float(price)))
db.commit()
print("logged")
else:
rows = db.execute("SELECT rowid, event_id, market_key, outcome, price, close_fair FROM bets").fetchall()
clvs = []
for rowid, event_id, key, outcome, price, close in rows:
if close is None:
close = closing_fair(event_id, key, outcome)
if close:
db.execute("UPDATE bets SET close_fair=? WHERE rowid=?", (close, rowid))
if close:
clv = price / close - 1
clvs.append(clv)
print(f"{event_id} {key} {outcome}: took {price}, closed fair {close:.3f} -> CLV {clv:+.2%}")
else:
print(f"{event_id} {key} {outcome}: took {price}, waiting for close")
db.commit()
if clvs:
print(f"average CLV over {len(clvs)} bets: {sum(clvs) / len(clvs):+.2%}")
python clv.py bet 1640229582 "s;0;m" home 2.10
python clv.py report
1640229582 s;0;m home: took 2.1, closed fair 3.181 -> CLV -33.99%
999 s;0;m home: took 1.9, waiting for close
average CLV over 1 bets: -33.99%
試合開始後にcronで report を実行してください。各ベットのクロージング価格は一度だけ取得され、保存されます。
ステップ 4 — 結果を解釈する#
- 数百件のベットで平均CLVが**+2%以上**であれば、実際の優位性を示す強い兆候です。
- CLVがマイナスなのに利益がプラスの場合、たいていは運によるもので、通常は時間とともに薄れていきます。
- CLVを競技、マーケット、ベットのタイミング別に分けると、優位性が実際にどこから来ているのかがわかります。
ステップ 5 — 1日分をまとめてダウンロードする#
調査やバックテストには、UTCの1日分のクロージングラインをすべて取得します。
curl -H "x-api-key: $PINNFEED_KEY" "https://pinnfeed.io/v1/closing?date=2026-11-08&sport=soccer&main=true"
よくある質問#
クロージングオッズが含まれるのはどのプランですか?#
クロージングオッズの履歴はBuilder(月額99ユーロ)から含まれ、ProとEnterpriseでもご利用いただけます。
クロージング価格はいつ記録されますか?#
イベントの開始時です。各マーケットの最後のプレマッチ価格が、記録時刻とともに保存されます。
アーカイブはいつからありますか?#
サービス開始日から始まり、毎日蓄積されています。Enterpriseプランでは、CSVまたはParquet形式で一括エクスポートできます。