from compass_api_sdk import CompassAPI, models
with CompassAPI(
api_key_auth="<YOUR_API_KEY_HERE>",
) as compass_api:
res = compass_api.risk_yield.risk_yield_rebalance(owner="0x06A9aF046187895AcFc7258450B15397CAc67400", position_id=1076416, chain=models.RiskYieldRebalanceRequestChain.ROBINHOOD, gas_sponsorship=False, preview=False, slippage_pct="0.5", deadline_seconds=300, strategy=models.RebalanceStrategy.VOL_SCALED, horizon_days=7, burn_old=True)
# Handle response
print(res)import { CompassApiSDK } from "@compass-labs/api-sdk";
const compassApiSDK = new CompassApiSDK({
apiKeyAuth: "<YOUR_API_KEY_HERE>",
});
async function run() {
const result = await compassApiSDK.riskYield.riskYieldRebalance({
owner: "0x06A9aF046187895AcFc7258450B15397CAc67400",
chain: "robinhood",
positionId: 1076416,
strategy: "vol_scaled",
horizonDays: 7,
});
console.log(result);
}
run();curl --request POST \
--url https://api.compasslabs.ai/v2/risk_yield/rebalance \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"owner": "0x06A9aF046187895AcFc7258450B15397CAc67400",
"chain": "robinhood",
"position_id": 1076416,
"strategy": "vol_scaled",
"horizon_days": 7
}
'const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
owner: '0x06A9aF046187895AcFc7258450B15397CAc67400',
chain: 'robinhood',
position_id: 1076416,
strategy: 'vol_scaled',
horizon_days: 7
})
};
fetch('https://api.compasslabs.ai/v2/risk_yield/rebalance', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.compasslabs.ai/v2/risk_yield/rebalance",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'owner' => '0x06A9aF046187895AcFc7258450B15397CAc67400',
'chain' => 'robinhood',
'position_id' => 1076416,
'strategy' => 'vol_scaled',
'horizon_days' => 7
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.compasslabs.ai/v2/risk_yield/rebalance"
payload := strings.NewReader("{\n \"owner\": \"0x06A9aF046187895AcFc7258450B15397CAc67400\",\n \"chain\": \"robinhood\",\n \"position_id\": 1076416,\n \"strategy\": \"vol_scaled\",\n \"horizon_days\": 7\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.compasslabs.ai/v2/risk_yield/rebalance")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"owner\": \"0x06A9aF046187895AcFc7258450B15397CAc67400\",\n \"chain\": \"robinhood\",\n \"position_id\": 1076416,\n \"strategy\": \"vol_scaled\",\n \"horizon_days\": 7\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.compasslabs.ai/v2/risk_yield/rebalance")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"owner\": \"0x06A9aF046187895AcFc7258450B15397CAc67400\",\n \"chain\": \"robinhood\",\n \"position_id\": 1076416,\n \"strategy\": \"vol_scaled\",\n \"horizon_days\": 7\n}"
response = http.request(request)
puts response.read_body{
"action": "<string>",
"reason": "<string>",
"transaction": {
"chainId": "0x2105",
"data": "0x1688f0b900000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c762000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000675f4a3d",
"from": "0x4A83b4413CF41C3244027e1590E35a0F48403F0c",
"gas": "0x7a120",
"maxFeePerGas": "0x59682f00",
"maxPriorityFeePerGas": "0x3b9aca00",
"nonce": "0x5",
"to": "0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67",
"value": "0x0"
},
"old_position_id": 123,
"old_range": {
"tick_lower": 123,
"tick_upper": 123,
"price_lower": "<string>",
"price_upper": "<string>",
"width_lower_pct": "<string>",
"width_upper_pct": "<string>",
"is_full_range": true
},
"new_range": {
"tick_lower": 123,
"tick_upper": 123,
"price_lower": "<string>",
"price_upper": "<string>",
"width_lower_pct": "<string>",
"width_upper_pct": "<string>",
"is_full_range": true
},
"liquidity_removed": "<string>",
"amount0_floor": "<string>",
"amount1_floor": "<string>",
"expected_liquidity_floor": "<string>",
"estimated_dust0": "<string>",
"estimated_dust1": "<string>",
"phases": [
{
"name": "<string>",
"description": "<string>",
"steps": [
{
"kind": "APPROVE",
"description": "<string>",
"contract": "<string>",
"token": "<string>",
"amount": "<string>"
}
]
}
],
"simulation": {
"ok": true,
"error": "<string>",
"gas_used": 123
},
"warnings": [
"<string>"
]
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Rebalance a position
Move a position to a new range, in one transaction.
NOOP is a real answer and often the right one. Rebalancing realizes
the impermanent loss the position has taken so far, pays gas twice and a
swap, and puts the position back at risk from a new price. If the position
is already centred at the requested width, that is what you will get.
When there is something to do, the transaction unwinds the old position,
sweeps it together with the fees, opens the new range and burns the empty
NFT. Every leg is sized from the floor the previous one guarantees
rather than from its quote — they execute in the same transaction, and a
mint sized from a quote reverts when the decrease comes back a wei short,
leaving the owner having paid gas to dismantle a position. estimated_dust
is what that safety costs.
The default vol_scaled strategy sizes the new range from the pair’s own
measured volatility: two standard deviations over the horizon. A range
narrower than the asset’s ordinary movement spends most of its life out of
range earning nothing, which is the most common way to lose money doing
this on purpose.
from compass_api_sdk import CompassAPI, models
with CompassAPI(
api_key_auth="<YOUR_API_KEY_HERE>",
) as compass_api:
res = compass_api.risk_yield.risk_yield_rebalance(owner="0x06A9aF046187895AcFc7258450B15397CAc67400", position_id=1076416, chain=models.RiskYieldRebalanceRequestChain.ROBINHOOD, gas_sponsorship=False, preview=False, slippage_pct="0.5", deadline_seconds=300, strategy=models.RebalanceStrategy.VOL_SCALED, horizon_days=7, burn_old=True)
# Handle response
print(res)import { CompassApiSDK } from "@compass-labs/api-sdk";
const compassApiSDK = new CompassApiSDK({
apiKeyAuth: "<YOUR_API_KEY_HERE>",
});
async function run() {
const result = await compassApiSDK.riskYield.riskYieldRebalance({
owner: "0x06A9aF046187895AcFc7258450B15397CAc67400",
chain: "robinhood",
positionId: 1076416,
strategy: "vol_scaled",
horizonDays: 7,
});
console.log(result);
}
run();curl --request POST \
--url https://api.compasslabs.ai/v2/risk_yield/rebalance \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"owner": "0x06A9aF046187895AcFc7258450B15397CAc67400",
"chain": "robinhood",
"position_id": 1076416,
"strategy": "vol_scaled",
"horizon_days": 7
}
'const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
owner: '0x06A9aF046187895AcFc7258450B15397CAc67400',
chain: 'robinhood',
position_id: 1076416,
strategy: 'vol_scaled',
horizon_days: 7
})
};
fetch('https://api.compasslabs.ai/v2/risk_yield/rebalance', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.compasslabs.ai/v2/risk_yield/rebalance",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'owner' => '0x06A9aF046187895AcFc7258450B15397CAc67400',
'chain' => 'robinhood',
'position_id' => 1076416,
'strategy' => 'vol_scaled',
'horizon_days' => 7
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.compasslabs.ai/v2/risk_yield/rebalance"
payload := strings.NewReader("{\n \"owner\": \"0x06A9aF046187895AcFc7258450B15397CAc67400\",\n \"chain\": \"robinhood\",\n \"position_id\": 1076416,\n \"strategy\": \"vol_scaled\",\n \"horizon_days\": 7\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.compasslabs.ai/v2/risk_yield/rebalance")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"owner\": \"0x06A9aF046187895AcFc7258450B15397CAc67400\",\n \"chain\": \"robinhood\",\n \"position_id\": 1076416,\n \"strategy\": \"vol_scaled\",\n \"horizon_days\": 7\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.compasslabs.ai/v2/risk_yield/rebalance")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"owner\": \"0x06A9aF046187895AcFc7258450B15397CAc67400\",\n \"chain\": \"robinhood\",\n \"position_id\": 1076416,\n \"strategy\": \"vol_scaled\",\n \"horizon_days\": 7\n}"
response = http.request(request)
puts response.read_body{
"action": "<string>",
"reason": "<string>",
"transaction": {
"chainId": "0x2105",
"data": "0x1688f0b900000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c762000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000675f4a3d",
"from": "0x4A83b4413CF41C3244027e1590E35a0F48403F0c",
"gas": "0x7a120",
"maxFeePerGas": "0x59682f00",
"maxPriorityFeePerGas": "0x3b9aca00",
"nonce": "0x5",
"to": "0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67",
"value": "0x0"
},
"old_position_id": 123,
"old_range": {
"tick_lower": 123,
"tick_upper": 123,
"price_lower": "<string>",
"price_upper": "<string>",
"width_lower_pct": "<string>",
"width_upper_pct": "<string>",
"is_full_range": true
},
"new_range": {
"tick_lower": 123,
"tick_upper": 123,
"price_lower": "<string>",
"price_upper": "<string>",
"width_lower_pct": "<string>",
"width_upper_pct": "<string>",
"is_full_range": true
},
"liquidity_removed": "<string>",
"amount0_floor": "<string>",
"amount1_floor": "<string>",
"expected_liquidity_floor": "<string>",
"estimated_dust0": "<string>",
"estimated_dust1": "<string>",
"phases": [
{
"name": "<string>",
"description": "<string>",
"steps": [
{
"kind": "APPROVE",
"description": "<string>",
"contract": "<string>",
"token": "<string>",
"amount": "<string>"
}
]
}
],
"simulation": {
"ok": true,
"error": "<string>",
"gas_used": 123
},
"warnings": [
"<string>"
]
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Body
Move a position to a new range.
Rebalancing is not free: it realizes the impermanent loss taken so far, pays
gas twice and a swap, and puts the position back at risk from a new price.
The API will answer NOOP when it thinks the move is not worth making.
The wallet that owns the Risk Yield Account.
"0x06A9aF046187895AcFc7258450B15397CAc67400"
1076416
Risk Yield is available on Robinhood Chain only.
robinhood "robinhood"
Return EIP-712 typed data for the owner to sign instead of a transaction, so a sponsor can broadcast it.
Return the plan and its simulation without building a transaction. Nothing is signed and nothing can be broadcast.
How far the executed amounts may fall short of the quote before the transaction reverts. Memecoin pools move between the quote and the block that includes the transaction.
0 < x <= 10How long the transaction stays valid once built.
30 <= x <= 3600Which Uniswap deployment a pool belongs to.
v3 pools hold their own tokens and pay LPs the fee tier. v4 pools live in a shared PoolManager and may route the fee through a hook, which is where the launchpad pools' zero LP yield comes from.
V3, V4 How to choose the new range.
recenter_symmetric_pct, vol_scaled, manual "vol_scaled"
Required for recenter_symmetric_pct.
0 < x <= 1000For vol_scaled: how long the range should survive an ordinary move. A range narrower than the asset's usual movement spends most of its life out of range earning nothing.
1 <= x <= 3657
For manual.
For manual.
Destroy the emptied NFT once it is unwound.
Response
Successful Response
NOOP, COLLECT_ONLY or RECENTER. NOOP is a real answer and often the right one — moving a position realizes its loss and pays for a swap.
Show child attributes
Show child attributes
{
"chainId": "0x2105",
"data": "0x1688f0b900000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c762000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000675f4a3d",
"from": "0x4A83b4413CF41C3244027e1590E35a0F48403F0c",
"gas": "0x7a120",
"maxFeePerGas": "0x59682f00",
"maxPriorityFeePerGas": "0x3b9aca00",
"nonce": "0x5",
"to": "0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67",
"value": "0x0"
}
A range after the API has snapped it to the pool's tick spacing.
Returned because the range you asked for is rarely the range you get: ticks are discrete, and a 30% band becomes whichever usable ticks bracket it.
Show child attributes
Show child attributes
A range after the API has snapped it to the pool's tick spacing.
Returned because the range you asked for is rarely the range you get: ticks are discrete, and a 30% band becomes whichever usable ticks bracket it.
Show child attributes
Show child attributes
What the unwind is guaranteed to return. The new position is sized from this rather than from the quote, because every leg executes in the same transaction and a mint sized from a quote reverts when the decrease comes back a wei short.
Show child attributes
Show child attributes
The result of executing the transaction against current state.
Meme tokens on this chain carry transfer taxes, blacklists and pause switches, none of which are visible from a pool's parameters. Simulating is the only way to find out before the owner signs.
Show child attributes
Show child attributes
Was this page helpful?