Algorithmic Trading - Real Trading

Now that we've built various algorithmic trading strategies and successfully backtested them with satisfactory results and paper traded them in live markets, it is finally time for real trading.

Real trading is where we execute a trading strategy in the live market hours with real money. If your strategy has performed well in backtesting and paper trading, you can expect similar results with real money. Please note that your strategy may not perform as expected in the real market, despite giving good backtesting and paper trading results. Profitable backtesting and paper trading results are prerequisites for a profitable real trading experience but are not sufficient to guarantee a profit for every session.

For real trading, a strategy configuration is required. It consists of multiple parameters, some of which are as follows:

  • Start and end times: The time duration within the current day for which paper trading should be run.
  • Financial instrument(s): One or more financial instruments for which paper trading should be performed.
  • Candle interval: One of various possible candle intervals; for example, 1 minute, 15 minutes, hour, or day.
  • Strategy specific parameters: Values for custom parameters defined in the strategy.
  • Strategy mode: One of intraday or delivery. Intraday strategies punch intraday orders, which are squared-off at the end of the day. Delivery strategies punch delivery orders, which don't square-off at the end of the day and get carried forward to the next trading day.

A real trading engine is required to perform real trading on a given strategy. In this chapter, you will use the real trading engine provided by AlgoBulls (https://algobulls.com), an algorithmic trading platform that makes its services available via its developer options. It provides a Python package called pyalgotrading (https://github.com/algobulls/pyalgotrading) to make these services available.

You coded two algorithmic trading strategies in Chapter 8, Algorithmic Trading Strategies – Coding Step by Step. Recall that the strategy descriptions are as follows:

  • EMA-Regular-Order strategy: A strategy based on the technical indicator EMA and regular orders. (The first six recipes of Chapter 7, Placing Bracket and Cover Orders on the Exchange)
  • MACD-Bracket-Order strategy: A strategy based on the technical indicator MACD and bracket orders. (The remaining six recipes of Chapter 7, Placing Bracket and Cover Orders on the Exchange)
These strategies are also available as part of a Python package, pyalgostrategypool. You can install it using pip with the $ pip install pyalgostrategypool command. You can also check them out on GitHub (https://github.com/algobulls/pyalgostrategypool). 

When following Chapter 8Algorithmic Trading Strategies – Coding Step by Step, you uploaded these two strategies to your AlgoBulls account. In this chapter, you will fetch these strategies from your AlgoBulls account and perform real trading on them. Real trading is fully automated and requires no involvement from your end while the trading session is going on. Upon real trading, you would gather strategy execution logs and various reports – namely, the profit and loss report and the statistics report. By using pyalgotrading, you ensure that you're focusing on developing and executing real trading strategies without worrying about the ecosystem needed for the strategy's execution. 

This chapter includes step-by-step recipes for the previously mentioned strategies, from setting up a connection to the AlgoBulls platform, fetching the strategy, and running real trading jobs to fetching the execution logs and fetching various types of reports.

In this chapter, you will cover the following recipes:

  • EMA-Regular-Order strategy  fetching the strategy
  • EMA-Regular-Order strategy  real trading the strategy
  • EMA-Regular-Order strategy  fetching real trading logs in real time
  • EMA-Regular-Order strategy – fetching a real trading report  P&L table
  • EMA-Regular-Order strategy – fetching a real trading report – statistics table
  • MACD-Bracket-Order strategy – fetching the strategy
  • MACD-Bracket-Order strategy – real trading the strategy
  • MACD-Bracket-Order strategy – fetching real trading logs in real time
  • MACD-Bracket-Order strategy – fetching a real trading report – P&L table
  • MACD-Bracket-Order strategy – fetching a real trading report – statistics table

Real trading is only meaningful if run during the live market hours, unlike backtesting, which can be run at any time. Please make sure you try out the recipes of this chapter in live market hours.

Technical requirements

You will need the following to successfully execute the recipes in this chapter:

  • Python 3.7+
  • Python package:
  • pyalgotrading ( $ pip install pyalgotrading )

Ensure you have added and bound your broking details on https://algobulls.com. Refer to Appendix II for more details. You can use any broker supported by the AlgoBulls platform for this chapter.

The latest Jupyter notebook for this chapter can be found on GitHub at https://github.com/PacktPublishing/Python-Algorithmic-Trading-Cookbook/tree/master/Chapter11.

EMA–Regular–Order strategy  fetching the strategy

In this recipe, you will fetch the StrategyEMARegularOrder strategy class from your account on the AlgoBulls platform. This recipe starts with setting up a connection to the AlgoBulls platform, querying all available strategies in your account, and fetching details of the required strategy class; that is, StrategyEMARegularOrder.

Make sure you have gone through the first six recipes of Chapter 8Algorithmic Trading Strategies – Coding Step by Step, to get a complete picture of the strategy class we will be using; that is, StrategyEMARegularOrder.

How to do it…

We execute the following steps for this recipe:

  1. Import the necessary modules:
>>> from pyalgotrading.algobulls import AlgoBullsConnection
  1. Create a new AlgoBulls connection object:
>>> algobulls_connection = AlgoBullsConnection()
  1. Fetch the authorization URL:
>>> algobulls_connection.get_authorization_url()

We get the following output:

Please login to this URL with your AlgoBulls credentials and get your developer access token: https://app.algobulls.com/user/login
'https://app.algobulls.com/user/login'
  1. Log into the preceding link with your AlgoBulls credentials, fetch your token, and set it here (refer to Appendix II for more details):
>>> algobulls_connection.set_access_token(
'80b7a69b168c5b3f15d56688841a8f2da5e2ab2c')
  1. Fetch and display all the strategies you have created and uploaded so far:
>>> all_strategies = algobulls_connection.get_all_strategies()
>>> all_strategies

We get the following output. Your output may differ (make sure you have followed the recipes in Chapter 8Algorithmic Trading Strategies – Coding Step by Step, to get a similar output):

  1. Fetch and display the strategy code of the first strategy:
>>> strategy_code1 = all_strategies.iloc[0]['strategyCode']
>>> strategy_code1

We get the following output (your output may differ):

'49287246f9704bbcbad76ade9e2091d9'
  1. Before real trading your strategy, you can inspect your strategy to ensure you have the right strategy:
>>> strategy_details1 = 
algobulls_connection.get_strategy_details(strategy_code1)
>>> print(strategy_details1)

We got the following output:

class StrategyEMARegularOrder(StrategyBase):

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

self.timeperiod1 = self.strategy_parameters['timeperiod1']
self.timeperiod2 = self.strategy_parameters['timeperiod2']

self.main_order = None

def initialize(self):
self.main_order = {}

@staticmethod
def name():
return 'EMA Regular Order Strategy'
....
def strategy_exit_position(self, candle, instrument,
sideband_info):
if sideband_info['action'] == 'EXIT':
self.main_order[instrument].exit_position()
self.main_order[instrument] = None
return True

return False

The complete output is not shown here. Please visit the following link to read the complete output, at https://github.com/algobulls/pyalgostrategypool/blob/master/pyalgostrategypool/strategy_ema_regular_order.py.

How it works…

You import the necessary modules in step 1. In step 2, an instance of the AlgoBullsConnection class is created, named algobulls_connection. In step 3, you get the authorization URL using the get_authorization_url() method of the algobulls_connection object. This prints the authorization URL. You should visit this URL from your web browser to sign into the AlgoBulls platform and fetch your developer access token. (You can find more details, along with screenshots, in Appendix II on fetching developer access tokens from the AlgoBulls platform.) You copy the access token and set it in step 4 using the set_access_token() method of algobulls_connection. If the token is accepted, a successful connection is set up with the AlgoBulls platform.

In step 5, you fetch all the strategies you have created and uploaded on the AlgoBulls platform so far. You use the get_all_strategies() method for this step and assign it to a new variable, all_strategies. This variable is a pandas.DataFrame object with strategyCode and strategyName columns. This table holds information on the strategy code and strategy names you have uploaded previously. If you followed the EMA-Regular-Order strategy – uploading the strategy on the AlgoBulls trading platform recipe from Chapter 8, Algorithmic Trading Strategies – Coding Step by Step, you will find a strategy called EMA regular order strategy. In step 6, you assign the strategy code of the strategy, EMA regular order strategy, to a new variable called strategy_code1. The strategy code is shown in the output of this step. This strategy code is unique for every strategy on the AlgoBulls platform.

Finally, in step 7, you ensure that the strategy being referred to by strategy_code1 is indeed the one you uploaded earlier (in the EMA-Regular-Order strategy – uploading the strategy on the AlgoBulls trading platform recipe in Chapter 8Algorithmic Trading Strategies – Coding Step by Step). You use the get_strategy_details() method of the algobulls_connection object to inspect the strategy. This method takes strategy code as an argument. You pass strategy_code1 here. This method returns the entire class code as a string. You assign it to a new variable, strategy_details1, and display it.

If, you would like to change the class code being referred to by strategy_code1, as shown in step 7, please refer to There's more… section of the EMA-Regular-Order strategy – uploading the strategy on the AlgoBulls trading platform recipe in Chapter 8, Algorithmic Trading Strategies – Coding Step by Step.

EMA–Regular–Order strategy real trading the strategy

In this recipe, you will perform real trading on the EMA-Regular-Order strategy. You must have fetched this strategy from your account on the AlgoBulls platform in the preceding recipe of this chapter. You will leverage the real trading functionality facilitated by pyalgotrading for this recipe, which, in turn, submits a real trading job on the AlgoBulls platform.

Once submitted, real trading will be run by the AlgoBulls real trading engine. You can query its status any time to find out about the state of the real trading job. The job goes through the following states, in the given order: 

  • STARTING (intermediate state)
  • STARTED (stable state)
  • STOPPING (intermediate state)
  • STOPPED (stable state)

On submitting a job, it starts with an intermediate state, STARTING. In this state, the AlgoBulls real trading engine fetches the strategy and gets the execution environment ready, which may take a couple of minutes. Once done, the job moves to the STARTED state. The real trading strategy is implemented in this stage. Here, it stays as long as it takes for real trading to complete. Once done, the job moves to an intermediate state, STOPPING. In this state, the AlgoBulls real trading engine cleans up the resources that have been allocated for this job, which usually takes less than a minute. Finally, the job moves to the STOPPED state.

If you have already submitted a strategy real trading job, you cannot submit another job for the same strategy until the first job completes. This means you have to wait for the first job to move to the STOPPED state. If the first job is long-running and you would like to stop it immediately, you can submit a stop job request via pyalgotrading. You need to ensure the job is in the STARTED state before submitting the request. 

The following state machine diagram demonstrates the various states and transitions of a real trading job during its lifetime on the AlgoBulls platform:

After submitting a real trading job, you can fetch logs and reports for the strategy's execution in real time. The logs and reports help validate the strategy's performance and debug any potential issues.

Make sure you have gone through the first six recipes of Chapter 8Algorithmic Trading Strategies – Coding Step by Step, to get a complete picture of the strategy class we will be using; that is, StrategyEMARegularORder.

Getting ready

Make sure the algobulls_connection and strategy_code1 objects are available in your Python namespace. Refer to the preceding recipe to set up the algobulls_connection and strategy_code1 objects.

How to do it…

We execute the following steps for this recipe:

  1. Import the necessary modules:
>>> from datetime import time
>>> from pyalgotrading.constants import *
  1. Search for an instrument by using its trading symbol as a keyword. Assign the returned object to instruments:
>>> instruments = algobulls_connection.search_instrument('SBIN')
>>> instruments

We got the following output (your output may differ):

[{'id': 7, 'value': 'NSE:SBIN'}]
  1. Get value for the instrument of choice from instruments:
>>> instrument = instruments[0]['value']
>>> instrument

We got the following output:

'NSE:SBIN'
  1. Submit a real trading job for strategy_code1:
>>> algobulls_connection.realtrade(
strategy_code=strategy_code1,
start_time=time(hour=9, minute=15),
end_time=time(hour=15, minute=30),
instrument=instrument,
lots=1,
strategy_parameters={
'timeperiod1': 5,
'timeperiod2': 12
},
candle_interval=CandleInterval.MINUTES_15)

We got the following output:

Setting Strategy Config... Success.
Submitting REALTRADING job... Success.
  1. Check the status of the submitted real trading job:
>>> algobulls_connection.get_realtrading_job_status(strategy_code1)

We got the following output:

{'data': 'STARTING'}
  1. Check the status of the submitted job again after some time:
>>> algobulls_connection.get_realtrading_job_status(strategy_code1)

We got the following output:

{'data': 'STARTED'}

How it works…

In step 1, you import the time class from the datetime module and all the constants from the pyalgotrading.constants module. In step 2, you fetch the instrument that you would like to real trade the strategy for, EMA-Regular-Order strategy, using the search_instrument() method of the algobulls_connection object. The search_instrument() method accepts a search string as an argument, which should be the trading symbol, in part or complete, of the instrument you are interested in. You pass 'SBIN' here. This function returns a list containing details of the instruments that match the search string. There could be multiple instruments that have the search string in their trading symbols. In step 3, you fetch the value of the first matched instrument and assign it to a new variable, instrument.

In step 4, you submit a real trading job using the realtrade() method of the algobulls_connection() object. It takes the following arguments:

  • strategy_code: Strategy code of the strategy for which real trading has to be performed. This should be a string. You pass strategy_code1 here.
  • start_time: Today's time when real trading should be started. This should be a datetime.time object. Here, you pass an object holding the value for 9:15 hours  time(hour=9, minute=15). Refer to the first recipe of this book for details on creating a time object.
  • end_time: Today's time when real trading should be performed. This object should hold a time value ahead of the value held by start_time. This should be a datetime.time instance. Here, you pass an object holding the value 15:30 hours  time(hour=15, minute=30).
  • instrument: A financial instrument for which real trading should be run. Historical data will be fetched for this instrument. This should be a string. You pass instrument here.
  • lots: Number of lots for which real trading should be performed. This should be an integer. The quantity is calculated by the strategy as number of lots × lot size of the financial instrument. You pass 1 here.
  • strategy_parameters: Parameter names and values expected by the strategy. This should be a dictionary, with parameter-name and parameter-value as key-value pairs. You pass the following parameters here:
  • timeperiod1: 5
  • timeperiod2: 12 

(Recall that the parameters for the EMA-Regular-Order strategy have been defined in its __init__() method, as shown in the first recipe of Chapter 8Algorithmic Trading Strategies – Coding Step by Step).

  • candle_interval: The candle interval for the historical data being fetched for real trading. This should be an enum of the CandleInterval type. You pass CandleInterval.MINUTES_15 here. (The CandleInterval enum provides various enums for candle intervals, some of which are MINUTE_1, MINUTES_3 , MINUTES_5, MINUTES_10, MINUTES_15, MINUTES_30, HOUR, and DAY.)

If the job submission is successful, you will see Success messages printed by the realtrade() function. 

Once a job has been submitted, it takes a while to start. After starting, it may take some time to finish, depending on the duration of real trading, as specified using the start_time and end_time arguments. Usually, real trading is run for the entire trading day, which means the job would be running for 6-8 hours.

In step 5, you fetch the job's status using the get_realtrading_job_status() method of the algobulls_connection object. You pass strategy_code1 as the argument here. This method returns a dictionary with a single key-value pair  the data and the job status. If you query the status immediately after placing the job, you get 'STARTING' as the status. In step 6, you query the status again after some time, and if the job starts, you get a status of 'STARTED'

A successful submission implies that the minimum inputs needed to real trade a strategy have been passed in the required format. However, this does not ensure that the strategy will run without errors. The strategy's execution may still run into errors during real trading. To debug execution issues, you would need to fetch the output logs, which will be explained in the next recipe. Possible reasons for errors could be either bugs in the strategy class' Python code or that an incomplete strategy_parameters dictionary has been passed to the realtrade() function.

There's more…

If a job is running for a long time and you would like to stop it before its completion, you can use the stop_realtrading_job() method of the algobulls_connection object. This method accepts strategy code as an argument. You pass strategy_code1 here. This method submits a stop request to the AlgoBulls real trading engine. If the request is accepted, you will see a Success message here:

>>> algobulls_connection.stop_realtrading_job(strategy_code1)
Stopping REALTRADING job... Success.

If you query the status after submitting the stop request, you'll get 'STOPPING' as the status:

>>> algobulls_connection.get_realtrading_job_status(strategy_code1)
{'data': 'STOPPING'}

If you query the status again after some time, and if the job has stopped, you'll get 'STOPPED' as the status:

>>> algobulls_connection.get_realtrading_job_status(strategy_code1)
{'data': 'STOPPED'}

EMA–Regular–Order strategy fetching real trading logs in real time

After submitting a real trading job on the AlgoBulls platform, the AlgoBulls real trading engine starts executing the strategy. During its execution, every event that occurs and the decisions that are made by the AlgoBulls real trading engine are recorded with exact timestamps in the form of textual logs.

Examples of recorded activities include the given strategy config, every new candle generated at regular intervals, trades punched by your strategy, the entry and exit of positions created by these trades, waits for new candles, and so on. These logs are quintessential when validating the strategy and debugging behavior or performance issues that are frequently encountered while developing a strategy. 

In this recipe, you will fetch real trading logs for your strategy. The logs start coming up as soon as your submitted real trading job reaches the 'STARTED' state (refer to the preceding recipe for more information on the states of a real trading job). The AlgoBulls platform allows you to fetch logs in real time, even while the real trading job is still going on. You can get insights into the strategy's execution without having to wait for the real trading job to complete. This is helpful as real trading jobs are usually long-running. The pyalgotrading package provides a simple method we can use to fetch the execution logs for a given strategy.

Make sure you have gone through the first six recipes of Chapter 8, Algorithmic Trading Strategies – Coding Step by Step, to get a complete picture of the strategy class we will be using; that is, StrategyEMARegularOrder.

Getting ready

Make sure the algobulls_connection and strategy_code1 objects are available in your Python namespace. Refer to the first recipe of this chapter to set up the algobulls_connection and strategy_code1 objects.

How to do it…

Execute the following steps to complete this recipe:

  1. Fetch the real trading execution logs for strategy_code1:
>>> logs = algobulls_connection.get_realtrading_logs(
strategy_code1)
>>> print(logs)

We got the following output (your output may differ):

[2020-07-09 09:12:25] Logs not available yet. Please retry in sometime.
  1. Fetch the real trading execution logs for strategy_code1 again after some time:
>>> logs = algobulls_connection.get_realtrading_logs(
strategy_code1)
>>> print(logs)

We got the following output (your output may differ):


########################################
INITIALIZING ALGOBULLS CORE (v3.2.0)...
########################################
[2020-07-09 09:13:05] Welcome PUSHPAK MAHAVIR DAGADE!
[2020-07-09 09:13:05] Reading strategy...
[2020-07-09 09:13:05] STARTING ALGOBULLS CORE...
...
[2020-07-09 10:30:00] [CRITICAL] [order] [PLACING NEW ORDER] [2020-07-09 10:30:00] [2b079bc873f64f53a33f91b6ceec707b] [BUY] [NSE:SBIN] [QTY:1] [QTY PENDING: 1] [ENTRY PRICE: 194.7] [PRICE:None] [TRIGGER PRICE:None] [ORDER_TYPE_REGULAR] [ORDER_CODE_INTRADAY] [ORDER_VARIETY_MARKET] [ORDER_POSITION_ENTER]
...
[2020-07-09 15:30:00] [INFO] [clock] Candle generation has been stopped...
[2020-07-09 15:30:00] [INFO] [tls] Received event END OF MARKET. Stopping Trading Core Engine...
[2020-07-09 15:30:00] [INFO] [tls] Exiting all open positions with order code: ORDER_CODE_INTRADAY (if any)...
[2020-07-09 15:30:00] [CRITICAL] [tls] [User: PUSHPAK MAHAVIR DAGADE] Trading session completed
...

The complete output is not shown here. Please visit the following link to read the complete output: https://github.com/algobulls/pyalgostrategypool/blob/master/pyalgostrategypool/sample/realtrading/strategy_ema_regular_order/logs.txt.

How it works…

In step 1, you use the get_realtrading_logs() method of the algobulls_connection object to fetch the strategy real trading logs in real time. This method accepts strategy code as an argument. You pass strategy_code1 here. The return data is a string. If you try this step immediately after submitting the job, you get a string, which says the logs are not ready yet ([2020-07-09 09:12:25] Logs not available yet. Please retry in sometime.). This happens if the real trading job is in the 'STARTING' state.

In step 2, you fetch the logs again after some time. If the job is out of the 'STARTING' state, you start getting your strategy execution logs. You get all the real trading logs every time you call the get_realtrading_logs() function.

There's more...

Once the real trading job moves to the 'STOPPED' state, no new logs are generated. You can fetch the complete logs any time before you submit the next real trading job for the same strategy. If a new real trading job is submitted (for the same strategy), these logs will no longer be accessible via the get_realtrading_logs() method. You can save the fetched logs to a file if you'd like to refer to them at a later date.

EMA–Regular–Order strategy fetching a real trading report profit and loss table

After submitting a real trading job on the AlgoBulls Platform, the AlgoBulls real trading engine starts executing the strategy. During its execution, along with the logs, the AlgoBulls real trading engine also generates a P&L table in real time. This table holds information on every trade punched in by the strategy. It also contains details on the mappings between entry and exit orders, the trade P&L, and the cumulative P&L, sorted chronologically, with the latest order first. This table gives us insight into the strategy's overall performance with the help of individual and cumulative P&L numbers. The entry-exit order mapping also helps validate the strategy's behavior. 

In this recipe, you will fetch the P&L table report for your strategy. This report is available as soon as the first trade is punched in by your strategy after you submit a real trading job. The AlgoBulls platform allows you to fetch the P&L table in real time, even while the real trading job is still going on. You can get insights into the strategy's performance without having to wait for the real trading job to complete. This is helpful as real trading jobs are usually long-running. The pyalgotrading package provides a simple method we can use to fetch the P&L table for a given strategy.

Make sure you have gone through the first six recipes of Chapter 8, Algorithmic Trading Strategies – Coding Step by Step, to get a complete picture of the strategy class we will be using; that is, StrategyEMARegularOrder.

Getting ready

Make sure the algobulls_connection and strategy_code1 objects are available in your Python namespace. Refer to the first recipe of this chapter to set up the algobulls_connection and strategy_code1 objects.

How to do it…

Fetch the real trading P&L report for strategy_code1:

>>> algobulls_connection.get_realtrading_report_pnl_table(strategy_code1)

We get the following output. Your output may differ (note that the following output has been split into multiple tables for representation purposes. You will see a single wide table in your Jupyter Notebook):

How it works…

In this recipe, you use the get_realtrading_report_pnl_table() method of the algobulls_connection object to fetch the real trading P&L table in real time. This method accepts strategy code as an argument. You pass strategy_code1 here. The return data is a pandas.DataFrame object with multiple columns, described as follows:

  • instrument: Financial instrument for which the trade was entered.
  • entry_timestamp: The timestamp at which the entry order was placed. (Note that it may remain in the 'OPEN' state for a while before it goes to the 'COMPLETE' state.)
  • entry_transaction_type: Entry order transaction type (either BUY or SELL).
  • entry_quantity: Entry order quantity.
  • entry_price: Price at which the entry order gets executed and goes to the 'COMPLETE' state.
  • exit_timestamp: The timestamp at which the exit order was placed. (Note that it may remain in the 'OPEN' state for a while before it goes to the 'COMPLETE' state.)
  • exit_transaction_type: Exit order transaction type (either BUY or SELL).
  • exit_quantity: Exit order quantity.
  • exit_price: Price at which the exit order gets executed and goes to the 'COMPLETE' state.
  • pnl_absolute: Difference between the exit order execution price and the entry order execution price. Mathematically, this is (exit_price - entry_price)*exit_quantity for a long trade and (entry_price - exit_price)*exit_quantity for a short trade. A positive value would imply that the trade is a profit-making trade. A negative value would imply that the trade is a loss-making trade.
  • pnl_percentage: Percentage of profit or loss with respect to the entry price. Mathematically, this is pnl_absolute / entry_price / exit_quantity x 100.
  • pnl_cumulative_absolute: Cumulative profit or loss. Mathematically, this is the sum of all the pnl_absolute values of the previous trades. This number gives us direct insight into the strategy's performance against the simulation time.
  • pnl_cumulative_percentage: Percentage of cumulative profit or loss with respect to the entry price. Mathematically, this is pnl_cumulative / entry_price / exit_quantity × 100.

There's more...

Once the real trading job moves to the 'STOPPED' state, the P&L table report will not update anymore. You can fetch the complete P&L report any time before you submit the next real trading job for the same strategy. If a new real trading job is submitted (for the same strategy), this report will no longer be accessible via the get_realtrading_report_pnl_table() method. You can save the fetched report to a .csv file if you'd like to refer to it at a later date.

EMA–Regular–Order strategy fetching a real trading report statistics table

After submitting a real trading job on the AlgoBulls platform, the AlgoBulls real trading engine starts executing the strategy. During its execution, along with the logs and P&L table, the AlgoBulls real trading engine also generates a summary from the P&L table in real time. This summary is a table of statistics containing various statistical numbers, such as Net P&L (absolute and percentage), Max Drawdown (absolute and percentage), count of total trades, winning trades, losing trades, long trades and short trades, the maximum gain and minimum gain (or maximum loss), and the average profit per winning and losing trade. This table gives an instant overview of the strategy's overall performance.

In this recipe, you will fetch the statistics table report for your strategy. This report is available as soon as the first trade is punched in by your strategy after you submit a real trading job. The AlgoBulls platform allows you to fetch the statistics table in real time, even while the real trading job is still going on. You can get insights into the strategy's performance without having to wait for the real trading job to complete. This is helpful as real trading jobs are usually long-running. The pyalgotrading package provides a simple method we can use to fetch the statistics table for a given strategy.

Make sure you have gone through the first six recipes of Chapter 8Algorithmic Trading Strategies – Coding Step by Step, to get a complete picture of the strategy class we will be using; that is, StrategyEMARegularOrder.

Getting ready

Make sure the algobulls_connection and strategy_code1 objects are available in your Python namespace. Refer to the first recipe of this chapter to set up the algobulls_connection and strategy_code1 objects.

How to do it…

Fetch the real trading statistics report for strategy_code1:

>>> algobulls_connection.get_realtrading_report_statistics(strategy_code1)

We got the following output (your output may differ):

How it works…

In this recipe, you use the get_realtrading_report_statistics() method of the algobulls_connection object to fetch the real trading statistics table in real time. This method accepts strategy code as an argument. You pass strategy_code1 here. The return data is a pandas.DataFrame object with two columns – highlight_type and highlight_value – and multiple rows. The rows are described as follows:

  • Net PnL: The cumulative real trading P&L. This is also the pnl_cumulative_absolute value of the first entry in the P&L table.
  • Net PnL %: The cumulative real trading P&L percentage. This is also the pnl_cumulative_percentage value of the first entry in the P&L table.
  • Max Drawdown: The lowest value in the pnl_cumulative column of the P&L table. This indicates the maximum loss your strategy has encountered during the execution.
  • Max Drawdown %: Mathematically, this is (Max Drawdown) / (corresponding entry_price) / exit_quantity × 100.
  • Number of Trades: Total trades (entry and exit counted as one) during the session.
  • Number of Wins: Count of trades where the trade P&L was non-negative.
  • Number of Losses: Count of trades where the trade P&L was negative.
  • Number of Long Trades: Count of trades where the entry transaction type was 'BUY'.
  • Number of Short Trades: Count of trades where the entry transaction type was 'SELL'.
  • Max Gain: P&L of the trade with the maximum P&L value among all trades.
  • Min Gain: P&L of the trade with the minimum P&L value among all trades.
  • Avg. Profit per winning trade: Mathematically, this is (Total P&L of winning trades) / (Count of winning trades).
  • Avg. Profit per losing trade: Mathematically, this is (Total P&L of losing trades) / (Count of losing trades).

There's more...

If the statistics table is fetched while the real trading job is still running, the aforementioned numbers will be intermediate numbers, based on the trades completed until that time. The numbers may change as more trades are punched in, until the real trading job completes.

Once the real trading job moves to the 'STOPPED' state, the statistics table will not change anymore. You can fetch the complete statistics table any time before you submit the next real trading job for the same strategy. If a new real trading job is submitted (for the same strategy), this table will no longer be accessible via the get_realtrading_report_statistics() method. You can save the fetched report table to a .csv file if you'd like to refer to it at a later date.

MACD–Bracket–Order strategy  fetching the strategy

In this recipe, you will fetch the StrategyMACDBracketOrder strategy class from your account on the AlgoBulls platform, which you must have uploaded while going through the last recipe in Chapter 8Algorithmic Trading Strategies – Coding Step by Step. This recipe starts with setting up a connection to the AlgoBulls platform, querying all available strategies in your account, and fetching details about the required strategy class; that is, StrategyMACDBracketOrder.

Make sure you have gone through the last six recipes of Chapter 8Algorithmic Trading Strategies Coding Step by Step, to get a complete picture of the strategy class we will be using; that is, StrategyMACDBracketOrder.

How to do it…

Execute the following steps to complete this recipe:

  1. Import the necessary modules:
>>> from pyalgotrading.algobulls import AlgoBullsConnection
  1. Create a new AlgoBulls connection object:
>>> algobulls_connection = AlgoBullsConnection()
  1. Fetch the authorization URL:
>>> algobulls_connection.get_authorization_url()

We got the following output:

Please login to this URL with your AlgoBulls credentials and get your developer access token: https://app.algobulls.com/user/login
'https://app.algobulls.com/user/login'
  1. Log into the preceding link with your AlgoBulls credentials, fetch your token, and set it here (refer to Appendix II for more details):
>>> algobulls_connection.set_access_token('
80b7a69b168c5b3f15d56688841a8f2da5e2ab2c')
  1. Fetch and display all the strategies you have created and uploaded so far:
>>> all_strategies = algobulls_connection.get_all_strategies()
>>> all_strategies

We got the following output. Your output may differ (make sure you've followed the recipes in Chapter 8Algorithmic Trading Strategies – Coding Step by Step, to get a similar output):

  1. Fetch and display the strategy code of the second strategy; that is, the MACD-Bracket-Order strategy:
>>> strategy_code2 = all_strategies.iloc[1]['strategyCode']
>>> strategy_code2

We got the following output (your output may differ):

'49287246f9704bbcbad76ade9e2091d9'
  1. Before real trading your strategy, you can inspect your strategy to ensure you have the right strategy:
>>> strategy_details2 = 
algobulls_connection.get_strategy_details(strategy_code2)
>>> print(strategy_details2)

We got the following output:

class StrategyMACDBracketOrder(StrategyBase):

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

self.fastMA_period =
self.strategy_parameters['fastma_period']
self.slowMA_period =
self.strategy_parameters['slowma_period']
self.signal_period =
self.strategy_parameters['signal_period']
self.stoploss =
self.strategy_parameters['stoploss_trigger']
self.target = self.strategy_parameters['target_trigger']
self.trailing_stoploss =
self.strategy_parameters['trailing_stoploss_trigger']

self.main_order = None

def initialize(self):
self.main_order = {}

@staticmethod
def name():
return 'MACD Bracket Order Strategy'
....
def strategy_exit_position(self, candle, instrument,
sideband_info):
if sideband_info['action'] == 'EXIT':
self.main_order[instrument].exit_position()
self.main_order[instrument] = None
return True

return False

The complete output is not shown here. Please visit the following link to read the complete output: https://github.com/algobulls/pyalgostrategypool/blob/master/pyalgostrategypool/strategy_macd_bracket_order.py.

How it works…

You import the necessary modules in step 1. In step 2, you create an instance of the AlgoBullsConnection class, named algobulls_connection. In step 3, you get the authorization URL using the get_authorization_url() method of the algobulls_connection object. This prints the authorization URL. You should visit this URL from your web browser to sign into the AlgoBulls platform and fetch your developer access token. (You can find more details, along with screenshots, in Appendix II on fetching a developer access token from the AlgoBulls platform.) You copy the access token and set it in step 4 using the set_access_token() method of algobulls_connection. If the token is accepted, a successful connection is set up with the AlgoBulls platform.

In step 5, you fetch all the strategies you have created and uploaded on the AlgoBulls platform so far. You use the get_all_strategies() method for this step and assign it to a new variable, all_strategies. This variable is a pandas.DataFrame object with strategyCode and strategyName columns. This table holds information on the strategy codes and the strategy names you have uploaded previously.

If you followed the MACD-Bracket-Order Strategy – uploading the strategy on the AlgoBulls trading platform recipe from Chapter 8, Algorithmic Trading Strategies – Coding Step by Step, you will find a strategy called MACD-Regular-Order strategy. In step 6, you assign the strategy code of the MACD-Regular-Order strategy to a new variable called strategy_code2. The strategy code is shown in the output of this step. This strategy code is unique for every strategy on the AlgoBulls platform.

Finally, in step 7, you ensure that the strategy being referred to by strategy_code2 is indeed the one you uploaded earlier (in the last recipe of Chapter 8Algorithmic Trading Strategies – Coding Step by Step). You use the get_strategy_details() method of the algobulls_connection object to inspect the strategy. This method takes strategy code as an argument. You pass strategy_code2 here. This method returns the entire class code as a string. You assign it to a new variable, strategy_details2, and display it.

If, you'd like to change the class code being referred to by strategy_code2, as shown in step 7, please refer to the There's more… section of the last recipe in Chapter 8, Algorithmic Trading Strategies – Coding Step by Step.

MACD–Bracket–Order strategy real trading the strategy

In this recipe, you will perform real trading on the MACD-Bracket-Order strategy. You must have fetched this strategy from your account on the AlgoBulls platform in the preceding recipe of this chapter. You will leverage the real trading functionality facilitated by pyalgotrading for this recipe, which, in turn, submits a real trading job on the AlgoBulls platform. 

Once submitted, real trading will be run by the AlgoBulls real trading engine. You can query the status anytime to find out the state of the real trading job. The job goes through the following states, in the given order: 

  • STARTING (intermediate state)
  • STARTED (stable state)
  • STOPPING (intermediate state)
  • STOPPED (stable state)

On submitting a job, it starts with an intermediate state, 'STARTING'. In this state, the AlgoBulls real trading engine fetches the strategy and get the execution environment ready, which may take a couple of minutes. Once done, the job moves to the 'STARTED' state. Strategy real trading happens in this stage. Here, it stays as long as it takes for real trading to complete. Once done, the job moves to an intermediate state, 'STOPPING'. In this state, the AlgoBulls real trading engine cleans up the resources allocated for this job, which usually takes less than a minute. Finally, the job moves to the 'STOPPED' state.

If you have already submitted a real trading job for a strategy, you cannot submit another job for the same strategy until the first job completes. This means you have to wait for the first job to move to the 'STOPPED' state. If the first job is long-running and you would like to stop it immediately, you can submit a stop job request via pyalgotrading. You need to ensure the job is in the 'STARTED' state before submitting the request. 

After submitting a real trading job, you can fetch logs and reports for the strategy execution in real time. These logs and reports help validate the strategy's performance and debug any potential issues.

You can refer to the second recipe of this chapter for the state machine diagram of a real trading job. It demonstrates the various states and transitions of a real trading job during its lifetime on the AlgoBulls platform.

Make sure you have gone through the last six recipes of Chapter 8Algorithmic Trading Strategies – Coding Step by Step, to get a complete picture of the strategy class we will be using; that is, StrategyMACDBracketOrder.

Getting ready

Make sure the algobulls_connection and strategy_code2 objects are available in your Python namespace. Refer to the preceding recipe of this chapter to set up the algobulls_connection and strategy_code2 objects.

How to do it…

Execute the following steps to complete this recipe:

  1. Import the necessary modules:
>>> from datetime import time
>>> from pyalgotrading.constants import *
  1. Search for an instrument and use its trading symbol as a keyword. Assign the returned object to instruments:
>>> instrument = algobulls_connection.search_instrument('
TATASTEEL')
>>> instrument

We got the following output (your output may differ):

[{'id': 1, 'value': 'NSE:TATASTEEL'}]
  1. Get value for the instrument of choice from instruments:
>>> instrument = instrument[0]['value']
>>> instrument

We got the following output:

'NSE:TATASTEEL'
  1. Submit a real trading job for strategy_code2:
>>> algobulls_connection.realtrade(
strategy_code=strategy_code2,
start_time=time(hour=9, minute=15),
end_time=time(hour=15, minute=30),
instrument=instrument,
lots=1,
strategy_parameters={
'fastma_period': 26,
'slowma_period': 6,
'signal_period': 9,
'target_trigger': 0.01,
'stoploss_trigger': 0.01,
'trailing_stoploss_trigger': 1
},
candle_interval=CandleInterval.MINUTES_15)

We got the following output:

Setting Strategy Config... Success.
Submitting REALTRADING job... Success.
  1. Check the status of the submitted real trading job:
>>> algobulls_connection.get_realtrading_job_status(strategy_code2)
{'data': 'STARTING'}
  1. Check the status of the submitted real trading job again after some time:
>>> algobulls_connection.get_realtrading_job_status(strategy_code2)
{'data': 'STARTED'}

How it works…

In step 1, you import the time class from the datetime module and all the constants from the pyalgotrading.constants module. In step 2, you fetch the instrument that you would like to real trade the strategy for, the MACD-Bracket-Order strategy, using the search_instrument() method of the algobulls_connection object. The search_instrument() method accepts a search string as an argument, which should be the trading symbol, in part or complete, of the instrument you are interested in. You pass 'TATASTEEL' here. This function returns a list with details of instruments that match the search string. There could be multiple instruments that could have the search string in their trading symbols. In step 3, you fetch the value of the first matched instrument and assign it to a new variable, instrument.

In step 4, you submit a real trading job using the realtrade() method of the algobulls_connection() object. It takes the following arguments:

  • strategy_code: Strategy code of the strategy for which real trading has to be performed. This should be a string. You pass strategy_code2 here.
  • start_time: Today's time when real trading should be started. This should be a datetime.time object. Here, you pass an object holding the value 9:15 hours  time(hour=9, minute=15). Refer to the first recipe of this book for details on creating a datetime object.
  • end_time: Today's time when real trading should be performed. This object should hold a time value ahead of the value held by start_time. This should be a datetime.time instance. Here, you pass an object holding the value 15:30 hours  time(hour=15, minute=30).
  • instrument: Financial instrument for which real trading should be run. Historical data will be fetched for this instrument. This should be a string. You pass instrument here.
  • lots: Number of lots for which real trading should be performed. This should be an integer. The quantity is calculated by the strategy as number of lots × lot size of the financial instrument. You pass 1 here.
  • strategy_parameters: Parameter names and values expected by the strategy. This should be a dictionary, with parameter-name and parameter-value as key-value pairs. You pass the following parameters here:
  • fastma_period: 26
  • slowma_period: 6 
  • signal_period: 9
  • target_trigger: 0.01
  • stoploss_trigger: 0.01
  • trailing_stoploss_trigger: 1

(Recall that the parameters for the MACD-Bracket-Order strategy have been defined in its __init__() method, as shown in the first recipe of Chapter 8Algorithmic Trading Strategies – Coding Step by Step).

  • candle_interval: The candle interval for the historical data fetched for real trading. This should be an enum of the CandleInterval type. You pass CandleInterval.MINUTES_15 here. (The CandleInterval enum provides various enums for candle intervals, some of which are MINUTE_1, MINUTES_3 , MINUTES_5, MINUTES_10, MINUTES_15, MINUTES_30, HOUR, and DAY.)

If the job submission is successful, you will see Success messages being printed by the realtrade() function. 

Once a job has been submitted, it takes a while to start. After starting, it may take some time to finish, depending on the duration of real trading specified using the start_time and end_time arguments. Usually, real trading is run for the entire trading day, which means the job would be running for 6-8 hours.

In step 5, you fetch the job's status using the get_realtrading_job_status() method of the algobulls_connection object. You pass strategy_code2 as the argument here. This method returns a dictionary with a single key-value pair – the data and the job status. If you query the status immediately after placing the job, you get 'STARTING' as the status. In step 6, you query the status again after some time, and if the job has started, you get a status of 'STARTED'.

A successful submission implies that the minimum inputs needed to real trade a strategy have been passed in the required format. However, this does not ensure that the strategy will run without errors. The strategy's execution may still run into errors during real trading. To debug execution issues, you will need to fetch the output logs, which will be explained in the next recipe. Possible reasons for errors could be either bugs in the strategy class' Python code or that an incomplete strategy_parameters dictionary has been passed to the realtrade() function.

There's more…

If a job is running for a long time and you would like to stop it before its completion, you can use the stop_realtrading_job() method of the algobulls_connection object. This method accepts strategy code as an argument. You pass strategy_code2 here. This method submits a stop request to the AlgoBulls real trading engine. If the request is accepted, you will see a Success message here:

>>> algobulls_connection.stop_realtrading_job(strategy_code2)
Stopping REALTRADING job... Success.

If you query the status after submitting the stop request, you'll get 'STOPPING' as the status:

>>> algobulls_connection.get_realtrading_job_status(strategy_code2)
{'data': 'STOPPING'}

If you query the status again after some time, and if the job has stopped, you'll get 'STOPPED' as the status:

>>> algobulls_connection.get_realtrading_job_status(strategy_code2)
{'data': 'STOPPED'}

MACD–Bracket–Order strategy fetching real trading logs in real time

After submitting a real trading job on the AlgoBulls platform, the AlgoBulls real trading engine starts executing the strategy. During its execution, every event that occurs and every decision that's been made by the AlgoBulls real trading engine is recorded with exact timestamps in the form of textual logs.

Examples of recorded activities include the given strategy config, every new candle generated at regular intervals, trades punched in by your strategy, the entry and exit of positions created by these trades, waits for new candles, and so on. These logs are quintessential for validating the strategy and debugging behavior or performance issues that are frequently encountered while developing a strategy.

In this recipe, you will fetch real trading logs for your strategy. The logs start coming up as soon as your submitted real trading job reaches the 'STARTED' state (refer to the preceding recipe for more information on the states of a real trading job). The AlgoBulls platform allows you to fetch logs in real time, even while the real trading job is still going on. You can get insights into the strategy's execution without having to wait for the real trading job to complete. This is helpful as real trading jobs are usually long-running. The pyalgotrading package provides a simple method we can use to fetch the execution logs for a given strategy.

Make sure you have gone through the last six recipes of Chapter 8Algorithmic Trading Strategies – Coding Step by Step, to get a complete picture of the strategy class we will be using; that is, StrategyMACDBracketOrder.

Getting ready

Make sure the algobulls_connection and strategy_code2 objects are available in your Python namespace. Refer to the MACD-Bracket-Order strategy fetching the strategy recipe of this chapter to set up the algobulls_connection and strategy_code2 objects.

How to do it…

Execute the following steps to complete this recipe:

  1. Fetch the real trading execution logs for strategy_code2:
>>> logs = algobulls_connection.get_realtrading_logs(
strategy_code2)
>>> print(logs)

We got the following output (your output may differ):

[2020-07-09 09:13:45] Logs not available yet. Please retry in sometime.
  1. Fetch the real trading execution logs for strategy_code2 again after some time:
>>> logs = algobulls_connection.get_realtrading_logs(
strategy_code2)
>>> print(logs)

We got the following output (your output may differ):

...
########################################
INITIALIZING ALGOBULLS CORE (v3.2.0)...
########################################
[2020-07-09 09:14:09] Welcome PUSHPAK MAHAVIR DAGADE!
[2020-07-09 09:14:09] Reading strategy...
[2020-07-09 09:14:09] STARTING ALGOBULLS CORE...
...
[2020-07-09 09:45:00] [CRITICAL] [order] [PLACING NEW ORDER] [2020-07-09 09:45:00][577e6b4cb646463282ae98ec1c0e6c25] [BUY] [NSE:TATASTEEL] [QTY:1] [QTY PENDING: 1] [ENTRY PRICE: 345.0] [PRICE:345.0] [TRIGGER PRICE:None] [ORDER_TYPE_BRACKET] [ORDER_CODE_INTRADAY] [ORDER_VARIETY_LIMIT] [ORDER_POSITION_ENTER] [STOPLOSS TRIGGER:341.55] [TARGET TRIGGER:348.45] [TRAILING STOPLOSS TRIGGER:345.0]
...
[2020-07-09 15:30:00] [INFO] [clock] Candle generation has been stopped...
[2020-07-09 15:30:00] [INFO] [tls] Received event END OF MARKET. Stopping Trading Core Engine...
[2020-07-09 15:30:00] [INFO] [tls] Exiting all open positions with order code: ORDER_CODE_INTRADAY (if any)...
[2020-07-09 15:30:00] [CRITICAL] [tls] [User: PUSHPAK MAHAVIR DAGADE] Trading session completed
...

The complete output is not shown here. Please visit the following link to read the complete output: https://github.com/algobulls/pyalgostrategypool/blob/master/pyalgostrategypool/sample/realtrading/strategy_macd_bracket_order/logs.txt.

How it works…

In step 1, you use the get_realtrading_logs() method of the algobulls_connection object to fetch the strategy real trading logs in real time. This method accepts strategy code as an argument. You pass strategy_code2 here. The return data is a string. If you try this step immediately after submitting the job, you get a string, which says the logs are not ready yet ([2020-07-09 09:13:45] Logs not available yet. Please retry in sometime..) This happens if the real trading job is in the 'STARTING' state.

In step 2, you fetch the logs again after some time. If the job is out of the 'STARTING' state, you start getting your strategy execution logs. You get all the real trading logs every time you call the get_realtrading_logs() function.

There's more...

Once the real trading job moves to the 'STOPPED' state, no new logs are generated. You can fetch the complete logs any time before you submit the next real trading job for the same strategy. If a new real trading job is submitted (for the same strategy), these logs will no longer be accessible via the get_realtrading_logs() method. You can save the fetched logs to a file if you'd like to refer to them at a later date.

MACD–Bracket–Order strategy fetching a real trading report  profit and loss table

After submitting a real trading job on the AlgoBulls platform, the AlgoBulls real trading engine starts executing the strategy. During its execution, along with the logs, the AlgoBulls real trading engine also generates a P&L table in real time. This table holds information on every trade punched in by the strategy. It also contains details on the mappings between entry and exit orders, the trade P&L, and the cumulative P&L, sorted chronologically, with the latest order first. This table gives us insight into the strategy's overall performance with the help of individual and cumulative P&L numbers. The entry-exit order mapping also helps validate the strategy's behavior.

In this recipe, you will fetch the P&L table report for your strategy. This report is available as soon as the first trade is punched in by your strategy after you submit a real trading job. The AlgoBulls platform allows you to fetch the P&L table in real time, even while the real trading job is still going on. You can get insights into the strategy's performance without having to wait for the real trading job to complete. This is helpful as real trading jobs are usually long-running. The pyalgotrading package provides a simple method we can use to fetch the P&L table for a given strategy.

Make sure you have gone through the last six recipes of Chapter 8, Algorithmic Trading Strategies – Coding Step by Step, to get a complete picture of the strategy class we will be using; that is, StrategyMACDBracketOrder.

Getting ready

Make sure the algobulls_connection and strategy_code2 objects are available in your Python namespace. Refer to the MACD-Bracket-Order strategy fetching the strategy recipe of this chapter to set up the algobulls_connection and strategy_code2 objects.

How to do it…

Fetch the real trading P&L report for strategy_code2:

>>> algobulls_connection.get_realtrading_report_pnl_table(strategy_code2)

We got the following output. Your output may differ (note that the following output has been split into multiple tables for representation purposes. You will see a single wide table in your Jupyter Notebook):

How it works…

In this recipe, you use the get_realtrading_report_pnl_table() method of the algobulls_connection object to fetch the real trading P&L table in real time. This method accepts strategy code as an argument. You pass strategy_code2 here. The return data is a pandas.DataFrame object with multiple columns, described as follows:

  • instrument: Financial instrument for which trade was entered.
  • entry_timestamp: The timestamp at which the entry order was placed. (Note that it may remain in the 'OPEN' state for a while before it goes to the 'COMPLETE' state.)
  • entry_transaction_type: Entry order transaction type (either BUY or SELL).
  • entry_quantity: Entry order quantity.
  • entry_price: Price at which the entry order gets executed and goes to the 'COMPLETE' state.
  • exit_timestamp: The timestamp at which the exit order was placed. (Note that it may remain in the 'OPEN' state for a while before it goes to the 'COMPLETE' state.)
  • exit_transaction_type: Exit order transaction type (either BUY or SELL).
  • exit_quantity: Exit order quantity.
  • exit_price: Price at which the exit order gets executed and goes to the 'COMPLETE' state.
  • pnl_absolute: Difference between the exit order execution price and the entry order execution price. Mathematically, this is (exit_price - entry_price)*exit_quantity for a long trade and (entry_price - exit_price)*exit_quantity for a short trade. A positive value would imply that the trade is a profit-making trade. A negative value would imply that the trade is a loss-making trade.
  • pnl_percentage: Percentage of profit or loss with respect to the entry price. Mathematically, this is pnl_absolute / entry_price / exit_quantity x 100.
  • pnl_cumulative_absolute: Cumulative profit or loss. Mathematically, this is the sum of all the pnl_absolute values of the previous trades. This number gives us direct insight into the strategy's performance against the simulation time.
  • pnl_cumulative_percentage: Percentage of cumulative profit or loss with respect to the entry price. Mathematically, this is pnl_cumulative / entry_price / exit_quantity x 100.

There's more...

Once the real trading job moves to the 'STOPPED' state, the P&L table report will not update anymore. You can fetch the complete P&L report any time before you submit the next real trading job for the same strategy. If a new real trading job is submitted (for the same strategy), this report will no longer be accessible via the get_realtrading_report_pnl_table() method. You can save the fetched report to a .csv file if you'd like to refer to it at a later date.

MACD–Bracket–Order strategy fetching a real trading report statistics table

After submitting a real trading job on the AlgoBulls platform, the AlgoBulls real trading engine starts executing the strategy. During its execution, along with the logs and P&L table, the AlgoBulls real trading engine also generates a summary from the P&L table in real time. This summary is a table of statistics containing various statistical numbers, such as Net P&L (absolute and percentage), Max Drawdown (absolute and percentage), count of total trades, winning trades, losing trades, long trades and short trades, the maximum gain and minimum gain (or maximum loss), and average profit per winning and losing trade. This table gives us an instant overview of the strategy's overall performance.

In this recipe, you will fetch the statistics table report for your strategy. This report is available as soon as the first trade is punched in by your strategy after you submit a real trading job. The AlgoBulls platform allows you to fetch the statistics table in real time, even while the real trading job is still going on. You can get insights into the strategy's performance without having to wait for the real trading job to complete. This is helpful as real trading jobs are usually long-running. The pyalgotrading package provides a simple method we can use to fetch the statistics table for a given strategy.

Make sure you have gone through the last six recipes of Chapter 8, Algorithmic Trading Strategies – Coding Step by Step, to get a complete picture of the strategy class we will be using; that is, StrategyMACDBracketOrder.

Getting ready

Make sure the algobulls_connection and strategy_code2 objects are available in your Python namespace. Refer to the MACD-Bracket-Order strategy – fetching the strategy recipe of this chapter to set up the algobulls_connection and strategy_code2 objects.

How to do it…

Fetch the real trading statistics report for strategy_code2:

>>> algobulls_connection.get_realtrading_report_statistics(strategy_code2)

We got the following output (your output may differ):

How it works…

In this recipe, you use the get_realtrading_report_statistics() method of the algobulls_connection object to fetch the real trading statistics table in real time. This method accepts strategy code as an argument. You pass strategy_code2 here. The return data is a pandas.DataFrame object with two columns – highlight_type and highlight_value – and multiple rows. The rows are described as follows:

  • Net PnL: The cumulative real trading P&L. This is also the pnl_cumulative_absolute value of the first entry in the P&L table.
  • Net PnL %: The cumulative real trading P&L percentage. This is also the pnl_cumulative_percentage value of the first entry in the P&L table.
  • Max Drawdown: The lowest value in the pnl_cumulative column of the P&L table. This indicates the maximum loss your strategy has encountered during its execution.
  • Max Drawdown %: Mathematically, this is (Max Drawdown) / (corresponding entry_price) / exit_quantity x 100.
  • Number of Trades: Total trades (entry and exit are counted as one) during the session.
  • Number of Wins: Count of trades where the trade P&L was non-negative.
  • Number of Losses: Count of trades where the trade P&L was negative.
  • Number of Long Trades: Count of trades where the entry transaction type was 'BUY'.
  • Number of Short Trades: Count of trades where the entry transaction type was 'SELL'.
  • Max Gain: P&L of the trade with the maximum P&L value among all trades.
  • Min Gain: P&L of the trade with the minimum P&L value among all trades.
  • Avg. Profit per winning trade: Mathematically, this is (Total P&L of winning trades) / (Count of winning trades).
  • Avg. Profit per losing trade: Mathematically, this is (Total P&L of losing trades) / (Count of losing trades).

There's more...

If the statistics table is fetched while the real trading job is still running, the aforementioned numbers will be intermediate numbers, based on the trades completed until that time. The numbers may change as more trades are punched in, until the real trading job completes.

Once the real trading job moves to the 'STOPPED' state, the statistics table will not change anymore. You can fetch the complete statistics table any time before you submit the next real trading job for the same strategy. If a new real trading job is submitted (for the same strategy), this table will no longer be accessible via the get_realtrading_report_statistics() method. You can save the fetched report to a .csv file if you'd like to refer to it at a later date.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset