async def process_subscription(self, socket: azmq.Socket): """ Receive request of the form "asset1:ticker1,asset2:ticker2,..." Subscribe to the broker TODO: add handling for exception. Currently always succeed """ msg = await socket.recv_string( ) # format: asset1:ticker1,asset2:ticker2,... self.logger.info(f'Receive subscription request on {msg}') # filter existing assets asset_strings = msg.split(',') assets = [Asset(s) for s in asset_strings] assets = [asset for asset in assets if asset not in self.subscribed] if len(assets) > 0: # submit subscription await utils.wait_for(self.subscribe(assets), self.subscription_wait_time, JobError('Data subscription timeout')) # remember newly added subscription self.subscribed.update(dict.fromkeys(assets)) self.logger.info(f'Subscribed: {str(assets)}') else: self.logger.info(f'No new subscription is needed') socket.send_json({'code': const.DCode.Succeeded.value})
async def run_strategy(self, data_socket: azmq.Socket, order_socket: azmq.Socket): bars = self.panel.update(str_to_datum(await data_socket.recv_string())) if bars is not None: timestamp, prices = bars new_positions = self.strategy.generate_positions(timestamp, prices) if new_positions is not None: # round towards 0 to avoid over-execution position_delta = np.fix(new_positions - self.positions) # send order order = { k: v for k, v in zip(self.asset_strings, position_delta) if abs(v) >= 1 } order['Strategy'] = self.name order_socket.send_json(order) self.logger.info(f'Sent order {order}') executions = await utils.wait_for_reply( order_socket, self.wait_time, const.DCode, 'Order execution') # for post processing self.equity_curve.update(timestamp, executions, prices['close'][-1]) else: self.equity_curve.update(timestamp, {}, prices['close'][-1])
async def get_spec(socket: Socket, request_id: str) -> APISpec: """ Construct open api spec by interrogating FlowMachine. Parameters ---------- socket : Socket request_id : str Unique id of the request Returns ------- APISpec The specification object """ msg = {"request_id": request_id, "action": "get_query_schemas"} socket.send_json(msg) # Get the reply. reply = await socket.recv_json() flowmachine_query_schemas = reply["payload"]["query_schemas"] # Need to mark query_kind as a required field # this is a workaround because the marshmallow-oneOf plugin strips # the query_kind off, which means it can't be required from the marshmallow # side without raising an error for schema, schema_dict in flowmachine_query_schemas.items(): try: if "query_kind" in schema_dict["properties"]: schema_dict["required"].append("query_kind") except KeyError: pass # Doesn't have any properties spec = APISpec( title="FlowAPI", version=__version__, openapi_version="3.0.1", info=dict( description="FlowKit Analytical API", license=dict(name="MPLv2", url="https://www.mozilla.org/en-US/MPL/2.0/"), contact=dict(email="*****@*****.**"), ), ) spec.components.schemas.update(flowmachine_query_schemas) spec.components.security_scheme( "token", { "type": "http", "scheme": "bearer", "bearerFormat": "JWT", "x-security-scopes": sorted(schema_to_scopes(spec.to_dict())), "x-audience": current_app.config["JWT_DECODE_AUDIENCE"], }, ) # Loop over all the registered views and try to parse a yaml # openapi spec from their docstrings for rule in current_app.url_map.iter_rules(): try: func = current_app.view_functions[rule.endpoint] operations = yaml_utils.load_operations_from_docstring( func.__doc__) if len(operations) > 0: for method, op in operations.items(): op["operationId"] = f"{rule.endpoint}.{method}" spec.path( path=rule.rule, operations=operations, ) except Exception as e: pass # Don't include in API return spec
async def get_spec(socket: Socket, request_id: str) -> APISpec: """ Construct open api spec by interrogating FlowMachine. Parameters ---------- socket : Socket request_id : str Unique id of the request Returns ------- APISpec The specification object """ msg = {"request_id": request_id, "action": "get_query_schemas"} socket.send_json(msg) # Get the reply. reply = await socket.recv_json() flowmachine_query_schemas = reply["payload"]["query_schemas"] # Need to mark query_kind as a required field # this is a workaround because the marshmallow-oneOf plugin strips # the query_kind off, which means it can't be required from the marshmallow # side without raising an error for schema, schema_dict in flowmachine_query_schemas.items(): try: schema_dict["required"].append("query_kind") except KeyError: pass # Doesn't have any properties spec = APISpec( title="FlowAPI", version=__version__, openapi_version="3.0.1", info=dict( description="FlowKit Analytical API", license=dict(name="MPLv2", url="https://www.mozilla.org/en-US/MPL/2.0/"), contact=dict(email="*****@*****.**"), ), ) spec.components._schemas = flowmachine_query_schemas spec.components.security_scheme( "token", dict(type="http", scheme="bearer", bearerFormat="JWT") ) # Loop over all the registered views and try to parse a yaml # openapi spec from their docstrings for endpoint_func_name, rule in current_app.url_map.endpoints.items(): try: func = current_app.view_functions[endpoint_func_name] operations = yaml_utils.load_operations_from_docstring(func.__doc__) if len(operations) > 0: for method, op in operations.items(): op["operationId"] = f"{endpoint_func_name}.{method}" spec.path( path=rule[ 0 ].rule, # In theory, could have multiple rules that match but will only be a single one here operations=operations, ) except Exception as e: pass # Don't include in API return spec