Testing the trading system in PHP

    Introduction



    Probably everyone who came across trading in stocks, currencies or some other exchange instrument often met advice on the need to build and test their trading system.

    Trading according to the system seemed to me the only true way to work on the exchange, and I decided to take advice and test my trading strategy.





    At the same time, I decided to combine business with pleasure, and implement testing of a trading strategy in PHP. Why I did not use ready-made software products like TSLab , WealthLabetc.? Firstly, the very task of implementing a trading robot is quite interesting as a self-development. Secondly, most products for testing trading strategies are paid, and no one can guarantee that free analogues will not change their distribution policy in the near future. Also, I am not sure that the capabilities of third-party products are enough for my future trading strategies. Thirdly, PHP is a web-oriented language, and its development can then be used as the main module for a web service. Already these three reasons were enough for me to start work on tradeSystem.

    I must say right away that I developed the project primarily for myself, and at this stage many people will be interested not so much from a practical point of view as from an academic point of view due to the small set of implemented indicators, insufficient testing of various use cases, the presence of documentation in the form of tests and other nuances . The project is open-source, so if you find the practical application of this development appropriate, try to expand and test the functionality.

    Formalization of strategy



    Our strategy will be essentially a "hello world" strategy. It will be based on the MACD histogram .



    It is believed that when the chart of this indicator crosses the value “0” from above or below, it signals a trend change. If the intersection occurs from top to bottom, a sell signal arrives; if from the bottom up, a buy signal arrives.

    Our strategy will work on an hourly chart and at the end of each hour will check if a signal to sell or buy has appeared. The signal will be the difference in signs between the current and previous value of the indicator, or if the previous value of the indicator is equal to zero. If there is a signal and there is no paper in the portfolio, we will open a position for all the cash that we have available. When opening a position, we will place a stop loss order at the level of 1% of the price of opening a position and take profit order at a level of 2% of the opening price, with a shift from the maximum of 0.4 points.

    We would also like to take into account the commission that the broker will take at the beginning of each day.

    Ultimately, according to the results of testing, we want to get the total amount on the balance sheet, information on the maximum win and loss in a row, and the log of operations that were performed during testing.

    Implementation of a trading system and testing script



    Before starting to develop our strategy, let's install tradeSystem. The installation process is not particularly difficult and is described in the project wiki .

    For testing, we need three components: quotation data, implementation of the trading system, and a script that organizes the testing environment and displays information about the operation of the system.

    As for the quotes data, I used the export of quotes from the Finam broker website. I decided to test the system on Sberbank quotes for 2011. Despite the fact that the trading strategy makes decisions on the hourly chart, we will need to submit the data of the minute chart to the input. To save the broker's site, I put the quotes file in the project robots / testing / input directory under the name: SBER_110101_111231_1min.txt.gz. Just unzip this file, preferably in the same directory where it lies.

    Next, we need to directly implement a trading strategy. The listing of the final code can be found by opening the MACDHistogrammReverseStrategy.class.php file . The class code should be clear enough, I will only comment in general terms.

    For our strategy, we need the indicator itself, on the basis of which it works, the paper we are testing and the counter of series of wins and losses. Next, the strategy should have a handleBar method whose argument is a candle. For convenience, I have identified two more methods: canOpenPosition and openPosition, which are directly responsible for checking the possibility of opening a position and directly about opening a position.
    In the simpleHandle function, we check whether it is time to make a decision, if it is, we check whether a signal to buy or sell has appeared. If appeared, open a position. In the openPosition function, we directly open a position, put stop loss and take profit orders. Since these orders are also essentially a position tracking strategy, we wedge ourselves into the chain of strategies calling using the insertUp method. That's all, all that remains is to write a script that will read the quotation data and submit it to the input of the strategy.

    Test script



    The listing of the script can be seen in the MACDHistogrammReverse.php file . The code again should be reasonably clear, I will focus on the main points.

    After checking whether the file name with the input data was transferred, you need to connect the init file, which is responsible for initializing the working environment, and call the classesAutoloaderInit function, which initializes the class autoloader.

    Then we need to prepare our indicator, which we will pass on to the strategy. It is known that the MACD histogram is built on the basis of other indicators, so we first create the basic indicators, and gradually get to the indicator we need.

    We will entrust the calculation of new indicator values ​​to the Chart class. To do this, create it and add all our indicators to it. Now, when the handleBar Chart is called, it will cause all indicators to calculate the new indicator value. Some questions may arise regarding the need for EndStrategy and BeginStrategy, which our strategy wraps around. The main purpose of these strategies is to ensure that the newly generated strategies are correctly processed by strategies that are in the chain itself. For example, with the insertUp method that uses our strategy, TakeProfit and StopLoss strategies are inserted up the chain, but after BeginStrategy. In the absence of BeginStrategy, a situation may arise when we call the handleBar of our strategy, and the strategies higher in the chain would generally be left out of the test.

    Further, everything is very simple, we create our strategy, create an object that will subtract the commission, start reading the input data with FinamBarReader and submit it to the commission, schedule and strategy input. Also, do not forget to update the current time in DateTimeManager so that our strategy correctly processes the point in time at which a decision must be made.
    In the end, if we have an open position, we close it forcibly at the price of the last transaction and, with the final chord, display the information that interests us.

    Testing



    We will supply minute data to the input. Despite the fact that the strategy makes decisions on the hourly chart, we need to conduct testing on the minutely chart due to the TakeProfit strategy. This strategy has only candle data at the input, and should work on the expectation of the worst quote movement for it, which is the movement from the maximum to the minimum of the candle, and vice versa. For an hourly candle, this will mean too often a false positive, which in reality could not have been. Therefore, we must try to take the smallest possible period of candles for testing exactly the strategy, in this case the movement of the quote within an hour will be more accurate, and the work of the strategies will be closer to reality.

    So, we test:

    php robots/testing/MACDHistogrammReverse.php robots/testing/input/SBER_110101_111231_1min.txt > /tmp/result.txt

    We look at the result.txt file and see that according to the test results, our strategy showed four wins in a row, six losses, and in the end we had 9143 rubles left on the account, with an initial balance of 10,000 rubles. In total, the trading system conducted operations in the amount of 2 million rubles.
    For clarity, I made a graph of the distribution of balance over time.



    From it you can clearly see the behavior of the system. Basically, the system makes a series of losing trades, which is interrupted by a profitable trade. But at the same time it is clear that the profit from the transaction cannot cover the losses from the previous series of unprofitable transactions.

    Well, at least we lost a little, which is also good. However, it is believed that with real trading the results of trading strategies will be slightly worse than with testing, therefore, we can assume that the strategy will lose. If we take into account the broker's monthly commissions, which we did not take into account during our testing, and the commission for transferring marginal transactions, then the strategy clearly needs either replacement or refinement.

    That’s probably all. If anyone was interested, join the project on github , ask questions, share your developments and test your trading strategies before working on them on a real account, this will save your savings and nerves.


    Also popular now: