Files
ritmex-bot/docs/grvt/grvt-pysdk-main/tests/pysdk/test_grvt_ccxt_pro.py
T

301 lines
10 KiB
Python

import asyncio
import os
import traceback
from datetime import datetime
from decimal import Decimal
from pysdk.grvt_ccxt_env import GrvtEnv
from pysdk.grvt_ccxt_logging_selector import logger
from pysdk.grvt_ccxt_pro import GrvtCcxtPro
from pysdk.grvt_ccxt_test_utils import validate_return_values
from pysdk.grvt_ccxt_types import DURATION_SECOND_IN_NSEC, GrvtOrderSide
from pysdk.grvt_ccxt_utils import rand_uint32
# Utility functions , not called directly by the __main__ test routine
async def get_open_orders(api: GrvtCcxtPro) -> list[dict]:
open_orders = await api.fetch_open_orders(
symbol="BTC_USDT_Perp",
params={"kind": "PERPETUAL"},
)
logger.info(f"open_orders: {open_orders=}")
return open_orders
async def fetch_order_history(api: GrvtCcxtPro) -> dict:
order_history: dict = await api.fetch_order_history(
params={"kind": "PERPETUAL", "limit": 3},
)
logger.info(f"order_history: {order_history=}")
return order_history
async def fetch_funding_history(api: GrvtCcxtPro) -> dict:
start_date: datetime = datetime.strptime("2025-05-01T00:00:00Z", "%Y-%m-%dT%H:%M:%SZ")
funding_history: dict = await api.fetch_funding_rate_history(
symbol="BTC_USDT_Perp",
since=int(start_date.timestamp() * DURATION_SECOND_IN_NSEC), # Convert to nanoseconds
limit=500,
)
results: list = funding_history.get("result", [])
if results:
logger.info(f"funding_history: START={results[0]}")
logger.info(f"funding_history: END={results[-1]}")
else:
logger.info(f"funding_history: No results found in {funding_history=}")
return funding_history
async def cancel_orders(api: GrvtCcxtPro, open_orders: list) -> int:
FN = "cancel_orders"
logger.info(f"{FN} START")
order_count: int = 0
for order_dict in open_orders:
client_order_id = order_dict["metadata"].get("client_order_id")
if client_order_id:
# Cancel
logger.info(f"{FN} cancel order by id:{order_dict['order_id']}")
await api.cancel_order(id=order_dict["order_id"])
order_count += 1
else:
logger.warning(f"{FN} client_order_id not found in {order_dict=}")
return order_count
async def show_derisk_mm_ratios(api: GrvtCcxtPro, keyword: str) -> None:
"""Show the current derisking market making ratios."""
FN = "show_derisk_mm_ratios"
acc_summary = await api.get_account_summary(type="sub-account")
maintenance_margin = acc_summary.get("maintenance_margin")
derisk_margin = acc_summary.get("derisk_margin")
derisk_ratio = acc_summary.get("derisk_to_maintenance_margin_ratio")
logger.info(f"{FN} {keyword} {maintenance_margin=}")
logger.info(f"{FN} {keyword} {derisk_margin=}")
logger.info(f"{FN} {keyword} {derisk_ratio=}")
logger.info(f"sub-account summary:\n{acc_summary}")
async def set_derisk_mm_ratio(api: GrvtCcxtPro, ratio: str = "1.5") -> None:
"""Set the derisking market making ratio."""
FN = f"set_derisk_mm_ratio {ratio=}"
logger.info(f"{FN} START")
await show_derisk_mm_ratios(api, "BEFORE")
await api.set_derisk_mm_ratio(ratio)
await show_derisk_mm_ratios(api, "AFTER")
async def cancel_all_orders(api: GrvtCcxtPro) -> bool:
FN = "cancel_all_orders"
logger.info(f"{FN} START")
cancel_response = await api.cancel_all_orders()
logger.info(f"{FN} {cancel_response=}")
return cancel_response
async def print_instruments(api: GrvtCcxtPro):
logger.info("print_instruments: START")
if not api.markets:
return
for market in list(api.markets.values())[:3]:
logger.info(f"{market=}")
instrument = market["instrument"]
logger.info(f"fetch_mini_ticker: {instrument=}, {await api.fetch_mini_ticker(instrument)}")
logger.info(f"fetch_ticker: {instrument=}, {await api.fetch_ticker(instrument)}")
logger.info(
f"fetch_order_book {instrument=}, {await api.fetch_order_book(instrument, limit=10)}"
)
logger.info(
f"fetch_recent_trades {instrument=}, "
f"{await api.fetch_recent_trades(instrument, limit=7)}"
)
logger.info(f"fetch_trades {instrument=}, {await api.fetch_trades(instrument, limit=5)}")
logger.info(
f"fetch_funding_rate_history {instrument=}, "
f"{await api.fetch_funding_rate_history(instrument, limit=5)}"
)
for type in ["TRADE", "MARK", "INDEX", "MID"]:
ohlc = await api.fetch_ohlcv(
instrument, timeframe="1m", limit=5, params={"candle_type": type}
)
logger.info(f"fetch_ohlcv {type} {instrument=}, {ohlc}")
async def send_order(api: GrvtCcxtPro, side: GrvtOrderSide, client_order_id: int) -> dict:
price = 64_000 if side == "buy" else 65_000
send_order_response = await api.create_order(
symbol="BTC_USDT_Perp",
order_type="limit",
side=side,
amount=0.01,
price=price,
params={"client_order_id": client_order_id},
)
logger.info(f"send order: {send_order_response=} {client_order_id=}")
return send_order_response
# Test scenarios, called by the __main__ test routine
async def send_fetch_order(api: GrvtCcxtPro):
client_order_id = rand_uint32()
_ = await send_order(api, side="buy", client_order_id=client_order_id)
order_status = await api.fetch_order(
id=None,
params={"client_order_id": client_order_id},
)
logger.info(f"result of fetch_order: {order_status=}")
async def send_mkt_order(
api: GrvtCcxtPro, symbol: str, side: GrvtOrderSide, amount: Decimal, client_order_id: int
) -> dict:
send_order_response = await api.create_order(
symbol=symbol,
order_type="market",
side=side,
amount=amount,
params={"client_order_id": client_order_id},
)
logger.info(f"send mkt order: {send_order_response=} {client_order_id=}")
return send_order_response
async def check_cancel_check_orders(api: GrvtCcxtPro):
logger.info("check_cancel_check_orders: START")
open_orders = await get_open_orders(api)
if open_orders:
await cancel_orders(api, open_orders)
await get_open_orders(api)
async def fetch_my_trades(api: GrvtCcxtPro):
logger.info("fetch_my_trades: START")
my_trades = await api.fetch_my_trades(
symbol="BTC_USDT_Perp",
limit=10,
params={},
)
logger.info(f"my_trades: num trades:{len(my_trades)}")
logger.info(f"my_trades: {my_trades=}")
async def cancel_send_order(api: GrvtCcxtPro):
FN = "cancel_send_order"
logger.info(f"{FN}: START")
client_order_id: int = rand_uint32()
logger.info(f"{FN} cancel order by {client_order_id=}")
result = await api.cancel_order(
params={"client_order_id": client_order_id, "time_to_live_ms": "1000"}
)
logger.info(f"{FN} cancel_order: {result=}")
order_response = await send_mkt_order(
api,
symbol="BTC_USDT_Perp",
side="sell",
amount=Decimal("0.01"),
client_order_id=client_order_id,
)
if order_response:
# Get status
logger.info(f"{FN} fetch_order by {client_order_id=}")
order_status = await api.fetch_order(params={"client_order_id": client_order_id})
logger.info(f"{FN} {order_status=}")
async def print_markets(api: GrvtCcxtPro):
logger.info("print_markets: START")
if api.markets:
logger.info(f"MARKETS:{len(api.markets)}")
for market in api.markets.values():
logger.info(f"MARKET:{market}")
async def fetch_all_markets(api: GrvtCcxtPro):
logger.info("fetch_all_markets: START")
instruments = await api.fetch_all_markets()
logger.info(f"fetch_all_markets: num instruments={len(instruments)}")
async def print_account_summary(api: GrvtCcxtPro):
try:
logger.info("print_account_summary: START")
logger.info(f"sub-account summary:\n{await api.get_account_summary(type='sub-account')}")
logger.info(f"funding-account summary:\n{await api.get_account_summary(type='funding')}")
logger.info(
f"aggregated-account summary:\n{await api.get_account_summary(type='aggregated')}"
)
logger.info(f"fetch_balance:\n{await api.fetch_balance()}")
except Exception as e:
logger.error(f"account summary failed: {e}")
async def print_account_history(api: GrvtCcxtPro):
try:
hist = await api.fetch_account_history(params={})
logger.info(f"account history:\n{hist}")
except Exception as e:
logger.error(f"account history failed: {e}")
async def print_positions(api: GrvtCcxtPro):
try:
logger.info(f"positions:\n{await api.fetch_positions(symbols=['BTC_USDT_Perp'])}")
except Exception as e:
logger.error(f"positions failed: {e}")
async def print_description(api: GrvtCcxtPro):
try:
logger.info(f"print_description: {api.describe()}")
except Exception as e:
logger.error(f"print_description failed: {e}")
async def grvt_ccxt_pro():
params = {
"api_key": os.getenv("GRVT_API_KEY"),
"trading_account_id": os.getenv("GRVT_TRADING_ACCOUNT_ID"),
"private_key": os.getenv("GRVT_PRIVATE_KEY"),
}
env = GrvtEnv(os.getenv("GRVT_ENV", "testnet"))
test_api = GrvtCcxtPro(env, logger, parameters=params, order_book_ccxt_format=True)
await test_api.load_markets()
await asyncio.sleep(2)
function_list = [
print_description,
# -------- MARKET related
fetch_all_markets,
print_markets,
print_instruments,
print_account_summary,
print_account_history,
print_positions,
# Order / Trade history
fetch_my_trades,
fetch_order_history,
fetch_funding_history,
# Trade related
send_fetch_order,
check_cancel_check_orders,
fetch_my_trades,
fetch_order_history,
print_positions,
cancel_send_order,
get_open_orders,
send_fetch_order,
get_open_orders,
cancel_all_orders,
get_open_orders,
set_derisk_mm_ratio,
]
for f in function_list:
try:
await f(test_api)
except Exception as e:
logger.error(f"Error in {f.__name__}: {e} {traceback.format_exc()}")
validate_return_values(test_api, "test_results.csv")
def test_grvt_ccxt_pro() -> None:
asyncio.run(grvt_ccxt_pro())
if __name__ == "__main__":
test_grvt_ccxt_pro()