Updatred README with a lot more sample code.

This commit is contained in:
Geoff Taylor 2022-03-08 16:26:37 +00:00
parent 09b10c6efb
commit 56159ac777
1 changed files with 308 additions and 40 deletions

348
README.md
View File

@ -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