اسناد حسابداری بروکر

همان فایل‌های مخزن؛ سیاست تازه نیست

واژه‌نامه حسابداری بروکر

مرجع الزام‌آور: BROKER_ACCOUNTING_ARCHITECTURE_FA.md
این فایل: توضیح اصطلاحات همان سند، برای خواندن کنسول /ops و commandها
سیاست تازه تعریف نمی‌کند. اگر با معماری تعارض داشت، معماری درست است.
خواندن در مرورگر: /docs/glossary و /docs/architecture

دو دفتر جدا:

دفتر منبع حقیقت چه چیزی را نگه می‌دارد
مالی TigerBeetle موجودی و انتقال حساب‌ها
عملیاتی PostgreSQL کاربر، نگاشت حساب، event، پوزیشن، allocation

یک عدد در کنسول ممکن است از هر دو بیاید. ستون تایگر مالی است؛ کش Postgres فقط تصویر است و اگر کهنه باشد stale می‌شود.


1. بازیگران

User. مشتری. بدهی بروکر به او در حساب‌های USER_* است، نه سکه‌ای که در یک والت جدا برایش قفل شده باشد.

System / Broker. خود بروکر. کارمزد، هزینه شبکه، بیمه، inventory اقتصادی.

Custody. محل نگهداری دارایی on-chain که بروکر کنترل می‌کند (والت‌های خودش یا custody provider). custody مالکیت اقتصادی کاربر نیست؛ فقط می‌گوید دارایی فیزیکی الان کجاست.

Venue / LP. صرافی یا نقدشوندگی بیرونی (مثلاً بایننس). دارایی‌ای که به آنجا رفته در VENUE_ASSET است، نه در والت بروکر.

A-Book. بروکر ریسک بازار را پیش مشتری نگه نمی‌دارد؛ معامله را سمت venue پوشش می‌دهد. برای همین باید روی venue موجودی واقعی داشته باشد.


2. دو نوع موجودی که نباید قاطی شوند

Liability (بدهی به کاربر). USER_AVAILABLE، USER_SPOT_LOCKED، USER_MARGIN، USER_WITHDRAWAL_LOCKED. جابه‌جایی بین این‌ها می‌گوید کاربر چقدر آزاد / در سفارش / در مارجین / در برداشت است. مجموع بدهی عوض نمی‌شود مگر واریز، برداشت، معامله، کارمزد یا اصلاح.

Location (محل دارایی بروکر). CUSTODY_* و VENUE_*. جابه‌جایی بین این‌ها می‌گوید سکه الان در کدام والت یا کدام صرافی است. بدهی کاربر عوض نمی‌شود.

مثال: انتقال ۲۰ BTC از Hot به Cold فقط location است. موجودی قابل برداشت علی همان است.


3. Custody — محل‌های نگهداری

Pooled custody یعنی سکه‌های کاربران در چند والت مشترک است، نه یک والت اختصاصی برای هر نفر. روی زنجیره یک UTXO/توکن است؛ در دفتر، بدهی هر کاربر جدا ثبت می‌شود.

حساب در کنسول یعنی چه
CustodyDeposit مقصد واقعی واریز on-chain. واریز اول اینجا می‌نشیند، نه لزوماً در Hot.
CustodyHot والت گرم؛ امضای آنلاین، برای برداشت و ارسال به venue.
CustodyWarm لایه میانی؛ کمتر در دسترس از Hot، بیشتر از Cold.
CustodyCold ذخیره‌ی آفلاین / چندامضایی سخت.
OnchainOutboundInFlight دارایی از والت خارج شده (tx پخش شده) ولی هنوز نهایی نشده.

Custody move. جابه‌جایی داخل همین محل‌ها، مثلاً Deposit → Hot (sweep) یا Hot → Cold. اگر کارمزد شبکه بدهی، هزینهٔ بروکر است (NetworkFeeExpense)، نه کم شدن بدهی کاربر.

واریز کاربر:

زنجیره تأیید شد
    → Debit  CustodyDeposit
    → Credit UserAvailable
بعداً اگر sweep شود
    → CustodyDeposit  →  CustodyHot     (کاربر نمی‌فهمد)

4. سطل‌های موجودی کاربر

حساب یعنی چه
UserAvailable آزاد؛ قابل انتقال داخلی، قفل سفارش، قفل برداشت، قفل مارجین.
UserSpotLocked برای سفارش اسپات کنار گذاشته شده؛ هنوز مال کاربر است.
UserWithdrawalLocked برای برداشت کنار گذاشته شده؛ تا confirm یا release از دسترس خارج است.
UserMargin وثیقهٔ پوزیشن مشتقه.
ClientBadDebtReceivable طلب بروکر از کاربر وقتی ضرر از موجودی بیشتر شده.

lock یعنی Available → آن سطل. release یعنی برعکس، وقتی کار لغو یا اضافه قفل آزاد می‌شود.


5. مرحله‌های برداشت (همان چهار فرمان کنسول)

برداشت یک state machine است، یک انتقال تکی نیست. بعد از broadcast ممکن است tx بیفتد، RBF شود، یا چند tx_hash برای یک withdrawal باشد. برای همین با pending transfer تایگر مدل نمی‌شود.

کاربر درخواست می‌دهد
        ↓
  Withdrawal lock      Available → WithdrawalLocked
        ↓
     (تأیید داخلی / امضا — هنوز command جدا در کنسول نیست)
        ↓
  Withdrawal broadcast دارایی از Hot می‌رود به InFlight
        ↓
  Withdrawal confirm   قفل کاربر و InFlight بسته می‌شوند

اگر قبل از پخش زنجیره کار لغو شد:

  Withdrawal release   WithdrawalLocked → Available

بعد از broadcast دیگر release خودکار نیست؛ اول باید معلوم شود tx چه شده.

فرمان چه کار می‌کند چه چیزی عوض نمی‌شود
Withdrawal lock مبلغ (+ کارمزد کاربر اگر باشد) را از آزاد برمی‌دارد و قفل می‌کند. هنوز هیچ tx روی زنجیره نیست.
Withdrawal release همان قفل را برمی‌گرداند. فقط وقتی tx پخش نشده. custody همان است.
Withdrawal broadcast سکه از CustodyHot به OnchainOutboundInFlight می‌رود (اصل + کارمزد شبکهٔ واقعی). بدهی کاربر هنوز در Locked است.
Withdrawal confirm بعد از نهایی شدن زنجیره: اصل از Locked جمع می‌شود، کارمزد شبکه هزینهٔ بروکر، کارمزد کاربر درآمد برداشت. InFlight باید صفر شود.

ترتیب اجباری: lock کامل → broadcast کامل → بعد confirm. confirm بیشتر از آنچه در InFlight ثبت شده حق ندارد بردارد.

withdrawal_id با tx_hash یکی نیست. یک برداشت می‌تواند چند تراکنش زنجیره داشته باشد.

مبلغ‌ها در confirm:


6. واریز و انتقال داخلی

Deposit. بعد از سیاست confirmation زنجیره: CustodyDeposit زیاد، UserAvailable زیاد. دارایی بروکر و بدهی به کاربر هر دو بالا می‌روند.

lifecycle عملیاتی واریز (watcher هنوز در این فاز نیست؛ فرمان کنسول فقط مرحلهٔ حساب‌شده است):

DETECTED → CONFIRMING → CONFIRMED → ACCOUNTED

Internal transfer. علی → سارا. فقط دو liability جابه‌جا می‌شود. custody و زنجیره دست نخورده می‌مانند.


7. Venue — رفتن دارایی پیش صرافی

بروکر برای پوشش A-Book باید روی venue موجودی داشته باشد.

فرمان معنی
Venue out از custody (معمولاً Hot) به راه: VenueInTransit. tx پخش شده، صرافی هنوز credit نکرده.
Venue in صرافی موجودی را نشان داد: VenueInTransit → VenueAsset.

VenueInTransit در حالت عادی بعد از تسویه باید صفر باشد.

VenueAsset محل اقتصادی دارایی نزد venue است، نه والت بروکر.


8. اسپات

اسپات واقعی است: در پایان خرید، بدهی بروکر به کاربر روی BTC زیاد می‌شود.

سفارش مشتری و اجرای venue یکی فرض نمی‌شوند. بینشان SpotSettlementClearing است. هدف این حساب در حالت پایدار صفر بودن است.

فرمان معنی
Spot lock سقف لازم (نوتیشنال + بدترین کارمزد) از Available به SpotLocked.
Spot release باقیماندهٔ قفل بعد از fill ناقص یا لغو.
Client buy / sell تسویه با مشتری: Locked/Available او و clearing. قیمت مشتری.
Venue buy / sell تسویه با صرافی: VenueAsset و clearing. قیمت/مقدار واقعی اجرا.
Inventory buy / sell پر کردن از موجودی خود بروکر (BrokerSpotInventoryReserve)، بدون ساختن venue جعلی.
Spread / improvement اختلاف مشتری و اجرا: ماندهٔ مثبت درآمد اسپرد، منفی هزینهٔ بهبود قیمت.
Allocations در Postgres می‌گوید کدام client fill از کدام venue/inventory آمده.

ترتیب تست معمول خرید:

Spot lock (USDT)
    → Client buy     (کاربر USDT می‌دهد، BTC می‌گیرد)
    → Venue buy      (بروکر روی صرافی USDT می‌دهد، BTC می‌گیرد)
    → Spread         اگر قیمت‌ها یکی نبود

base دارایی معامله‌شده است (BTC). quote واحد قیمت است (USDT).


9. مشتقه (A-Book)

فرمان معنی
Margin lock / release Available ⇄ Margin.
Open position پوزیشن در Postgres؛ مارجین از قبل باید قفل باشد.
Close position realizedPnl مثبت = سود مشتری (هزینهٔ بروکر). منفی = زیان مشتری (درآمد بروکر)، اول از Margin بعد Available. کسری → bad debt.
Hedge PnL نتیجهٔ پوشش روی venue؛ جدا از PnL مشتری.
Client funding funding دوره‌ای بین مشتری و بروکر.
Venue funding همان مفهوم سمت موجودی venue.
Liquidation بستن اجباری؛ کارمزد لیکویید و زیان تحقق‌یافته.
Bad-debt write-off وقتی طلب از مشتری دیگر وصول‌شدنی نیست.

10. کارمزد و اصلاح

فرمان معنی
Trading fee کارمزد معامله از Available یا از SpotLocked.
Venue fee کارمزد اجرا که venue می‌گیرد؛ هزینهٔ بروکر از VenueAsset.
Correction اصلاح دستی با debit/credit نام‌دار. مسیر آزاد برای هر دو حساب دلخواه نیست؛ owner از نوع حساب می‌آید (کاربر / custody / venue / system).

11. اصطلاحات کنسول و دفتر

Ensure user. کاربر را در Postgres می‌سازد و حساب‌های لازم آن دارایی را در تایگر provision می‌کند (خالی). تا واریز نکنی موجودی ندارد.

amount. واحد خرد دارایی است، نه واحد نمایش. USDT با scale ۶ یعنی 1000000 = ۱ USDT.

Debit / Credit. در تایگر هر انتقال از یک حساب کم و به یکی زیاد می‌کند. برای liability، credit یعنی بدهی بروکر به کاربر زیاد شد.

Accounting event / leg. یک رخداد کسب‌وکار (واریز، lock، confirm، …) ممکن است چند leg داشته باشد. همهٔ legهای یک event با هم linked می‌شوند تا ناقص نمانند.

operationId. کلید idempotency همان فرمان. تکرار همان id همان نتیجه را برمی‌گرداند، دوباره پول جابه‌جا نمی‌کند.

stale. کش balance_cache در Postgres از موجودی زندهٔ تایگر عقب است (آستانهٔ سخت ۵ ثانیه). ستون تایگر منبع مالی است.

Reconciliation. جمع بدهی‌های کاربر + ذخیره‌ها باید با جمع locationها (custody + venue + in-flight) برای هر دارایی جور باشد.

Suspense. حساب انتظار وقتی منبع یا مقصد قطعی نیست (DepositSuspense, WithdrawalSuspense, ReconciliationSuspense).

Chain reorg. زنجیره بلاک را بازچینی کرد؛ transfer قبلی پاک نمی‌شود، correction می‌خورد. اگر موجودی کاربر برای برگشت کافی نبود به ChainReorgReceivable می‌رود.


12. نقشهٔ سریع فرمان → بخش سند

گروه کنسول بخش معماری
واریز / انتقال §14 Deposit، §15 Internal Transfer
Custody §16 Hot/Warm/Cold، §17 Venue
برداشت §25 Withdrawal
اسپات §18–§21
کارمزد §21
مشتقه §22–§24
اصلاح §29
حساب‌ها §7 و §8