-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from quant-vn/base
Base
- Loading branch information
Showing
23 changed files
with
771 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
name: Publish vBroker using Poetry | ||
|
||
on: | ||
release: | ||
types: [created] | ||
|
||
jobs: | ||
deploy: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Set up Python | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: '3.x' | ||
- name: Install Poetry | ||
uses: snok/install-poetry@v1 | ||
with: | ||
version: 1.5.1 | ||
virtualenvs-create: true | ||
virtualenvs-in-project: true | ||
- name: Install dependencies | ||
run: poetry install | ||
- name: Build package | ||
run: poetry build | ||
- name: Publish to PyPI | ||
env: | ||
PYPI_USERNAME: __token__ | ||
PYPI_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} | ||
run: | | ||
poetry config pypi-token.pypi $PYPI_PASSWORD | ||
poetry publish |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,14 @@ | ||
# vbroker | ||
vBroker | ||
# vBroker | ||
vBroker: A Python wrapper for Viet Nam Broker API | ||
|
||
![PyPI - Version](https://img.shields.io/pypi/v/vbroker) | ||
![Python Version](https://img.shields.io/pypi/pyversions/vbroker) | ||
![PyPI - Downloads](https://img.shields.io/pypi/dm/vbroker) | ||
![License: MIT](https://img.shields.io/badge/License-MIT-green.svg) | ||
|
||
## Installation | ||
```bash | ||
pip install vbroker | ||
``` | ||
|
||
## Usage |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
[tool.poetry] | ||
name = "vbroker" | ||
version = "0.1.0" | ||
license = "MIT" | ||
description = "vBroker: A Python wrapper for Viet Nam Broker API" | ||
repository = "https://github.com/quant-vn/vbroker" | ||
homepage = "https://quant.vn" | ||
authors = ["thync <thync@outlook.com>"] | ||
readme = ["README.md", "LICENSE"] | ||
classifiers = [ | ||
"Typing :: Typed", | ||
"Intended Audience :: Developers", | ||
"Programming Language :: Python :: 3.9", | ||
"Programming Language :: Python :: 3.10", | ||
"Programming Language :: Python :: 3.11", | ||
"Programming Language :: Python :: 3.12", | ||
"Operating System :: OS Independent", | ||
"Operating System :: POSIX", | ||
"Operating System :: MacOS", | ||
"Operating System :: POSIX :: Linux", | ||
"Operating System :: Microsoft :: Windows", | ||
"Topic :: Software Development :: Libraries :: Python Modules" | ||
] | ||
|
||
[tool.poetry.dependencies] | ||
python = "^3.9" | ||
requests = "^2.32.3" | ||
websockets = "^13.0.1" | ||
pydantic = "^2.9.1" | ||
pyjwt = "^2.9.0" | ||
|
||
|
||
[build-system] | ||
requires = ["poetry-core"] | ||
build-backend = "poetry.core.masonry.api" |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
from vbroker import Broker, Config, EnumBroker | ||
|
||
broker = Broker( | ||
broker=EnumBroker.SSI.value, | ||
config=Config( | ||
ssi_broker_id="", | ||
ssi_broker_secret="", | ||
ssi_broker_private_key="" | ||
) | ||
) | ||
|
||
print(broker.api.get_token()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
""" Broker module. """ | ||
from .enum_broker import EnumBroker # noqa: F401 | ||
from .broker import Broker # noqa: F401 | ||
from .config import Config # noqa: F401 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
""" Broker module for broker API and HUB. """ | ||
from .config import Config | ||
|
||
from .enum_broker import EnumBroker | ||
from .interface_broker_api import IBrokerAPI | ||
from .interface_broker_hub import IBrokerHUB | ||
|
||
from .ssi import SSIBrokerAPI, SSIBrokerHUB | ||
|
||
|
||
class Broker: | ||
def __init__(self, broker: EnumBroker, config: Config) -> None: | ||
if broker == EnumBroker.SSI.value: | ||
self.__api: IBrokerAPI = SSIBrokerAPI(config) | ||
self.__hub: IBrokerHUB = SSIBrokerHUB(self.__api) | ||
|
||
@property | ||
def api(self) -> IBrokerAPI: | ||
return self.__api | ||
|
||
@property | ||
def hub(self) -> IBrokerHUB: | ||
return self.__hub |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
""" Configuration module for the broker. """ | ||
from typing import Optional | ||
|
||
from .utils import BaseModel | ||
|
||
|
||
class Config(BaseModel): | ||
""" | ||
Configuration class for the broker. | ||
Attributes: | ||
ssi_broker_id (Optional[str]): The SSI broker ID. | ||
ssi_broker_secret (Optional[str]): The SSI broker secret. | ||
ssi_broker_private_key (Optional[str]): The SSI broker private key. | ||
""" | ||
# SSI datafeed information | ||
ssi_broker_id: Optional[str] = None | ||
ssi_broker_secret: Optional[str] = None | ||
ssi_broker_private_key: Optional[str] = None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
""" | ||
This module contains the EnumDatafeed class which is used for handling datafeed enumerations. | ||
""" | ||
from .utils import EnumHandler | ||
|
||
|
||
class EnumBroker(EnumHandler): | ||
""" | ||
This module contains the EnumDatafeed class which is used for handling datafeed enumerations. | ||
Attributes: | ||
SSI (str): Represents the SSI datafeed. | ||
""" | ||
SSI = 'ssi' | ||
SSI_PAPER = 'ssi_paper' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
""" Interface for Broker API """ | ||
from abc import ABC, abstractmethod | ||
from .config import Config | ||
|
||
|
||
class IBrokerAPI(ABC): | ||
def __init__(self, config: Config): | ||
self.config: Config = config | ||
|
||
@abstractmethod | ||
def get_token(self) -> str: | ||
return NotImplemented |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
""" This module defines the interface for a broker HUB. """ | ||
from abc import ABC, abstractmethod | ||
|
||
|
||
class IBrokerHUB(ABC): | ||
def __init__(self, api): | ||
self.api = api | ||
self.__token: str = None | ||
|
||
@property | ||
def token(self) -> str: | ||
""" | ||
Returns the token used for authentication. | ||
Returns: | ||
str: The authentication token. | ||
""" | ||
return self.__token | ||
|
||
@token.setter | ||
def token(self, value: str): | ||
self.__token = value | ||
|
||
@abstractmethod | ||
async def listen(self, args, on_message): | ||
""" | ||
Listens for incoming messages from the broker. | ||
Args: | ||
args: The arguments for the listen method. | ||
on_message: The callback function to be executed when a message is received. | ||
Returns: | ||
NotImplemented | ||
""" | ||
return NotImplemented |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from .api import SSIBrokerAPI # noqa: F401 | ||
from .hub import SSIBrokerHUB # noqa: F401 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from ..interface_broker_api import IBrokerAPI | ||
|
||
|
||
class SSIBrokerAPI(IBrokerAPI): | ||
def __init__(self, config): | ||
self.config = config | ||
|
||
def get_token(self): | ||
return "token" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
""" Constant for SSI datafeed """ | ||
API_URL = "https://fc-tradeapi.ssi.com.vn" | ||
API_PAPER_URL = "https://fc-paperapi.ssi.com.vn" | ||
ENDPOINT_OTP = "api/v2/Trading/GetOTP" | ||
ENDPOINT_AUTH = "api/v2/Trading/AccessToken" | ||
|
||
ENDPOINT_EQUITY_NEW_ORDER = "api/v2/Trading/NewOrder" | ||
ENDPOINT_EQUITY_MODIFY_ORDER = "api/v2/Trading/ModifyOrder" | ||
ENDPOINT_EQUITY_CANCEL_ORDER = "api/v2/Trading/CancelOrder" | ||
ENDPOINT_EQUITY_POSITION = "api/v2/Trading/stockPosition" | ||
ENDPOINT_EQUITY_ACCOUNT_BALANCE = "api/v2/Trading/cashAcctBal" | ||
|
||
ENDPOINT_DERIVATIVE_NEW_ORDER = "api/v2/Trading/derNewOrder" | ||
ENDPOINT_DERIVATIVE_MODIFY_ORDER = "api/v2/Trading/derModifyOrder" | ||
ENDPOINT_DERIVATIVE_CANCEL_ORDER = "api/v2/Trading/derCancelOrder" | ||
ENDPOINT_DERIVATIVE_POSITION = "api/v2/Trading/derivPosition" | ||
ENDPOINT_DERIVATIVE_ACCOUNT_BALANCE = "api/v2/Trading/derivAcctBal" | ||
|
||
ENDPOINT_ORDER_HISTORY = "api/v2/Trading/orderHistory" | ||
ENDPOINT_ORDERBOOK = "api/v2/Trading/orderBook" | ||
ENDPOINT_MAX_BUY_QUANTITY = "api/v2/Trading/maxBuyQty" | ||
ENDPOINT_MAX_SELl_QUANTITY = "api/v2/Trading/maxSellQty" | ||
|
||
HUB_URL = "wss://fc-tradehub.ssi.com.vn//v2.0/signalr" | ||
HUB_PAPER_URL = "wss://fc-paperhub.ssi.com.vn//v2.0/signalr" | ||
HUB = "BroadcastHubV2" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from ..interface_broker_hub import IBrokerHUB | ||
|
||
|
||
class SSIBrokerHUB(IBrokerHUB): | ||
def __init__(self, api): | ||
super().__init__(api) | ||
|
||
async def listen(self, args, on_message): | ||
return NotImplemented |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from .enum_handler import EnumHandler # noqa: F401 | ||
from .model_handler import BaseModel, AliasChoices, Field # noqa: F401 | ||
from .request_handler import request_handler # noqa: F401 | ||
from .socket_handler import SocketListener # noqa: F401 | ||
from .jwt_handler import jwt_handler # noqa: F401 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
from enum import Enum | ||
|
||
|
||
class EnumHandler(Enum): | ||
def __str__(self) -> str: | ||
return str.__str__(self) | ||
|
||
@classmethod | ||
def keys(cls): | ||
return cls._member_names_ | ||
|
||
@classmethod | ||
def values(cls): | ||
return list(cls._value2member_map_.keys()) | ||
|
||
@classmethod | ||
def items(cls): | ||
return list(cls) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import jwt | ||
import time | ||
|
||
|
||
class JWTHandler: | ||
def is_expired(self, bearer_token: str) -> bool: | ||
if bearer_token is None: | ||
return True | ||
decoded = jwt.decode(bearer_token.replace("Bearer ", ""), options={"verify_signature": False}) | ||
return int(time.time()) > (decoded.get("exp") - 1) | ||
|
||
|
||
jwt_handler = JWTHandler() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from pydantic import BaseModel as BM, ConfigDict, Field, AliasChoices # noqa: F401 | ||
|
||
|
||
class BaseModel(BM): | ||
model_config: ConfigDict = ConfigDict( | ||
use_enum_values=True, | ||
validate_return=True | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import time | ||
import requests | ||
|
||
|
||
class RequestHandler: | ||
def __init__(self) -> None: | ||
self.__timeout: int = 10 | ||
|
||
def get(self, url: str, headers: dict, params: dict, limit: int = 0) -> dict: | ||
try: | ||
res = requests.get(url, headers=headers, params=params, timeout=self.__timeout) | ||
if limit: | ||
time.sleep(limit) | ||
res.raise_for_status() | ||
return res.json() | ||
except requests.RequestException as e: | ||
raise e | ||
|
||
def post(self, url: str, headers: dict, data: dict = {}, limit: int = 0) -> dict: | ||
try: | ||
if data: | ||
res = requests.post(url, headers=headers, json=data, timeout=self.__timeout) | ||
else: | ||
res = requests.post(url, headers=headers, timeout=self.__timeout) | ||
if limit: | ||
time.sleep(limit) | ||
res.raise_for_status() | ||
return res.json() | ||
except requests.RequestException as e: | ||
raise e | ||
|
||
|
||
request_handler = RequestHandler() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
""" This module is responsible for handling the socket connection to the server. """ | ||
import websockets | ||
|
||
|
||
class SocketListener: | ||
""" | ||
A class that handles socket connections. | ||
Methods: | ||
-------- | ||
connect_socket_server(url: str, headers: dict) -> websockets.WebSocketClientProtocol: | ||
Connects to a socket server using the specified URL and headers. | ||
""" | ||
def connect_socket_server(self, url: str, headers: dict) -> websockets.WebSocketClientProtocol: | ||
""" | ||
Connects to a socket server using the specified URL and headers. | ||
Parameters: | ||
----------- | ||
url : str | ||
The URL of the socket server to connect to. | ||
headers : dict | ||
Additional headers to include in the connection request. | ||
Returns: | ||
-------- | ||
websockets.WebSocketClientProtocol | ||
The WebSocket client protocol object representing the connection. | ||
""" | ||
return websockets.connect(url, extra_headers=headers) |