yanyan ho
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # MARGIN https://pacific-tuck-372.notion.site/Dex-FundingFee-Design-dc43fa7e22db4162b2a45681148ede51 https://pacific-tuck-372.notion.site/Dex-Margin-Design-3f3d004ad37744558eaaf18b219c77ec https://pacific-tuck-372.notion.site/margin-156450e57e1e44bdac1cdfc1e67a49b9 https://pacific-tuck-372.notion.site/Lite-Paper-34aa321bf48a48b4b5d2c86e12420a34 litepaper https://pacific-tuck-372.notion.site/4fff7f429b0e4e8589806b95e8d74081 whitehat https://pacific-tuck-372.notion.site/SSoT-4e68f85e4ffa44fda68bef6b9ce5c936 https://pacific-tuck-372.notion.site/249b552daa1d42819c8e791a1d5ef1fc?v=24f9973fade84b489a90c9bb64c10e66 https://www.notion.so/BANA-Tokenomics-Design-06e8745f492a4294ae2bd689ea1e87fc https://pacific-tuck-372.notion.site/ApeX-c3dcfd14e8434468897ce5c8d4501cfd # **margin合约的设计和实现** ### **1. 架构** 作为apeX交易站的一个重要模块,margin在整个协议的角色如图所示,负责管理所有用户的仓位,包括加减保证金、开平仓和清算、更新全局CPF等,它的前端是router(目前开平仓操作仅对config合约中的白名单router开放调用),后端是具有一一绑定关系的Amm。margin的正常运行依赖于Amm中有足够的流动性,以及bot可以对可清算仓位进行及时清算等。 ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/1227555e-ac9f-4b22-82fc-d9994e5bebaf/Untitled.png) ### **2. 设计** ### **2.1 仓位管理** 用户预先存入保证金后,就可以依据这笔保证金进行杠杆交易。以下简要描述margin的仓位管理过程,以一次eth-vUSD开平仓为例,假设最初amm中流动性对应的token数量分别是:5000eth,10000000vUSD,场内价格2000vUSD/eth。 - trader添加2eth的保证金,然后在2000块的价格开了20000vUSD的多仓,开完仓后margin中的该trader的仓位信息是:eth有2+9.98个,vUSD有-20000个;amm经过swap,剩下4990.02个eth和10020000个vUSD。 - 平仓的过程就是把vUSD绝对值变小:平多仓时,需要卖掉足量eth,填补vUSD负债;平空仓时,需要把vUSD卖掉,填补eth负债。 - 当考虑了fundingFee和风控参数beta的仓位负债率达到100%时,仓位清空且清算后仓位的剩余资产由amm承担 ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/2791aebe-87e5-433f-bfea-04dae17c9795/Untitled.png) ### **2.2 资金费收支** 为了让AMM中的场内价格紧跟场外的指数价格,设置了资金费用的机制,根据场内和场外的溢价在多空双方进行资金费用的结算,必要时AMM充当仓位少的那一方。考虑到链上无法集中结算所有仓位的资金费用,所以在用户操作自己仓位时,利用累计溢价率(CPF,cumulative premium fraction)的差值进行实时资金费用的结算。 - Premium Fraction (PF) 计算公式 $PF=\dfrac{MarkPrice-IndexPrice}{IndexPrice} * \dfrac{1}{FundingDuration}$ - 资金费收支示例 每当有用户操作自己仓位时,会先触发全局CPF的更新,这个更新会影响全部持仓账户的资金费用,然后通过全局CPF和上一次自己操作仓位时用户CPF的差值以及当前持仓大小进行资金费的收支。 以下是资金费用结算的一个简单示例:trader1在全局CPF为0时开10个单位的多仓,在全局CPF为10时平掉所有仓位,需要支付100;trader2在全局CPF为0时开10个单位的多仓,在全局CPF为10时平掉一半仓位,需要支付100(此时需要记录用户CPF为10),然后在全局CPF为-5时平掉剩余仓位,赚了75;trader3在全局CPF为5时开20个单位的空仓,在全局CPF为10时平掉所有仓位,赚了100。 ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/481a8426-dec7-4c63-8e95-ec6e3b88acd1/Untitled.png) 真实场景中,为了减少AMM因被动参与资金费结算带来的损失,会对收支系数进行调整(乘以或除以Long/Short),以实现AMM在资金费结算时赚的更多一点、亏的更少一点。 ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/07704985-7d0c-41bc-b941-08a38feda902/Untitled.png) - 其他说明 > 多头trader资金费用的对手方是空头trader,不足或多出的部分由Amm承担。CPF更新包含两种情况:用户操作仓位时会被动触发全局CPF和该用户的CPF、bot主动触发全局CPF。每次操作仓位时,都需要对总Long或Short进行更新部分平仓时,资金费率是全部结算的,对照收支示例的trader2。 > ### **2.3 数据结构** 对应上面的仓位管理过程,需要相应的数据结构,以下是几个关键的变量及其数据结构:traderPositionMap用来记录每个用户的持仓信息和保证金信息;traderCPFMap记录每个用户对应的最后一次结算时CPF,用于计算仓位fundingFee的收支,CPF是一个可正可负的溢价率累积指数。 - traderPositionMap(trader -> position) > position(包含quoteSize、baseSize、tradeSize) > > - quoteSize是quote的数量 > - baseSize是base的总数量 > - tradeSize是quoteSize对应的成本,base计价 > - quoteSize、baseSize都是可正可负。如果quoteSize为正,净持有short仓位;quoteSize为负,净持有long仓位 > - quoteSize/tradeSize就是当前仓位的平均入场价 1个eth开10倍仓位,现价500,basesize指的是11eth、quotesize指的是550vusd、tradesize指的是10 eth(By arwen) - traderCPFMap(trader -> CPF) ### **3. 实现** ### **3.1 配置项** 设置参数(都是通过config合约来设置,然后在margin合约读取) - 初始保证金率(跟apeX的最大开仓杠杆有关) - 清算负债率阈值(仓位的负债率高于此值时,可以被清算,如100%) > (quote资产或负债的总市值用priceOracle中的AccountSpecificMarkPrice来计价,这样不管做空做多,都通过beta考虑到了quote数量对滑点的影响,为安全清算留出buffer) > > > 资产 = 余额为正的资产总市值 > 负债 = 余额为负的资产总市值 > 负债率 = 负债 / 资产 > - 清算费率(支付给清算机器人的盈利,清算剩余资产的百分比) - CPF boost(防止多空严重不平衡时,fundingFee收支太大,设置的边界值) - beta(风控参数) - routerMap(可以写margin状态的router列表) ### **3.2 仓位写函数** - 增加保证金addMargin, 提高保证金率 需要指定增加的base保证金数量以及保证金充值到的账户,简要过程: - 需要trader先通过router合约将baseToken转入margin合约 - 检查上一步转入的base数量不少于depositAmount - 更新holder的position中baseSize - 更新margin合约的reserve值,reserve = _reserve + depositAmount; - 减少保证金removeMargin 需要指定从哪个账户withdraw保证金、需要withdraw到哪个账户以及withdraw的base数量,简要过程: - 更新fundingFee的全局CPF,用于结算fundingFee. - 结算fundingFee。 - 计算未结盈亏PNL,检查调用者可以withdraw的保证金数量_getWithdrawable(基于用户当前仓位、风控参数beta和初始保证金率)。 1 用markprice计算未结盈亏。 2 计算负债率公式 ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/14afe8f4-4a83-4de4-8ae3-b088ec4317a8/Untitled.png) - 从trader position的baseSize减少保证金 - 按照fundingFee、unrealizedPnl、margin的先后顺序进行withdraw(疑问,funding fee, margin提即可, unpnl必须关仓才能提, 感觉这样逻辑会简单点) - 如果fundingFee有盈余且盈余超过withdraw数量,就直接提取withdraw,并把盈余剩下部分加到baseSize,作为已实现fundingFee - 如果fundingFee无法覆盖withdraw数量且未实现盈亏可以覆盖(withdraw数量-fundingFee),就将这部分未实现盈亏变为已实现盈亏 - 如果fundingFee无法覆盖withdraw数量且未实现盈亏无法覆盖(withdraw数量-fundingFee),就将未实现盈亏变为已实现盈亏,(withdraw数量-fundingFee-unrealizedPnl)由原始保证金承担 - 提取未实现盈亏时,仓位quoteSize不变,tradeSize变化,最终体现在平均入场价的修改 - 更新position - 更新用户CPF - 将保证金从margin合约直接转给to - 开仓openPosition 需要指定为哪个账户开仓、开仓方向(0long,1short)以及开仓的quote数量(已经乘了杠杆),简要过程: - 更新fundingFee的全局CPF,用于结算fundingFee - 检查仓位健康状况,杠杆符合初始保证金率 1. 如果有仓位的情况下,先模拟平调仓位,获取仓位此时的保证金; 2. 计算当前池子市价(如果市价跟场外价格偏差10%,或者兑换后价格差10%,以场外价格计算市场价) 3. 根据市价计算最大可开仓量(根据最大可开仓量公式)。 4. 调用amm swap 进行实际开仓 5. 更新仓位的tradesize - 同向加仓或新开仓,就直接加tradeSize,入场价应该会有变化 - 反向开小仓,按比例减tradeSize,入场价不变 - 反向开大仓,tradeSize减为0后,新开反向仓,入场价变为当前开仓价 6. 更新仓位的basesize,quotesize,以及池子当前总开仓量 7. 检查用户当前仓位小于最大开仓量 - 检查负债率是否小于清算线(负债率检查过程补充todo) ,禁止开仓即被清算(todo,是否跟最大开仓量互斥); - 更新position - 更新用户CPF - 平仓closePosition 需要指定为哪个账户平仓、以及平仓的quote数量,简要过程: - 更新fundingFee的全局CPF,用于结算fundingFee - 计算负债率,检查是否小于清算线 - 与amm进行swap平仓进行实际关仓 - 更新position - 更新用户CPF - 如果用户平完有坏账,由amm承担 - 清算liquidate 需要指定清算哪个账户以及清算奖励(base)的接收地址,简要过程: - 更新fundingFee的全局CPF,用于结算fundingFee - 计算负债率是否小于清算线 ,检查是否可以清算 - 根据仓位quoteSize和amm的swap函数,计算清算后对应的base资产数量 - 如果场内和oracle价差过大,就用oracle价格进行settle,然后forceSwap剩余的资产(盈利或亏损)到amm;如果价差不大,就直接将被清算仓位forceSwap到amm - 如果仓位清算完,有剩余资金,就将清算bonus转给to地址,剩下的转到treasury或amm,如果没有剩余资金,则无清算奖励 - 清除仓位 - 更新用户CPF - 更新全局CPF updateCPF 任何人都可以主动更新,也可以由用户操作仓位时被动更新,简要过程: - 从预言机获取最新的PF,并根据Long和Short以及时长计算出deltaPF - 累积deltaPF到全局CPF,完成更新 - baseToken的deposit和withdraw amm将流动性对应的baseToken转入转出margin合约 ### **3.3 仓位读函数** - 查询最新的CPF getNewLatestCPF:根据历史CPF和价差率*时长,计算实时的CPF,用于计算fundingFee - 查询可以减少的base保证金数量 getWithdrawable:基于最大开仓杠杆和风控参数beta,算出quoteSize对应的base资产,然后用baseSize减掉 - 查询用户最新的资金费 calFundingFee:根据用户仓位和最新的CPF,计算fundingFee的收入或亏损 - 查询用户负债率 calDebtRatio - 查询是否可以清算 canLiquidate:计算负债率是否超过清算负债率阈值,涉及到fundingFee和AccountSpecificMarkPrice - 查询用户未实现盈亏 calUnrealizedPnl:如果场内和oracle价差过大,就用oracle价格进行模拟平仓结算;如果价差不大,就直接以场内价格进行模拟平仓结算。 把仓位剩余的quotesize平掉得到baseAmount,然后用仓位tradeSize减去baseAmount ### **3.4 其他说明** - 仓位有四种情形:有盈利、有亏损但未至清算、可清算且无坏账、可清算且有坏账 - margin合约可以处理base资产(如eth)和虚拟的quote资产(如vUSD) - 仓位以全仓模式进行管理,非逐仓模式 - 清算情况下,没有部分平仓,要平就全部平掉;普通平仓可以部分平仓 - 不设立保险基金,清算导致的赔付和盈余由amm负责 - 触发清算的价格是场内twap标记价格(AccountSpecificMarkPrice),实际清算时直接forceSwap场外价格结算的剩余资金或场内价格计算的仓位 - 清算机器人通过graph监控链上仓位,对不健康的仓位进行清算

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully