All About Trading!

Share this post

Coding & Trading Psychological Levels in Python.

abouttrading.substack.com

Coding & Trading Psychological Levels in Python.

Let's Create a Strategy Based on Forecasting Market Reactions Close to Psychological Levels.

Sofien Kaabar, CFA
Sep 9, 2021
Share this post

Coding & Trading Psychological Levels in Python.

abouttrading.substack.com

Detecting support & resistance levels is a highly subjective field of analysis and this explains the complete discrepancy between results. However, it should not be this way because we have many ways of making the subjective part rather objective. We can do this in many ways, among them are psychological levels, an interesting phenomenon based on human psychology and anchoring. In this article, we will present the concept of psychological levels, code them in Python, and then evaluate a simple strategy based on them.

I have just published a new book after the success of my previous one “New Technical Indicators in Python”. It features a more complete description and addition of structured trading strategies with a Github page dedicated to the continuously updated code. If you feel that this interests you, feel free to visit the below link, or if you prefer to buy the PDF version, you could contact me on Linkedin.

The Book of Trading Strategies
Amazon.com: The Book of Trading Strategies: 9798532885707: Kaabar, Sofien: Bookswww.amazon.com

Introduction to Support & Resistance Levels

At its purest form, a support level is an area supposed to keep prices from going down further. Naturally, when the market price approaches a support area, the right decision is to have a bullish bias.

EURUSD hourly values showing 1.2175 acting as resistance before it turned support.

A resistance level is an area supposed to keep prices from going up further. Naturally, when the market price approaches a resistance area, the right decision is to have a bearish bias.

USDCHF hourly values showing 0.8960 acting as a support level.

By subscribing, you are supporting me and unlocking all of the articles that deal with trading, back-testing, and strategy research. As for consistency, you can expect between 4-7 articles per week.

Introduction to Psychological Levels

Psychological levels form an important part in any analysis. The reason for this is because mentally, they are given more attention than other levels. For instance, which price would you retain more in your mind if you come across it? 1.1500 on the EURUSD or 1.3279 on the GBPUSD? By Psychological Levels, we are talking about either round numbers (such as 1.2000 on the EURUSD) or simply par numbers (such as 1.000 USDCHF or $100 on Apple stock).

Clearly, round numbers are the first part of a psychological price. The other part is simply significance. For example, the par-value or par-level such as 1.000 on the USDCHF or 100.00 on the USDJPY is considered a par-level. The basic idea is that around these levels, market participants may choose to place their orders, hence, a form of reaction may happen.

EURGBP with the psychological levels 0.8500 support and 0.8700 resistance.

Our aim is to develop an algorithm that trades whenever the market reaches a psychological level. This is done using a very simple loop function in Python discussed later.

Creating a Strategy Based on Psychological Levels

Our main goal is to create an algorithm that loops around the historical data and identifies the psychological closing prices which can be {1.2900, 0.7500, 1.0000, 1.5100}. For this we need to tell the algorithm to:

  • Perform a general loop across all data in the fourth column which harbors the closing prices.

  • Mark the times when there is a closing price ending in a hundred pips position such as 1.1000 or 2.300.

  • Increase the interval by 100 pips (0.0100) each time so that we scan for all possible levels.

The Python syntax to do this can be written down as follows.

def psychological_levels_scanner(Data, close, where):
    
    # Adding buy and sell columns
    Data = adder(Data, 10)
    
    # Rounding for ease of use
    Data = rounding(Data, 4)
    
    # Threshold
    level     = 1.00
    
    # Scanning for Psychological Levels
    for i in range(len(Data)):
        
        for i in range(len(Data)):
            
            if Data[i, close] == level:
                    
                Data[i, where] = 1
                
        level = round(level + 0.01, 2)
        if level > 5:
            break
    
    return Data

# You can choose your starting level. To be sure you will get all the psychological levels, you can start at zero
    

As with any proper research method, the aim is to test the strategy and to be able to see for ourselves whether it is worth having as an add-on to our pre-existing trading framework or not.

The first step is creating the trading rules. When will the system buy and when will it go short? In other words, when is the signal given that tells the system that the current market will go up or down?

The trading conditions we can choose are:

  • A buy (Long) signal is triggered whenever the market has closed at a round level while the previous closing prices have been above it.

  • A sell (Short) signal is triggered whenever the market has closed at a round level while the previous closing prices have been below it.

def signal(Data, close, psychological_col, buy, sell):

    for i in range(len(Data)):
        
        if Data[i, psychological_col] == 1 and Data[i, close] < Data[i - 1, close] and \
           Data[i, close] < Data[i - 2, close] and \
           Data[i, close] < Data[i - 3, close] and \
           Data[i, close] < Data[i - 4, close]:
               
               Data[i, buy] = 1

        elif Data[i, psychological_col] == 1 and Data[i, close] > Data[i - 1, close] and \
           Data[i, close] > Data[i - 2, close] and \
           Data[i, close] > Data[i - 3, close] and \
           Data[i, close] > Data[i - 4, close]:
               
               Data[i, sell] = -1
               
    return Data
Signal chart.

The above chart shows the values on the EURUSD through the hourly time frame. The green arrows show the bullish opportunities identified by the algorithm while the red arrows show the bearish opportunities identified by the algorithm.

Signal chart.

Some markets will have rare signals but this does not hinder the quality. The above example shows the GBPUSD hourly values. We can see that in the last 500 trading hours, we only had two signals which were pretty good. Remember, we are looking for short-term reactions.

Evaluating the Strategy

Having had the signals, we now know when the algorithm would have placed its buy and sell orders, meaning, that we have an approximate replica of the past where can can control our decisions with no hindsight bias. We have to simulate how the strategy would have done given our conditions. This means that we need to calculate the returns and analyze the performance metrics. Let us see a neutral metric that can give us somewhat a clue on the predictability of the indicator or the strategy. For this study, we will use the Signal Quality metric.

The signal quality is a metric that resembles a fixed holding period strategy. It is simply the reaction of the market after a specified time period following the signal. Generally, when trading, we tend to use a variable period where we open the positions and close out when we get a signal on the other direction or when we get stopped out (either positively or negatively).

Sometimes, we close out at random time periods. Therefore, the signal quality is a very simple measure that assumes a fixed holding period and then checks the market level at that time point to compare it with the entry level. In other words, it measures market timing by checking the reaction of the market.

def signal_quality(Data, closing, buy, sell, period, where):
    
    Data = adder(Data, 1)
    
    for i in range(len(Data)):
        try:
            
            if Data[i, buy] == 1:
                
                Data[i + period, where] = Data[i + period, closing] - Data[i, closing] 
            if Data[i, sell] == -1:
                
                Data[i + period, where] = Data[i, closing] - Data[i + period, closing]
        except IndexError:
            pass           
    return Data

my_data = signal_quality(my_data, 3, 6, 7, 21, 8)

positives = my_data[my_data[:, 8] > 0]
negatives = my_data[my_data[:, 8] < 0]

signal_quality = len(positives) / (len(negatives) + len(positives))
print('Signal Quality = ', round(signal_quality * 100, 2), '%')

# Output Signal Quality EURUSD = 53.82%
# Output Signal Quality USDCHF = 54.55%
# Output Signal Quality GBPUSD = 51.67%

With the most basic parameters and no optimization, we were able to obtain better than random signal quality (Above 50%). The strategy shows potential and in a later article, we will see how to combine it with technical indicators. Make sure to subscribe so you do not miss anything!

Signal chart.

If you are also interested by more technical indicators and using Python to create strategies, then my best-selling book on Technical Indicators may interest you:

New Technical Indicators in Python
Amazon.com: New Technical Indicators in Python: 9798711128861: Kaabar, Mr Sofien: Bookswww.amazon.com

Conclusion

Remember to always do your back-tests. You should always believe that other people are wrong. My indicators and style of trading may work for me but maybe not for you.

I am a firm believer of not spoon-feeding. I have learnt by doing and not by copying. You should get the idea, the function, the intuition, the conditions of the strategy, and then elaborate (an even better) one yourself so that you back-test and improve it before deciding to take it live or to eliminate it. My choice of not providing specific Back-testing results should lead the reader to explore more herself the strategy and work on it more.

To sum up, are the strategies I provide realistic? Yes, but only by optimizing the environment (robust algorithm, low costs, honest broker, proper risk management, and order management). Are the strategies provided only for the sole use of trading? No, it is to stimulate brainstorming and getting more trading ideas as we are all sick of hearing about an oversold RSI as a reason to go short or a resistance being surpassed as a reason to go long. I am trying to introduce a new field called Objective Technical Analysis where we use hard data to judge our techniques rather than rely on outdated classical methods.

Share All About Trading!

Share this post

Coding & Trading Psychological Levels in Python.

abouttrading.substack.com
Comments
TopNewCommunity

No posts

Ready for more?

© 2023 Sofien Kaabar
Privacy ∙ Terms ∙ Collection notice
Start WritingGet the app
Substack is the home for great writing