LogoLogo
  • Overview
    • Introduction
    • Table of Contents
  • Token Information
    • Symmio Foundation
  • Protocol Architecture
    • Protocol Introduction
    • Technical Documentation
      • Building an Application with SYMM
        • Introduction and Diamond Explainer
        • Querying Info from the SYMM Diamond
        • MultiAccount
        • Creating an Account and Depositing Funds
        • Sending a Quote
        • Closing a Quote
        • Instant Trading
          • Instant Login (EOA)
          • Instant Login (Account Abstraction)
          • Sending a Quote (Instant Open)
          • Sending a Quote (Instant Close)
        • Frequently Used Queries
      • Solver Docs
        • Solver Docs (github)
        • Solver Implementation Guide (High Level Overview)
        • Building a Solver on SYMMIO
          • 1. Intent Creation
          • 2. Seeing the Intent
          • 3. Hedging Off-Chain
          • 4. Opening/Closing a Position On-Chain
          • Creating the APIs
            • GET Contract Symbols
            • GET Open Interest
            • GET Notional Cap
            • GET Price Range
            • GET Error Codes
            • GET Get Locked Params
            • GET Get Funding Info
            • POST Position State
          • Solver Flow Summary Example
          • Recommended Architecture for Solvers
          • Glossary
        • Conditional Orders Handler
        • Rasa Solver TP/SL Implementation
        • Instant Trading
          • Instant Trading (Solvers)
          • Rasa Instant Trading Implementation
          • Instant Trading Condition Checks
        • Fetching Gas Prices Script
        • How to Add a Market as a Solver
        • Verifying Account Abstracted Instant Actions (ERC-4337)
      • Frontend Docs
        • Setting up a Frontend with SYMMIO
        • Frontend SDK Setup Guide
        • MultiAccount Deployment Guide
        • Instant Trading (Frontends)
          • Account Abstracted Instant Actions (Frontends)
        • Implement a Trading Bot on Symmio (OLD)
          • Setup
          • Creating a Sub-Account
          • Minting Collateral Tokens (Optional)
          • Depositing and Allocating Tokens
          • Obtaining Muon Signatures
          • Sending a Quote
          • Monitoring Price for Execution
      • Contract Docs
        • SYMMIO CORE v0.82
        • Contracts Documentation 0.8.2
          • Main Flow
          • The SYMM Diamond
          • Facets
            • Account Facet
            • Control Facet
            • Funding Rate Facet
            • PartyA Facet
            • PartyB Facet
            • Liquidation Facet
            • View Facet
          • MultiAccount
            • PartyA
            • PartyB
          • SYMM App (Muon)
            • LibMuon
            • MuonStorage
        • Contracts Documentation 0.8.3
          • Facets
            • Control Facet
            • Account Facet
            • PartyA Facet
            • PartyB Facet
            • View Facet
            • Bridge Facet
            • Liquidation Facet (Implementation)
          • Modified Events
          • New Events
          • MuonStorage
        • Contracts Documentation 0.8.4
          • Main Flow (0.8.4)
          • The SYMM Diamond (0.8.4)
          • Facets
            • Account Facet (0.8.4)
            • Bridge Facet (0.8.4)
            • Control Facet (0.8.4)
            • Force Actions Facet (0.8.4)
            • Funding Rate Facet (0.8.4)
            • Liquidations Facet (0.8.4)
            • PartyA Facet (0.8.4)
            • PartyB Group Actions Facet (0.8.4)
            • PartyB Quote Actions Facet (0.8.4)
            • PartyB Position Actions Facet (0.8.4)
            • Settlement Facet (0.8.4)
            • View Facet (0.8.4)
          • MultiAccount (0.8.4)
            • SymmioPartyA
            • SymmioPartyB
          • SYMM App (Muon)
            • LibMuon (0.8.4)
            • MuonStorage (0.8.4)
      • Contract Addresses / Solver Endpoints
        • Mantle
        • Mode
        • IOTA
        • Base
        • BSC
        • Arbitrum
        • Polygon
        • Berachain
        • Solver Endpoints and Addresses
          • Perps Hub
          • Rasa Capital
          • Rasa Capital (Zero Spread)
          • Zenith
      • How to Query our Contracts
      • Muon API Queries
      • Solver Error Codes
      • Interacting with SYMMIO Contracts
    • Protocol higher level architecture
      • 12-Hour Fraud Proof Window
      • PartyB
      • Solver Settings
      • Max Leverage
      • Maintenance Margin (CVA) Calculations
    • Symmio Whitepaper
  • Building on Symmio
    • Builders introduction
    • Solving for Symmio
      • Solver documentation
      • Solver - Example Flow
    • Trading Fees
      • Perps - Settlement Costs
      • Pair Trading - Settlement costs
    • Exchanges (Frontends)
      • Frontend Introduction
      • SDK - SYMM client
      • Trade on Symmio
  • Legal & Brand & Security
    • Security (Audits / Bugbounty)
      • Bug bounty / Coverage
        • How to contact ?
      • Audits
        • SYMM - V0.8 - 0.81
          • Sherlock Audit - Jun 15, 2023
          • Smart State - Jul 2, 2023
        • SYMM - 0.82
          • Sherlock Audit -Aug 30, 2023
        • SYMM - 0.83
          • Sherlock Audit - Jun 17, 2024
        • SYMM - 0.84
          • Sherlock Audit - Oct 3, 2024
        • Vaults
          • Sherlock Audit - Jan 2, 2024
    • Terms of Service & Licensing
      • TRADEMARK & COPYRIGHT NOTICE
      • CONTACT US
      • TERMS OF SERVICE
      • FRONTEND LICENSE
        • Frontend Modifications
        • Frontend Use Grants
      • CONTRACT LICENSE
        • Contract Use Grants
        • Contract Modifications
    • Brand - Assets Logos
Powered by GitBook
LogoLogo

All rights to the people (c) 2023 Symmetry Labs A.G.

On this page
  • /get_funding_info
  • Get Funding Info Rasa Implementation
  • Router
  • Data Sources
  • Logic
  1. Protocol Architecture
  2. Technical Documentation
  3. Solver Docs
  4. Building a Solver on SYMMIO
  5. Creating the APIs

GET Get Funding Info

/get_funding_info

/get_funding_info

Example Query:

https://base-hedger82.rasa.capital/get_funding_info

Example Response:

  "BTCUSDT": {
    "next_funding_time": 1744070400000,
    "next_funding_rate_short": "0.000040455",
    "next_funding_rate_long": "-0.000053940",
    "funding_rate_epoch_duration": 14400
  },
  "FILUSDT": {
    "next_funding_time": 1744070400000,
    "next_funding_rate_short": "0.000045081",
    "next_funding_rate_long": "-0.000060108",
    "funding_rate_epoch_duration": 14400
  },

Get Funding Info Rasa Implementation

Router

@common_router.get(
    '/get_funding_info',
    response_model=Dict[str, FundingInfoResponseSchema],
    dependencies=[
        Depends(CustomRateLimiter(times=1, seconds=1)),
        Depends(CustomRateLimiter(times=40, minutes=1)),
        Depends(CustomRateLimiter(times=1500, hours=1)),
    ]
)
async def get_funding_info(symbols: List[symbol_enum] = Query(None)):
    # symbols: optional list of tickers; defaults to BaseSymbols if None
    return get_funding_rates(symbols or BaseSymbols)

Output:

  • Dict mapping ticker → FundingInfoResponseSchema.

class FundingInfoResponseSchema(BaseModel):
    next_funding_time: int
    next_funding_rate_short: Decimal
    next_funding_rate_long: Decimal

Data Sources

  1. Symbol table (DB)

    • Symbol.funding_rate_epoch_duration

    • Symbol.funding_rate_window_time

  2. External exchange (Binance)

    • binance_client.futures_mark_price() → lastFundingRate, nextFundingTime

  3. Hedger coefficients (from settings.py)

    • FundingRateHedgerToUserCoefficient

    • FundingRateUserToHedgerCoefficient

  4. Positions table (DB)

    • Used for filtering and in expressions (Positions.position_type, Positions.opened_price, etc.)

Logic

In short, the logic can be summarized like this:

GET /get_funding_info
    ↓
get_funding_info(symbols) #Entry point 
    ↓
get_funding_rates(symbols)    
    ├─→ FundingRate.get_symbol_funding_details()
    ├    # read Symbol.is_valid from DB
    ├    # call binance_client.futures_mark_price()
    ├    # return List[SymbolFundingDetail]
    └─→ FundingRate.get_funding_details(..., to_apply=False)
    ├    # 1) build SQL CTE from symbol_funding_details
    ├    # 2) apply hedger’s long/short coefficients
    ├    # 3) compute contract_rate expression
    ├    # 4) group by Positions.party_a_address
    ├    # 5) optional $-amount filtering if to_apply=True
    ├    # 6) session.all_(stmt) → [FundingDetail(...)]
    ↓
map into Dict[str, FundingInfoResponseSchema]
    ↓
return JSON

Fetch Symbol & Market Details

@staticmethod
def get_symbol_funding_details() -> List[SymbolFundingDetail]:
    # 1) Fetch mark‐price & funding‐time info for all symbols from Binance
    binance_markets: Dict[str, BinanceMarketDetail] = binance_client.futures_mark_price()

    # 2) Record current time (in seconds) to compare against each symbol’s funding window
    start_time = get_now_epoch()

    result: List[SymbolFundingDetail] = []
    # 3) Load every valid symbol row from your local Symbol table
    for symbol in session.scalars_all(
        Symbol.select().where(Symbol.is_valid.is_(true()))
    ):  

        # 4) Read the next funding timestamp (ms→s) from Binance’s data
        binance_next_funding_time = binance_markets[symbol.title].nextFundingTime // 1000
        
        # 5) Only keep symbols whose next funding falls within the on-chain funding window
        if binance_next_funding_time < start_time + symbol.funding_rate_window_time:
            symbol_funding_detail = SymbolFundingDetail(
                symbol_id                = symbol.symbol_id,
                binance_mark_price       = binance_markets[symbol.title].markPrice,
                binance_last_funding_rate= binance_markets[symbol.title].lastFundingRate,
                binance_next_funding_time= binance_next_funding_time,
                funding_rate_window_time = symbol.funding_rate_window_time,
            )

            # 7) Sanity check: confirm on-chain epoch aligns with Binance’s tick
            #    If it doesn’t, emit an alert and skip this symbol
            if binance_next_funding_time % symbol.funding_rate_epoch_duration != 0:
                send_instant_error_message(
                    title='Funding time of contract not compatible with Binance.',
                    amend=asdict(symbol_funding_detail)
                )
                continue

            # 8) Add to the list of symbols we’ll compute funding for
            result.append(symbol_funding_detail)

    # 9) Return all valid SymbolFundingDetail entries
    return result

Coefficient Application Logic

@staticmethod
def get_funding_details(
    symbol_funding_details: List[SymbolFundingDetail],
    to_apply: bool = True
) -> Optional[List[FundingDetail]]:
    # 1) Build an in-SQL CTE of symbol timing & rates
    symbol_details_expr = values(
        column('symbol_id', Integer),
        column('price',     Numeric(**numeric_args)),
        column('funding_rate', Numeric(**numeric_args)),
        column('funding_window_open_time', BigInteger),
        column('binance_next_funding_time', BigInteger),
        name='funding_details'
    ).data([
        detail.get_data_for_cte()
        for detail in symbol_funding_details
    ])

    # 2) Apply hedger coefficients to raw funding_rate
    funding_rate_expr = symbol_details_expr.c.funding_rate * case(
        # SHORT & positive → hedger pays user (negate HedgerToUserCoef)
        (and_(Positions.position_type == PositionType.SHORT,
              symbol_details_expr.c.funding_rate >= 0),
         -FundingRateHedgerToUserCoefficient),

        # SHORT & negative → user pays hedger (negate UserToHedgerCoef)
        (and_(Positions.position_type == PositionType.SHORT,
              symbol_details_expr.c.funding_rate < 0),
         -FundingRateUserToHedgerCoefficient),

        # LONG & positive → user pays hedger
        (and_(Positions.position_type == PositionType.LONG,
              symbol_details_expr.c.funding_rate >= 0),
         FundingRateUserToHedgerCoefficient),

        # LONG & negative → hedger pays user
        (and_(Positions.position_type == PositionType.LONG,
              symbol_details_expr.c.funding_rate < 0),
         FundingRateHedgerToUserCoefficient)
    )

    # 3) Embed into full “contract rate” formula
    sign = case((Positions.position_type == PositionType.SHORT, -1), else_=1)
    contract_rate = func.round(
        (
            (
                (funding_rate_expr * symbol_details_expr.c.price)
                / (Positions.funding_rate_diff * Positions.opened_price)
                * sign + 1
            ) * Positions.funding_rate_diff - 1
        ) * sign,
        NumberFloatingPoint
    )

    # 4) Build query: group by counterparty (party A)
    stmt = Positions.select(
        Positions.party_a_address,
        func.json_agg(Positions.quote_id),
        func.json_agg(contract_rate)
    ).outerjoin(
        AppliedFundingRate, Positions.quote_id == AppliedFundingRate.quote_id
    ).join(Symbol).select_from(symbol_details_expr).join(
        symbol_details_expr,
        Symbol.symbol_id == symbol_details_expr.c.symbol_id
    ).where(
        AppliedFundingRate.id.is_(None),
        Positions.state.in_([PositionState.OPEN, PositionState.CLOSE_PENDING]),
        Positions.open_time <= symbol_details_expr.c.binance_next_funding_time,
        or_(
            Positions.last_funding_time < symbol_details_expr.c.funding_window_open_time,
            Positions.last_funding_time.is_(None)
        )
    ).group_by(Positions.party_a_address)

    # 5) If “to_apply”, also calculate $-amount and filter tiny ones
    if to_apply:
        funding_amount = (
            (Positions.quantity - Positions.filled_closed_amount)
            * Positions.opened_price * contract_rate
        )
        stmt = stmt.add_columns(
            func.json_agg(
                case(
                    (contract_rate > Positions.max_funding_rate,
                     Positions.max_funding_rate),
                    else_=contract_rate
                )
            ),
            func.sum(funding_amount).label('funding_amount')
        ).where(
            func.abs(funding_amount) > GasWorthyFundingThresholdPerPosition
        ).order_by(desc('funding_amount'))

    # 6) Execute and map to dataclass
    rows = session.all_(stmt)
    return [FundingDetail(*row) for row in rows]
PreviousGET Get Locked ParamsNextPOST Position State

Last updated 12 days ago