Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
- the API key config is saved in a local file `./api_key_config.json`

## Start trading on testnet
- `create_modify_cancel_order.py`
- `create_modify_cancel_order_http.py`
- creates an ask (sell) order for 0.1 ETH @ $4050
- modified the order and increases the size to 0.11 ETH and increases the price to $4100
- cancels the order
- Note: all of these operations use the client order index of the order. You can use the order from the exchange as well

- `ws_send_tx.py`
- same flow as `create_modify_cancel_order.py`
- `create_modify_cancel_order_ws.py`
- same flow as `create_modify_cancel_order_http.py`
- sends TXs over WS instead of HTTP

- `create_grouped_ioc_with_attached_sl_tp.py`
Expand All @@ -25,7 +25,7 @@
- the size of the SL/TP will be equal to the executed size of the order
- the SL/TP orders are canceled when the sign of your position changes

- `create_position_tied_sl_tl.py`
- `create_position_tied_sl_tp.py`
- creates a bid (buy) Stop Loss (SL) and a Take Profit (TP) to close your short position
- the size of the orders will be for your whole position (because BaseAmount=0)
- the orders will grow / shrink as you accumulate more position
Expand All @@ -43,6 +43,24 @@ What about the order types? Just as normal orders, SL/TP orders trigger an order
- market order
- limit IOC / GTC

### Modify leverage / Margin Mode (Cross, Isolated) / Add Collateral to isolated-only positions
- `margin_eth_20x_cross_http`
- sets ETH market to 20x leverage and cross-margin mode, using HTTP
- `margin_eth_50x_isolate_ws`
- sets ETH market to 50x leverage and isolated margin mode, using HTTP
- `margin_eth_add_collateral_http.py`
- adds $10.5 USDC to the ETH position (must be opened and in isolated mode)
- `margin_eth_remove_collateral_ws.py`
- removes $5 USDC from the ETH position (must be opened and in isolated mode)

### Batch orders
- `send_batch_tx_http.py`
- sends multiple orders in a single HTTP request
- `send_batch_tx_ws.py`
- sends multiple orders in a single WS request`

Batch TXs will be executed back to back, without the possibility of other TXs interfering.

## Setup steps for mainnet
- deposit money on Lighter to create an account first
- change the URL to `mainnet.zklighter.elliot.ai`
Expand Down
34 changes: 21 additions & 13 deletions examples/create_grouped_ioc_with_attached_sl_tp.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
import asyncio
import lighter
from lighter.signer_client import CreateOrderTxReq
from utils import default_example_setup


async def main():
client, api_client, _ = default_example_setup()

# Sell some ETH at $2500
# The size of the SL/TP orders will be equal to the size of the executed order

# set SL trigger price at 5000 and limit price at 5050
# set TP trigger price at 1500 and limit price at 1550
# Note: set the limit price to be higher than the SL/TP trigger price to ensure the order will be filled
# If the mark price of ETH reaches 1500, there might be no one willing to sell you ETH at 1500, so trying to buy at 1550 would increase the fill rate

ioc_order = CreateOrderTxReq(
MarketIndex=0,
ClientOrderIndex=0,
BaseAmount=1000, # 0.1 ETH
Price=300000, # $3000
Price=2500_00, # $2500
IsAsk=1, # sell
Type=lighter.SignerClient.ORDER_TYPE_LIMIT,
TimeInForce=lighter.SignerClient.ORDER_TIME_IN_FORCE_IMMEDIATE_OR_CANCEL,
Type=client.ORDER_TYPE_LIMIT,
TimeInForce=client.ORDER_TIME_IN_FORCE_IMMEDIATE_OR_CANCEL,
ReduceOnly=0,
TriggerPrice=0,
OrderExpiry=0,
Expand All @@ -25,30 +32,30 @@ async def main():
MarketIndex=0,
ClientOrderIndex=0,
BaseAmount=0,
Price=300000,
Price=1550_00,
IsAsk=0,
Type=lighter.SignerClient.ORDER_TYPE_TAKE_PROFIT_LIMIT,
TimeInForce=lighter.SignerClient.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
Type=client.ORDER_TYPE_TAKE_PROFIT_LIMIT,
TimeInForce=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
ReduceOnly=1,
TriggerPrice=300000,
TriggerPrice=1500_00,
OrderExpiry=-1,
)

stop_loss_order = CreateOrderTxReq(
MarketIndex=0,
ClientOrderIndex=0,
BaseAmount=0,
Price=500000,
Price=5050_00,
IsAsk=0,
Type=lighter.SignerClient.ORDER_TYPE_STOP_LOSS_LIMIT,
TimeInForce=lighter.SignerClient.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
Type=client.ORDER_TYPE_STOP_LOSS_LIMIT,
TimeInForce=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
ReduceOnly=1,
TriggerPrice=500000,
TriggerPrice=5000_00,
OrderExpiry=-1,
)

transaction = await client.create_grouped_orders(
grouping_type=lighter.SignerClient.GROUPING_TYPE_ONE_TRIGGERS_A_ONE_CANCELS_THE_OTHER,
grouping_type=client.GROUPING_TYPE_ONE_TRIGGERS_A_ONE_CANCELS_THE_OTHER,
orders=[ioc_order, take_profit_order, stop_loss_order],
)

Expand All @@ -57,5 +64,6 @@ async def main():
await client.close()
await api_client.close()


if __name__ == "__main__":
asyncio.run(main())
Original file line number Diff line number Diff line change
@@ -1,43 +1,54 @@
import asyncio
import lighter
from utils import default_example_setup


async def main():
client, api_client, _ = default_example_setup()
client.check_client()

# create order
api_key_index, nonce = client.nonce_manager.next_nonce()
tx, tx_hash, err = await client.create_order(
market_index=0,
client_order_index=123,
base_amount=1000, # 0.1 ETH
price=405000, # $4050
price=4050_00, # $4050
is_ask=True,
order_type=lighter.SignerClient.ORDER_TYPE_LIMIT,
time_in_force=lighter.SignerClient.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
order_type=client.ORDER_TYPE_LIMIT,
time_in_force=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
reduce_only=False,
trigger_price=0,
nonce=nonce,
api_key_index=api_key_index,
)
print(f"Create Order {tx=} {tx_hash=} {err=}")
if err is not None:
raise Exception(err)

# create order
## modify order
# use the same API key so the TX goes after the create order TX
api_key_index, nonce = client.nonce_manager.next_nonce(api_key_index)
tx, tx_hash, err = await client.modify_order(
market_index=0,
order_index=123,
base_amount=1100, # 0.11 ETH
price=410000, # $4100
price=4100_00, # $4100
trigger_price=0,
nonce=nonce,
api_key_index=api_key_index,
)
print(f"Modify Order {tx=} {tx_hash=} {err=}")
if err is not None:
raise Exception(err)

# cancel order
## cancel order
# use the same API key so the TX goes after the modify order TX
api_key_index, nonce = client.nonce_manager.next_nonce(api_key_index)
tx, tx_hash, err = await client.cancel_order(
market_index=0,
order_index=123,
nonce=nonce,
api_key_index=api_key_index,
)
print(f"Cancel Order {tx=} {tx_hash=} {err=}")
if err is not None:
Expand Down
68 changes: 68 additions & 0 deletions examples/create_modify_cancel_order_ws.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import websockets
import asyncio
from utils import default_example_setup, ws_send_tx


# this example does the same thing as the create_modify_cancel_order.py example, but sends the TX over WS instead of HTTP
async def main():
client, api_client, ws_client_promise = default_example_setup()

# set up WS client and print a connected message
ws_client: websockets.ClientConnection = await ws_client_promise
print("Received:", await ws_client.recv())

# create order
api_key_index, nonce = client.nonce_manager.next_nonce()
tx_type, tx_info, tx_hash, err = client.sign_create_order(
market_index=0,
client_order_index=123,
base_amount=1000, # 0.1 ETH
price=4050_00, # $4050
is_ask=True,
order_type=client.ORDER_TYPE_LIMIT,
time_in_force=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
reduce_only=False,
trigger_price=0,
nonce=nonce,
api_key_index=api_key_index,
)
if err is not None:
raise Exception(err)
await ws_send_tx(ws_client, tx_type, tx_info, tx_hash)

## modify order
# use the same API key so the TX goes after the create order TX
api_key_index, nonce = client.nonce_manager.next_nonce(api_key_index)
tx_type, tx_info, tx_hash, err = client.sign_modify_order(
market_index=0,
order_index=123,
base_amount=1100, # 0.11 ETH
price=4100_00, # $4100
trigger_price=0,
nonce=nonce,
api_key_index=api_key_index,
)
if err is not None:
raise Exception(err)
await ws_send_tx(ws_client, tx_type, tx_info, tx_hash)

## cancel order
# use the same API key so the TX goes after the modify order TX
api_key_index, nonce = client.nonce_manager.next_nonce(api_key_index)
tx_type, tx_info, tx_hash, err = client.sign_cancel_order(
market_index=0,
order_index=123,
nonce=nonce,
api_key_index=api_key_index,
)
if err is not None:
raise Exception(err)
await ws_send_tx(ws_client, tx_type, tx_info, tx_hash)

await client.close()
await api_client.close()
await ws_client.close()


if __name__ == "__main__":
asyncio.run(main())
48 changes: 0 additions & 48 deletions examples/create_position_tied_sl_tl.py

This file was deleted.

56 changes: 56 additions & 0 deletions examples/create_position_tied_sl_tp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import asyncio
from lighter.signer_client import CreateOrderTxReq
from utils import default_example_setup


async def main():
client, api_client, _ = default_example_setup()

# Creates a position tied SL/TP pair
# The SL/TP orders will close your whole position, even if you add/remove from it later on
# if the positions reach 0 or switches from short -> long, the orders are canceled

# this particular example, sets the SL/TP for a short position
# set SL trigger price at 5000 and limit price at 5050
# set TP trigger price at 1500 and limit price at 1550
# Note: set the limit price to be higher than the SL/TP trigger price to ensure the order will be filled
# If the mark price of ETH reaches 1500, there might be no one willing to sell you ETH at 1500, so trying to buy at 1550 would increase the fill rate

# Create a One-Cancels-the-Other grouped order with a take-profit and a stop-loss order
take_profit_order = CreateOrderTxReq(
MarketIndex=0,
ClientOrderIndex=0,
BaseAmount=0,
Price=1550_00,
IsAsk=0,
Type=client.ORDER_TYPE_TAKE_PROFIT_LIMIT,
TimeInForce=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
ReduceOnly=1,
TriggerPrice=1500_00,
OrderExpiry=-1,
)

stop_loss_order = CreateOrderTxReq(
MarketIndex=0,
ClientOrderIndex=0,
BaseAmount=0,
Price=4050_00,
IsAsk=0,
Type=client.ORDER_TYPE_STOP_LOSS_LIMIT,
TimeInForce=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
ReduceOnly=1,
TriggerPrice=4000_00,
OrderExpiry=-1,
)

transaction = await client.create_grouped_orders(
grouping_type=client.GROUPING_TYPE_ONE_CANCELS_THE_OTHER,
orders=[take_profit_order, stop_loss_order],
)

print("Create Grouped Order Tx:", transaction)
await client.close()
await api_client.close()

if __name__ == "__main__":
asyncio.run(main())
Loading