Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new endpoints #23

Merged
merged 2 commits into from
Oct 8, 2022
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
38 changes: 38 additions & 0 deletions docs/endpoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ client.get_price_quote(pair="BTC/ETH", amount="1.0", side="buy")
client.place_order(pair="BTC/ETH", quantity="1.0", side="buy")
```

* **POST** /api/v1/orders/cancel (Cancels an order.) ✔️

```python3
def cancel_order(self, "8037298b-3ba4-41f9-8718-8a7bf87560f6")
```

* **POST** /api/v1/orders/cancel/all (Cancels all orders for a pair) ✔️

```python3
def cancel_all_orders(self, "ETH/USDT")
```

* **POST** /api/v1/orders/trigger (Places a trigger order.) ✔️

```python3
Expand Down Expand Up @@ -79,3 +91,29 @@ client.get_trade_history(pairs=["BTC/ETH", "BTC/USDT"], start_date="123242424242
```python3
client.get_price_quote(transaction_id="22442")
```

### Futures

* **GET** /api/v1/futures/instruments (Retrieves futures instruments) ✔️

```python3
client.get_all_future_instruments()
```

* **GET** /api/v1/futures/positions (Retrieves futures positions) ✔️

```python3
client.get_future_positions(status="any")
```

* **POST** /api/v1/futures/order (Places a futures order) ✔️

```python3
client.place_future_order()
```

* **POST** /api/v1/future/close-all-positions (Closes all future positions) ❌

```python3
client.close_all_future_positions()
```
25 changes: 25 additions & 0 deletions examples/futures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import sys
from os import path
import time

sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))

import nexo
import os
from dotenv import load_dotenv

import time

load_dotenv()

key = os.getenv("NEXO_PUBLIC_KEY")
secret = os.getenv("NEXO_SECRET_KEY")

client = nexo.Client(key, secret)
instruments = client.get_all_future_instruments()
print(instruments)

positions = client.get_future_positions(status="any")
print(positions)

print(client.close_all_future_positions())
2 changes: 1 addition & 1 deletion examples/get_quote.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@

# Buys 0.03 ETH with USDT at market price
quote = client.get_price_quote("ETH/USDT", "100.0", "buy")
print(quote)
print(quote)
15 changes: 12 additions & 3 deletions examples/place_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,22 @@
client = nexo.Client(key, secret)

# Buys 0.03 ETH with USDT at market price
order_resp = client.place_order("ETH/USDT", "buy", "market", "0.03", serialize_json_to_object=True)
order_resp = client.place_order(
"ETH/USDT", "buy", "market", "0.03", serialize_json_to_object=True
)
print(order_resp)

# Gets order details
order = client.get_order_details(str(order_resp.order_id))
print(order)

# Sells 0.03 ETH for USDT at limit price 2000 USDT
order_resp = client.place_order("ETH/USDT", "sell", "limit", "0.03", "1500", serialize_json_to_object=True)
print(order_resp)
order_resp = client.place_order(
"ETH/USDT", "sell", "limit", "0.03", "1500", serialize_json_to_object=True
)
print(order_resp)

cancel_order = client.cancel_all_orders("ETH/USDT")
print(cancel_order)

print(client.cancel_order("kerar"))
4 changes: 2 additions & 2 deletions nexo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.. moduleauthor:: Erwin Lejeune
"""

__version__ = '1.0.1'
__version__ = "1.0.1"

from nexo.client import Client
from nexo.response_serializers import (
Expand All @@ -20,5 +20,5 @@
NexoAPIException,
NotImplementedException,
NexoRequestException,
NEXO_API_ERROR_CODES
NEXO_API_ERROR_CODES,
)
86 changes: 78 additions & 8 deletions nexo/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def _generate_signature(
)
return base64.b64encode(m.digest())


class Client(BaseClient):
def __init__(self, api_key, api_secret):
super().__init__(api_key, api_secret)
Expand All @@ -81,7 +82,9 @@ def _handle_response(response: requests.Response):
json_response = response.json()
except Exception:
if not response.ok:
raise NexoRequestException(f"Failed to get API response: \nCode: {response.status_code}\nRequest: {str(response.request.body)}")
raise NexoRequestException(
f"Failed to get API response: \nCode: {response.status_code}\nRequest: {str(response.request.body)}"
)

try:
if "errorCode" in json_response:
Expand All @@ -93,13 +96,14 @@ def _handle_response(response: requests.Response):
)
else:
if not response.ok:
raise NexoRequestException(f"Failed to get API response: \nCode: {response.status_code}\nRequest: {str(response.request.body)}")

raise NexoRequestException(
f"Failed to get API response: \nCode: {response.status_code}\nRequest: {str(response.request.body)}"
)

return json_response

except ValueError:
raise NexoRequestException("Invalid Response: %s" % json_response)


def _request(
self, method, path: str, version=BaseClient.PUBLIC_API_VERSION, **kwargs
Expand Down Expand Up @@ -255,9 +259,7 @@ def get_transaction_info(
self, transaction_id: str, serialize_json_to_object: bool = False
) -> Dict:

data = {
"transactionId": transaction_id
}
data = {"transactionId": transaction_id}

transaction_json = self._get(f"transaction", data=data)

Expand Down Expand Up @@ -315,7 +317,11 @@ def place_trigger_order(
raise NexoRequestException(
f"Bad Request: Tried to place a trigger order with side = {side}, side must be 'buy' or 'sell'"
)
if trigger_type != "stopLoss" and trigger_type != "takeProfit" and trigger_type != "trailing":
if (
trigger_type != "stopLoss"
and trigger_type != "takeProfit"
and trigger_type != "trailing"
):
raise NexoRequestException(
f"Bad Request: Tried to place a trigger order with trigger type = {trigger_type}, trigger type must be 'stopLoss' or 'takeProfit' or 'trailing'"
)
Expand Down Expand Up @@ -415,3 +421,67 @@ def place_twap_order(
return AdvancedOrderResponse(twap_order_json)

return twap_order_json

def cancel_order(self, order_id: str):
data = {"orderId": order_id}

return self._post("orders/cancel", data=data)

def cancel_all_orders(self, pair: str):
if not check_pair_validity(pair):
raise NexoRequestException(
f"Bad Request: Tried to cancel all orders with pair = {pair}, must be of format [A-Z]{{2,6}}/[A-Z]{{2, 6}}"
)

data = {"pair": pair}

return self._post("orders/cancel/all", data=data)

def get_all_future_instruments(self):
return self._get("futures/instruments")

def get_future_positions(self, status: str):
if status != "any" and status != "active" and status != "inactive":
raise NexoRequestException(
f"Bad Request: Tried to get future positions with status = {status}, status must be 'any', 'active' or 'inactive'"
)

data = {"status": status}

return self._get("futures/positions", data=data)

def place_future_order(
self,
instrument: str,
position_action: str,
position_side: str,
type: str,
quantity: float,
):
if position_action != "open" and position_action != "close":
raise NexoRequestException(
f"Bad Request: Tried to place future position with position action = {position_action}, must be 'open' or 'close'"
)

if position_side != "long" and position_side != "short":
raise NexoRequestException(
f"Bad Request: Tried to place future position with position side = {position_side}, must be 'long' or 'short'"
)

if type != "market":
raise NexoRequestException(
f"Bad Request: Tried to place future position with type = {type}, must be 'market'"
)

data = {
"positionAction": position_action,
"instrument": instrument,
"positionSide": position_side,
"type": type,
"quantity": quantity,
}

return self._post("futures/order", data=data)

def close_all_future_positions(self):
return self._post("futures/close-all-positions")
Loading