-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
💥 breaking with handler template capability
- Loading branch information
Showing
7 changed files
with
402 additions
and
182 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
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 .basic import BasicHandler | ||
from .standard import StandardHandler | ||
|
||
__all__ = ["StandardHandler"] |
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,61 @@ | ||
""" | ||
Basic Parser | ||
""" | ||
|
||
from loguru import logger | ||
from pyparsing import ( | ||
Optional, | ||
Word, | ||
alphas, | ||
nums, | ||
one_of, | ||
pyparsing_common, | ||
) | ||
|
||
from .handler import ParserClient | ||
|
||
|
||
class BasicHandler(ParserClient): | ||
|
||
def __init__(self, **kwargs): | ||
""" | ||
Initialize the Handler object | ||
""" | ||
|
||
super().__init__(**kwargs) | ||
|
||
async def identify_order( | ||
self, | ||
my_string: str, | ||
) -> dict: | ||
""" | ||
Identify an order and return a dictionary | ||
with the order parameters | ||
Args: | ||
my_string (str): Message | ||
Returns: | ||
dict with the order parameters: | ||
action, instrument | ||
""" | ||
try: | ||
action = ( | ||
one_of(self.action_identifier, caseless=True) | ||
.set_results_name("action") | ||
.set_parse_action(pyparsing_common.upcase_tokens) | ||
) | ||
instrument = Word(alphas + nums).set_results_name("instrument") | ||
|
||
order_grammar = action("action") + Optional(instrument, default=None) | ||
|
||
order = order_grammar.parse_string(instring=my_string, parse_all=False) | ||
logger.debug("Order parsed {}", order) | ||
return order.asDict() | ||
|
||
except Exception as error: | ||
logger.error(error) | ||
return error |
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,124 @@ | ||
from datetime import datetime, timezone | ||
|
||
from loguru import logger | ||
|
||
|
||
class ParserClient: | ||
""" | ||
Parser Handler Base Class | ||
Args: | ||
**kwargs: | ||
Methods: | ||
search(self) | ||
identify_order(self) | ||
get_order(self) | ||
replace_instrument(self) | ||
""" | ||
|
||
def __init__(self, **kwargs): | ||
""" | ||
Initialize the chat client. | ||
""" | ||
|
||
self.name = kwargs.get("name", None) | ||
self.enabled = kwargs.get("enabled", None) | ||
|
||
self.action_identifier = kwargs.get("action_identifier", None) | ||
self.stop_loss_identifier = kwargs.get("stop_loss_identifier", None) | ||
self.take_profit_identifier = kwargs.get("take_profit_identifier", None) | ||
self.quantity_identifier = kwargs.get("quantity_identifier", None) | ||
self.order_type_identifier = kwargs.get("order_type_identifier", None) | ||
self.leverage_type_identifier = kwargs.get("leverage_type_identifier", None) | ||
self.comment_identifier = kwargs.get("comment_identifier", None) | ||
self.stop_loss = kwargs.get("stop_loss", None) | ||
self.take_profit = kwargs.get("take_profit", None) | ||
self.quantity = kwargs.get("quantity", None) | ||
self.instrument_mapping = kwargs.get("instrument_mapping", None) | ||
self.mapping = kwargs.get("mapping", None) | ||
self.ignore_instrument = kwargs.get("ignore_instrument", None) | ||
|
||
async def identify_order( | ||
self, | ||
my_string: str, | ||
) -> dict: | ||
""" | ||
Identify an order and return a dictionary | ||
with the order parameters to be implemented in | ||
the child class | ||
""" | ||
|
||
async def search(self, message: str) -> bool: | ||
""" | ||
Search an order. | ||
Args: | ||
message (str): Message | ||
Returns: | ||
bool | ||
""" | ||
if message: | ||
order_identifier = message.split()[0].lower() | ||
if order_identifier in ( | ||
action.lower() for action in self.action_identifiers | ||
): | ||
logger.debug("Order identifier found in {}", order_identifier) | ||
return True | ||
|
||
return False | ||
|
||
async def replace_instrument(self, order): | ||
""" | ||
Replace instrument by an alternative instrument, if the | ||
instrument is not in the mapping, it will be ignored. | ||
Args: | ||
order (dict): | ||
Returns: | ||
dict | ||
""" | ||
instrument = order["instrument"] | ||
for item in self.mapping: | ||
if item["id"] == instrument: | ||
order["instrument"] = item["alt"] | ||
break | ||
logger.debug("Instrument symbol changed", order) | ||
return order | ||
|
||
async def get_order( | ||
self, | ||
msg: str, | ||
): | ||
""" | ||
Get an order from a message. The message can be | ||
an order or an order identifier | ||
Args: | ||
msg (str): Message | ||
Returns: | ||
dict | ||
""" | ||
if not await self.search(msg): | ||
logger.debug("No order identified") | ||
return None | ||
order = await self.identify_order(msg) | ||
if isinstance(order, dict): | ||
order["timestamp"] = datetime.now(timezone.utc).strftime( | ||
"%Y-%m-%dT%H:%M:%SZ" | ||
) | ||
if self.instrument_mapping: | ||
logger.debug("mapping") | ||
await self.replace_instrument(order) | ||
if order["instrument"] in self.ignore_instrument: | ||
logger.debug("Ignoring instrument {}", order["instrument"]) | ||
return | ||
logger.debug("Order identified {}", order) | ||
return order |
This file was deleted.
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,91 @@ | ||
""" | ||
Standard Parser | ||
""" | ||
|
||
from loguru import logger | ||
from pyparsing import ( | ||
Combine, | ||
Optional, | ||
Suppress, | ||
Word, | ||
alphas, | ||
nums, | ||
one_of, | ||
pyparsing_common, | ||
) | ||
|
||
from .handler import ParserClient | ||
|
||
|
||
class StandardHandler(ParserClient): | ||
|
||
def __init__(self, **kwargs): | ||
""" | ||
Initialize the Handler object | ||
""" | ||
|
||
super().__init__(**kwargs) | ||
|
||
async def identify_order( | ||
self, | ||
my_string: str, | ||
) -> dict: | ||
""" | ||
Identify an order and return a dictionary | ||
with the order parameters | ||
Args: | ||
my_string (str): Message | ||
Returns: | ||
dict | ||
""" | ||
try: | ||
action = ( | ||
one_of(self.action_identifier, caseless=True) | ||
.set_results_name("action") | ||
.set_parse_action(pyparsing_common.upcase_tokens) | ||
) | ||
instrument = Word(alphas + nums).set_results_name("instrument") | ||
stop_loss = Combine( | ||
Suppress(self.stop_loss_identifier) + Word(nums) | ||
).set_results_name("stop_loss") | ||
take_profit = Combine( | ||
Suppress(self.take_profit_identifier) + Word(nums) | ||
).set_results_name("take_profit") | ||
quantity = Combine( | ||
Suppress(self.quantity_identifier) | ||
+ Word(nums) | ||
+ Optional(Suppress("%")) | ||
).set_results_name("quantity") | ||
order_type = one_of( | ||
self.order_type_identifier, caseless=True | ||
).set_results_name("order_type") | ||
leverage_type = one_of( | ||
self.leverage_type_identifier, caseless=True | ||
).set_results_name("leverage_type") | ||
comment = Combine( | ||
Suppress(self.comment_identifier) + Word(alphas) | ||
).set_results_name("comment") | ||
|
||
order_grammar = ( | ||
action("action") | ||
+ Optional(instrument, default=None) | ||
+ Optional(stop_loss, default=self.stop_loss) | ||
+ Optional(take_profit, default=self.take_profit) | ||
+ Optional(quantity, default=self.quantity) | ||
+ Optional(order_type, default=None) | ||
+ Optional(leverage_type, default=None) | ||
+ Optional(comment, default=None) | ||
) | ||
|
||
order = order_grammar.parse_string(instring=my_string, parse_all=False) | ||
logger.debug("Order parsed {}", order) | ||
return order.asDict() | ||
|
||
except Exception as error: | ||
logger.error(error) | ||
return error |
Oops, something went wrong.