Updatred README with a lot more sample code.
This commit is contained in:
parent
09b10c6efb
commit
56159ac777
348
README.md
348
README.md
|
@ -32,59 +32,327 @@ The latest version of the code is in the [main branch on Github](https://github.
|
|||
Code to integrate with Version 2 of Mango is in the [v2 branch](https://github.com/blockworks-foundation/mango-explorer/tree/v2).
|
||||
|
||||
|
||||
## Example
|
||||
## Examples
|
||||
|
||||
Here's a brief but complete example of how to place and cancel an order. [This example is runnable in your browser](https://mybinder.org/v2/gh/blockworks-foundation/mango-explorer-examples/HEAD?labpath=PlaceAndCancelOrders.ipynb)!
|
||||
Here are some example snippets to get you started.
|
||||
|
||||
Many more examples are provided in a separate [Github repo](https://github.com/blockworks-foundation/mango-explorer-examples) and can be [run in your browser (no installation required!) at Binder](https://mybinder.org/v2/gh/blockworks-foundation/mango-explorer-examples/HEAD).
|
||||
|
||||
|
||||
### Show OrderBook
|
||||
> [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/blockworks-foundation/mango-explorer-examples/HEAD?labpath=ShowOrderBook.ipynb) [Full example code](https://github.com/blockworks-foundation/mango-explorer-examples/blob/main/ShowOrderBook.ipynb)
|
||||
|
||||
This code will connect to the _devnet_ cluster, fetch the orderbook for BTC-PERP, and print out a summary of it:
|
||||
```
|
||||
import mango
|
||||
|
||||
with mango.ContextBuilder.build(cluster_name="devnet") as context:
|
||||
market = mango.market(context, "BTC-PERP")
|
||||
print(market.fetch_orderbook(context))
|
||||
```
|
||||
|
||||
|
||||
### Subscribe to OrderBook
|
||||
> [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/blockworks-foundation/mango-explorer-examples/HEAD?labpath=SubscribeOrderBook.ipynb) [Full example code](https://github.com/blockworks-foundation/mango-explorer-examples/blob/main/SubscribeOrderBook.ipynb)
|
||||
|
||||
This code will connect to the _devnet_ cluster and will print out the latest orderbook every time the orderbook changes, and will exit after 60 seconds.
|
||||
```
|
||||
import datetime
|
||||
import mango
|
||||
import time
|
||||
|
||||
with mango.ContextBuilder.build(cluster_name="devnet") as context:
|
||||
market = mango.market(context, "BTC-PERP")
|
||||
subscription = market.on_orderbook_change(context, lambda ob: print("\n", datetime.datetime.now(), "\n", ob))
|
||||
|
||||
time.sleep(60)
|
||||
|
||||
subscription.dispose()
|
||||
|
||||
print("Example complete.")
|
||||
```
|
||||
|
||||
|
||||
### Show Perp Fills
|
||||
> [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/blockworks-foundation/mango-explorer-examples/HEAD?labpath=ShowPerpFills.ipynb) [Full example code](https://github.com/blockworks-foundation/mango-explorer-examples/blob/main/ShowPerpFills.ipynb)
|
||||
|
||||
A 'fill' is when a maker order from the orderbook is matched with an incoming taker order. It can be useful to see these.
|
||||
|
||||
This code will connect to the _devnet_ cluster and fetch all recent events. It will then show all the fill events.
|
||||
```
|
||||
import mango
|
||||
|
||||
with mango.ContextBuilder.build(cluster_name="devnet") as context:
|
||||
market = mango.market(context, "BTC-PERP")
|
||||
event_queue = mango.PerpEventQueue.load(context, market.event_queue_address, market.lot_size_converter)
|
||||
print(event_queue.fills)
|
||||
|
||||
print("Example complete.")
|
||||
```
|
||||
|
||||
|
||||
### Subscribe to Fills
|
||||
> [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/blockworks-foundation/mango-explorer-examples/HEAD?labpath=SubscribeFills.ipynb) [Full example code](https://github.com/blockworks-foundation/mango-explorer-examples/blob/main/SubscribeFills.ipynb)
|
||||
|
||||
This code will connect to the _devnet_ cluster and print out every fill that happens. It will exit after 60 seconds.
|
||||
```
|
||||
import datetime
|
||||
import mango
|
||||
import time
|
||||
|
||||
with mango.ContextBuilder.build(cluster_name="devnet") as context:
|
||||
market = mango.market(context, "BTC-PERP")
|
||||
subscription = market.on_fill(context, lambda ob: print("\n", datetime.datetime.now(), "\n", ob))
|
||||
|
||||
time.sleep(60)
|
||||
|
||||
subscription.dispose()
|
||||
|
||||
print("Example complete.")
|
||||
```
|
||||
|
||||
### Place Order
|
||||
> [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/blockworks-foundation/mango-explorer-examples/HEAD?labpath=PlaceOrder.ipynb) [Full example code](https://github.com/blockworks-foundation/mango-explorer-examples/blob/main/PlaceOrder.ipynb)
|
||||
|
||||
This code will load the 'example' wallet, connect to the _devnet_ cluster, place an order and wait for the order's transaction signature to be confirmed.
|
||||
|
||||
The order is an IOC ('Immediate Or Cancel') order to buy 2 SOL-PERP at $1. This order is unlikely to be filled (SOL currently costs substantially more than $1), but that saves having to show order cancellation code here.
|
||||
|
||||
Possible `order_type` values are:
|
||||
* mango.OrderType.LIMIT
|
||||
* mango.OrderType.IOC
|
||||
* mango.OrderType.POST_ONLY
|
||||
* mango.OrderType.MARKET (it's nearly always better to use IOC and a price with acceptable slippage)
|
||||
* mango.OrderType.POST_ONLY_SLIDE (only available on perp markets)
|
||||
```
|
||||
import decimal
|
||||
import mango
|
||||
import os
|
||||
import time
|
||||
|
||||
# Load the wallet from the environment variable 'KEYPAIR'. (Other mechanisms are available.)
|
||||
wallet = mango.Wallet(os.environ.get("KEYPAIR"))
|
||||
from solana.publickey import PublicKey
|
||||
|
||||
# Create a 'devnet' Context
|
||||
context = mango.ContextBuilder.build(cluster_name="devnet")
|
||||
# Use our hard-coded devnet wallet for DeekipCw5jz7UgQbtUbHQckTYGKXWaPQV4xY93DaiM6h.
|
||||
# For real-world use you'd load the bytes from the environment or a file. Later we use
|
||||
# its Mango Account at HhepjyhSzvVP7kivdgJH9bj32tZFncqKUwWidS1ja4xL.
|
||||
wallet = mango.Wallet(bytes([67,218,68,118,140,171,228,222,8,29,48,61,255,114,49,226,239,89,151,110,29,136,149,118,97,189,163,8,23,88,246,35,187,241,107,226,47,155,40,162,3,222,98,203,176,230,34,49,45,8,253,77,136,241,34,4,80,227,234,174,103,11,124,146]))
|
||||
|
||||
# Load the wallet's account
|
||||
group = mango.Group.load(context)
|
||||
accounts = mango.Account.load_all_for_owner(context, wallet.address, group)
|
||||
account = accounts[0]
|
||||
with mango.ContextBuilder.build(cluster_name="devnet") as context:
|
||||
group = mango.Group.load(context)
|
||||
account = mango.Account.load(context, PublicKey("HhepjyhSzvVP7kivdgJH9bj32tZFncqKUwWidS1ja4xL"), group)
|
||||
market_operations = mango.operations(context, wallet, account, "SOL-PERP", dry_run=False)
|
||||
|
||||
# Load the market operations
|
||||
market_operations = mango.operations(context, wallet, account, "SOL-PERP", dry_run=False)
|
||||
# Try to buy 2 SOL for $1.
|
||||
order = mango.Order.from_values(side=mango.Side.BUY,
|
||||
price=decimal.Decimal(1),
|
||||
quantity=decimal.Decimal(2),
|
||||
order_type=mango.OrderType.IOC)
|
||||
print("Placing order:", order)
|
||||
placed_order_signatures = market_operations.place_order(order)
|
||||
|
||||
print("Initial order book:\n\t", market_operations.load_orderbook())
|
||||
print("Your current orders:\n\t", market_operations.load_my_orders(include_expired=True))
|
||||
|
||||
# Go on - try to buy 1 SOL-PERP contract for $10.
|
||||
order = mango.Order.from_values(side=mango.Side.BUY,
|
||||
price=decimal.Decimal(10),
|
||||
quantity=decimal.Decimal(1),
|
||||
order_type=mango.OrderType.POST_ONLY)
|
||||
placed_order = market_operations.place_order(order)
|
||||
print("\n\nPlaced order:\n\t", placed_order)
|
||||
|
||||
print("\n\nSleeping for 10 seconds...")
|
||||
time.sleep(10)
|
||||
|
||||
print("\n\nOrder book (including our new order):\n", market_operations.load_orderbook())
|
||||
print("Your current orders:\n\t", market_operations.load_my_orders(include_expired=True))
|
||||
|
||||
cancellation_signatures = market_operations.cancel_order(placed_order)
|
||||
print("\n\nCancellation signature:\n\t", cancellation_signatures)
|
||||
|
||||
print("\n\nSleeping for 10 seconds...")
|
||||
time.sleep(10)
|
||||
|
||||
print("\n\nOrder book (without our order):\n", market_operations.load_orderbook())
|
||||
print("Your current orders:\n\t", market_operations.load_my_orders(include_expired=True))
|
||||
print("Waiting for place order transaction to confirm...\n", placed_order_signatures)
|
||||
mango.WebSocketTransactionMonitor.wait_for_all(
|
||||
context.client.cluster_ws_url, placed_order_signatures, commitment="processed"
|
||||
)
|
||||
|
||||
print("Example complete.")
|
||||
```
|
||||
|
||||
Many more examples are provided in a separate [Github repo](https://github.com/blockworks-foundation/mango-explorer-examples) and can be [run in your browser (no installation required!) at Binder](https://mybinder.org/v2/gh/blockworks-foundation/mango-explorer-examples/HEAD).
|
||||
### Place and Cancel Order
|
||||
> [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/blockworks-foundation/mango-explorer-examples/HEAD?labpath=PlaceAndCancelOrders.ipynb) [Full example code](https://github.com/blockworks-foundation/mango-explorer-examples/blob/main/PlaceAndCancelOrders.ipynb)
|
||||
|
||||
This code will load the 'example' wallet, connect to the _devnet_ cluster, place an order and then cancel it.
|
||||
|
||||
This is a bit longer than the Place Order example but only because it performs most of the Place Order code as a setup to create the order so there's an order to cancel.
|
||||
|
||||
The key point is that `cancel_order()` takes an `Order` as a parameter, and that `Order` needs either the `id` or `client_id` property to be set. The easiest way to get such an order is from the `OrderBook`, so the code loads the `OrderBook` and then gets the current account's orders from it. Then the code cancels it and waits for the transaction to confirm.
|
||||
```
|
||||
import decimal
|
||||
import mango
|
||||
|
||||
from solana.publickey import PublicKey
|
||||
|
||||
# Use our hard-coded devnet wallet for DeekipCw5jz7UgQbtUbHQckTYGKXWaPQV4xY93DaiM6h.
|
||||
# For real-world use you'd load the bytes from the environment or a file. Later we use
|
||||
# its Mango Account at HhepjyhSzvVP7kivdgJH9bj32tZFncqKUwWidS1ja4xL.
|
||||
wallet = mango.Wallet(bytes([67,218,68,118,140,171,228,222,8,29,48,61,255,114,49,226,239,89,151,110,29,136,149,118,97,189,163,8,23,88,246,35,187,241,107,226,47,155,40,162,3,222,98,203,176,230,34,49,45,8,253,77,136,241,34,4,80,227,234,174,103,11,124,146]))
|
||||
|
||||
with mango.ContextBuilder.build(cluster_name="devnet") as context:
|
||||
group = mango.Group.load(context)
|
||||
account = mango.Account.load(context, PublicKey("HhepjyhSzvVP7kivdgJH9bj32tZFncqKUwWidS1ja4xL"), group)
|
||||
market_operations = mango.operations(context, wallet, account, "SOL-PERP", dry_run=False)
|
||||
|
||||
print("Orders (initial):")
|
||||
print(market_operations.load_orderbook())
|
||||
|
||||
order = mango.Order.from_values(side=mango.Side.BUY,
|
||||
price=decimal.Decimal(10),
|
||||
quantity=decimal.Decimal(1),
|
||||
order_type=mango.OrderType.POST_ONLY)
|
||||
print("Placing order:", order)
|
||||
placed_order_signatures = market_operations.place_order(order)
|
||||
|
||||
print("Waiting for place order transaction to confirm...\n", placed_order_signatures)
|
||||
mango.WebSocketTransactionMonitor.wait_for_all(
|
||||
context.client.cluster_ws_url, placed_order_signatures, commitment="processed"
|
||||
)
|
||||
|
||||
print("\n\nOrders (including our new order):")
|
||||
orderbook = market_operations.load_orderbook()
|
||||
print(orderbook)
|
||||
|
||||
my_orders = orderbook.all_orders_for_owner(account.address)
|
||||
print("My orders on the orderbook:", my_orders)
|
||||
|
||||
cancellaton_signatures = market_operations.cancel_order(my_orders[0])
|
||||
|
||||
print("Waiting for cancel order transaction to confirm...\n", cancellaton_signatures)
|
||||
mango.WebSocketTransactionMonitor.wait_for_all(
|
||||
context.client.cluster_ws_url, cancellaton_signatures, commitment="processed"
|
||||
)
|
||||
|
||||
print("\n\nOrders (without our order):")
|
||||
print(market_operations.load_orderbook())
|
||||
|
||||
print("Example complete.")
|
||||
```
|
||||
|
||||
|
||||
### Show Account Data
|
||||
> [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/blockworks-foundation/mango-explorer-examples/HEAD?labpath=ShowAccountDataFrame.ipynb) [Full example code](https://github.com/blockworks-foundation/mango-explorer-examples/blob/main/ShowAccountDataFrame.ipynb)
|
||||
|
||||
This code will connect to the _devnet_ cluster and show important data from a Mango Account.
|
||||
|
||||
Data on deposits, borrows and perp positions are all available in a `pandas` `DataFrame` for you to perform your own calculations upon. The `Account` class also has some methods to take this `DataFrame` and run common calculations on it, such as calculating the total value of the `Account` (using `total_value()`), the health of the account (using `init_health()` and `maint_health()`), or the account's leverage (using `leverage()`).
|
||||
```
|
||||
import mango
|
||||
|
||||
from solana.publickey import PublicKey
|
||||
|
||||
with mango.ContextBuilder.build(cluster_name="devnet") as context:
|
||||
group = mango.Group.load(context)
|
||||
cache: mango.Cache = mango.Cache.load(context, group.cache)
|
||||
|
||||
account = mango.Account.load(context, PublicKey("HhepjyhSzvVP7kivdgJH9bj32tZFncqKUwWidS1ja4xL"), group)
|
||||
open_orders = account.load_all_spot_open_orders(context)
|
||||
frame = account.to_dataframe(group, open_orders, cache)
|
||||
print(frame)
|
||||
print(f"Init Health: {account.init_health(frame)}")
|
||||
print(f"Maint Health: {account.maint_health(frame)}")
|
||||
print(f"Total Value: {account.total_value(frame)}")
|
||||
print(f"Leverage: {account.leverage(frame):,.2f}x")
|
||||
|
||||
print("Example complete.")
|
||||
```
|
||||
|
||||
### Subscribe to Account changes
|
||||
> [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/blockworks-foundation/mango-explorer-examples/HEAD?labpath=SubscribeAccount.ipynb) [Full example code](https://github.com/blockworks-foundation/mango-explorer-examples/blob/main/SubscribeAccount.ipynb)
|
||||
|
||||
This code will connect to the _devnet_ cluster and print out the Mango `Account` every time it changes. It will exit after 60 seconds.
|
||||
|
||||
The `subscribe()` method takes a lambda callback as a parameter - this lambda will be called with a new `Account` object when an update is received.
|
||||
|
||||
This code will exit after 60 seconds.
|
||||
|
||||
This pattern can also be used with `Group`, `Cache` and `EventQueue` objects.
|
||||
|
||||
**NOTE:** This will send an updated `Account` object, including whatever updated values triggered the update. However a proper valuation of an `Account` involves several more Mango data accounts so it's important to fetch all data fresh (including `Group`, `Cache` and all `OpenOrders`) to calculate values.
|
||||
```
|
||||
import datetime
|
||||
import mango
|
||||
import time
|
||||
|
||||
from solana.publickey import PublicKey
|
||||
|
||||
with mango.ContextBuilder.build(cluster_name="devnet") as context:
|
||||
# Load our devnet Random Taker Mango Account - it should have some activity
|
||||
group = mango.Group.load(context)
|
||||
account = mango.Account.load(context, PublicKey("5JDWiJGmnvs1DZomMV3s9Ev6DAgCQ9Svxd81EHCapjnD"), group)
|
||||
|
||||
manager = mango.IndividualWebSocketSubscriptionManager(context)
|
||||
subscription = account.subscribe(context, manager, lambda acc: print(datetime.datetime.now(), "\n", acc))
|
||||
manager.open()
|
||||
|
||||
time.sleep(60)
|
||||
|
||||
manager.dispose()
|
||||
|
||||
print("Example complete.")
|
||||
```
|
||||
|
||||
|
||||
### Deposit
|
||||
> [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/blockworks-foundation/mango-explorer-examples/HEAD?labpath=Deposit.ipynb) [Full example code](https://github.com/blockworks-foundation/mango-explorer-examples/blob/main/Deposit.ipynb)
|
||||
|
||||
This code will connect to the _devnet_ cluster and deposit 0.1 SOL into a Mango `Account`.
|
||||
```
|
||||
import decimal
|
||||
import mango
|
||||
|
||||
from solana.publickey import PublicKey
|
||||
|
||||
|
||||
# Use our hard-coded devnet wallet for DeekipCw5jz7UgQbtUbHQckTYGKXWaPQV4xY93DaiM6h.
|
||||
# For real-world use you'd load the bytes from the environment or a file. This wallet
|
||||
# has a Mango Account at HhepjyhSzvVP7kivdgJH9bj32tZFncqKUwWidS1ja4xL.
|
||||
wallet = mango.Wallet(bytes([67,218,68,118,140,171,228,222,8,29,48,61,255,114,49,226,239,89,151,110,29,136,149,118,97,189,163,8,23,88,246,35,187,241,107,226,47,155,40,162,3,222,98,203,176,230,34,49,45,8,253,77,136,241,34,4,80,227,234,174,103,11,124,146]))
|
||||
|
||||
with mango.ContextBuilder.build(cluster_name="devnet") as context:
|
||||
group = mango.Group.load(context)
|
||||
account = mango.Account.load(context, PublicKey("HhepjyhSzvVP7kivdgJH9bj32tZFncqKUwWidS1ja4xL"), group)
|
||||
sol_token = mango.token(context, "SOL")
|
||||
|
||||
print("Wrapped SOL in account", account.slot_by_instrument(sol_token).net_value)
|
||||
|
||||
deposit_value = mango.InstrumentValue(sol_token, decimal.Decimal("0.1"))
|
||||
deposit_signatures = account.deposit(context, wallet, deposit_value)
|
||||
print("Waiting for deposit transaction to confirm...", deposit_signatures)
|
||||
mango.WebSocketTransactionMonitor.wait_for_all(
|
||||
context.client.cluster_ws_url, deposit_signatures, commitment="processed"
|
||||
)
|
||||
|
||||
account = mango.Account.load(context, account.address, group)
|
||||
print("Wrapped SOL after deposit", account.slot_by_instrument(sol_token).net_value)
|
||||
|
||||
print("Example complete.")
|
||||
```
|
||||
|
||||
|
||||
### Withdraw
|
||||
> [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/blockworks-foundation/mango-explorer-examples/HEAD?labpath=Withdraw.ipynb) [Full example code](https://github.com/blockworks-foundation/mango-explorer-examples/blob/main/Withdraw.ipynb)
|
||||
|
||||
This code will connect to the _devnet_ cluster and withdraw 0.1 SOL from a Mango `Account`.
|
||||
|
||||
Unlike `deposit()`, you specify an address as the destination. You can withdraw from your Mango `Account` to anyone's wallet (be careful!). Also, you can withdraw tokens even if you don't own them (as long as you have sufficient collateral) by borrowing them - `withdraw()`'s `allow_borrow` boolean allows or prohibits borrowing tokens the `Account` doesn't own.
|
||||
```
|
||||
import decimal
|
||||
import mango
|
||||
|
||||
from solana.publickey import PublicKey
|
||||
|
||||
|
||||
# Use our hard-coded devnet wallet for DeekipCw5jz7UgQbtUbHQckTYGKXWaPQV4xY93DaiM6h.
|
||||
# For real-world use you'd load the bytes from the environment or a file. This wallet
|
||||
# has a Mango Account at HhepjyhSzvVP7kivdgJH9bj32tZFncqKUwWidS1ja4xL.
|
||||
wallet = mango.Wallet(bytes([67,218,68,118,140,171,228,222,8,29,48,61,255,114,49,226,239,89,151,110,29,136,149,118,97,189,163,8,23,88,246,35,187,241,107,226,47,155,40,162,3,222,98,203,176,230,34,49,45,8,253,77,136,241,34,4,80,227,234,174,103,11,124,146]))
|
||||
|
||||
with mango.ContextBuilder.build(cluster_name="devnet") as context:
|
||||
group = mango.Group.load(context)
|
||||
account = mango.Account.load(context, PublicKey("HhepjyhSzvVP7kivdgJH9bj32tZFncqKUwWidS1ja4xL"), group)
|
||||
sol_token = mango.token(context, "SOL")
|
||||
|
||||
print("Wrapped SOL in account", account.slot_by_instrument(sol_token).net_value)
|
||||
|
||||
withdraw_value = mango.InstrumentValue(sol_token, decimal.Decimal("0.1"))
|
||||
withdrawal_signatures = account.withdraw(context, wallet, wallet.address, withdraw_value, False)
|
||||
print("Waiting for withdraw transaction to confirm...", withdrawal_signatures)
|
||||
mango.WebSocketTransactionMonitor.wait_for_all(
|
||||
context.client.cluster_ws_url, withdrawal_signatures, commitment="processed"
|
||||
)
|
||||
|
||||
account = mango.Account.load(context, account.address, group)
|
||||
print("Wrapped SOL after withdrawal", account.slot_by_instrument(sol_token).net_value)
|
||||
|
||||
print("Example complete.")
|
||||
```
|
||||
|
||||
|
||||
## Running the marketmaker
|
||||
|
|
Loading…
Reference in New Issue