# Unlocking 3106+% Profits Using Algorithmic Trading on 130+ Crypto Assets! — From Pine Code to Python

--

Understanding 3106+% Returns: A Deep Dive into Our Backtested Results

6th Edition of the famous Algorithmic Trading Strategies articles’ on building PROFITABLE TRADING SYSTEM. (New Strategy)

# TrendAlert: From Pine Script to Python

This article is an inspiration , taken from Tradingview indicators, mainly the “TrendAlert” by Rstraat. This indicator based on Long term (daily) en Mid term (4h) timeframes so you can enter a trade in direction of the trend at the Short term (1h) timeframe in direction of trend. You can configure the LongTerm en MidTerm timeframe to your liking. Method by Jospeh Nemeth — https://www.youtube.com/watch?v=YxDAYtlQjBM

TradingView’s Pinescript language is widely recognized for its ease in developing trading algorithms and strategies. Python, on the other hand, is a versatile language with powerful libraries that can assist in analyzing and automating trading. This article provides a guide to converting a Pinescript code into Python, specifically tailored for the freqtrade platform.

1. Understanding the Strategy Structure
2. Implementing Heiken Ashi Candlestick Calculation
3. Constructing the Trend Alert Optimization Function
4. Strategy Entry Logic in Python
5. Strategy Exit Logic in Python
6. ‘Repainting’ and issues related to Them and how we avoided it
7. Freqtarde introduction and setup
8. Backtest results, Tips to improve strategy and summary
9. Conclusion

# 1. Understanding the Strategy Structure

Before diving into the code, it’s essential to understand the structure of the strategy we are converting:

• The Heiken Ashi candlesticks are used to smooth price data to generate signals.
• Trend-based conditions using EMA (Exponential Moving Average) are employed for generating buy/sell signals.
• The strategy also incorporates volume and the ADX (Average Directional Movement Index) to confirm trend strength.

# 2. Implementing Heiken Ashi Candlestick Calculation

Heiken Ashi candlesticks are a variation of standard candlesticks that offer a smoothed view of the price action. The function `calculate_heiken_ashi` computes these values:

`def calculate_heiken_ashi(dataframe):    ha_open = (np.roll(dataframe['open'], 1) + np.roll(dataframe['close'], 1)) / 2    ha_close = (dataframe['open'] + dataframe['high'] + dataframe['low'] + dataframe['close']) / 4    ha_high = dataframe[['high', 'open', 'close']].max(axis=1)    ha_low = dataframe[['low', 'open', 'close']].min(axis=1)        ha_candles = pd.DataFrame({'open': ha_open, 'high': ha_high, 'low': ha_low, 'close': ha_close})    return ha_candles`

Key Concepts:

• Heiken Ashi Open: Average of the previous candle’s open and close.
• Heiken Ashi Close: Average of the current candle’s open, high, low, and close.
• Heiken Ashi High: Maximum of the current high, open, and close.
• Heiken Ashi Low: Minimum of the current low, open, and close.

# 3. Constructing the Trend Alert Optimization Function

The `optimize_trend_alert` function refines the trend signals:

`def calculate_heiken_ashi(dataframe):    ha_open = (np.roll(dataframe['open'], 1) + np.roll(dataframe['close'], 1)) / 2    ha_close = (dataframe['open'] + dataframe['high'] + dataframe['low'] + dataframe['close']) / 4    ha_high = dataframe[['high', 'open', 'close']].max(axis=1)    ha_low = dataframe[['low', 'open', 'close']].min(axis=1)        ha_candles = pd.DataFrame({'open': ha_open, 'high': ha_high, 'low': ha_low, 'close': ha_close})    return ha_candlesdef optimize_trend_alert(dataframe, mid_ema_mul = 4, lng_ema_mul = 16):    # Heiken Ashi calculation    ha_candles = calculate_heiken_ashi(dataframe)    current_ema = np.array(ta.EMA(dataframe['close'], timeperiod=20))    mid_term_ema = np.array(ta.EMA(dataframe['close'], timeperiod=20 * mid_ema_mul))    long_term_ema = np.array(ta.EMA(dataframe['close'], timeperiod=20 * lng_ema_mul))    # Buy and sell conditions for Heiken Ashi    MTlong1 = (ha_candles['close'] > ha_candles['open']) & (ha_candles['close'] > mid_term_ema) & (ha_candles['close'] > current_ema) & (ha_candles['close'] < 4 * mid_term_ema) & (mid_term_ema > long_term_ema)    MTshort = (ha_candles['close'] < ha_candles['open']) & (ha_candles['close'] < mid_term_ema) & (ha_candles['close'] < current_ema) & (ha_candles['close'] < 4 * mid_term_ema) & (mid_term_ema < long_term_ema)    ha_trend = np.where(MTlong1, 1, np.where(MTshort, -1, 0))        # Convert the donchian_trend tuple to an array    ha_trend = np.array(ha_trend)    dataframe['trend'] = ha_trend    return dataframe`

Key Concepts:

• Heiken Ashi candles are used to establish the primary trend.
• Multiple EMAs, including current, mid-term, and long-term, are calculated.
• Buy and sell conditions incorporate comparisons of Heiken Ashi candles with these EMAs.

You can find the whole code here https://patreon.com/pppicasso

# 4. Strategy Entry Logic in Python

The `populate_entry_trend` function specifies the conditions for entering trades:

`    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:        dataframe.loc[            (                        (dataframe['adx'] > self.adx_long_min.value) & # trend strength confirmation                        (dataframe['adx'] < self.adx_long_max.value) & # trend strength confirmation                        (dataframe['trend_l'] > 0) &                        (dataframe['volume'] > dataframe['volume_mean']) &                        (dataframe['volume'] > 0)            ),            'enter_long'] = 1        dataframe.loc[            (                        (dataframe['adx'] > self.adx_short_min.value) & # trend strength confirmation                        (dataframe['adx'] < self.adx_short_max.value) & # trend strength confirmation                        (dataframe['trend_s'] < 0) &                        (dataframe['volume'] > dataframe['volume_mean_s']) # volume weighted indicator            ),            'enter_short'] = 1                return dataframe`

Key Concepts:

• Uses the ADX to confirm the strength of a trend.
• Volume confirms the momentum behind the trend.
• Separate conditions for entering long and short trades.

# 5. Strategy Exit Logic in Python

The `populate_exit_trend` function dictates when to exit the trades:

`    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:        dataframe.loc[            (                        (dataframe['adx'] > self.adx_long_min.value) & # trend strength confirmation                        (dataframe['adx'] < self.adx_long_max.value) & # trend strength confirmation                        (dataframe['trend_l'] > 0) &                        (dataframe['volume'] > dataframe['volume_mean']) &                        (dataframe['volume'] > 0)            ),            'enter_long'] = 1        dataframe.loc[            (                        (dataframe['adx'] > self.adx_short_min.value) & # trend strength confirmation                        (dataframe['adx'] < self.adx_short_max.value) & # trend strength confirmation                        (dataframe['trend_s'] < 0) &                        (dataframe['volume'] > dataframe['volume_mean_s']) # volume weighted indicator            ),            'enter_short'] = 1                return dataframe    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:        conditions_long = []        conditions_short = []        dataframe.loc[:, 'exit_tag'] = ''        exit_long = (                (dataframe['close'] < dataframe['ema_l']) &                (dataframe['volume'] > dataframe['volume_mean_exit'])        )        exit_short = (                (dataframe['close'] > dataframe['ema_s']) &                (dataframe['volume'] > dataframe['volume_mean_exit_s'])        )        conditions_short.append(exit_short)        dataframe.loc[exit_short, 'exit_tag'] += 'exit_short'        conditions_long.append(exit_long)        dataframe.loc[exit_long, 'exit_tag'] += 'exit_long'        if conditions_long:            dataframe.loc[                reduce(lambda x, y: x | y, conditions_long),                'exit_long'] = 1        if conditions_short:            dataframe.loc[                reduce(lambda x, y: x | y, conditions_short),                'exit_short'] = 1                    return dataframe`

Key Concepts:

• Exit conditions are based on price relationships with EMAs and volume.
• Separate conditions are applied for exiting long and short trades.
• Uses Python’s `reduce` function to aggregate multiple conditions.

You can find the whole code here https://patreon.com/pppicasso

# 1. What is Repainting?

Repainting refers to when an indicator or strategy recalculates its values based on new price data and alters its historical signals or values. This means that an indicator might produce a signal (like a buy or sell) based on certain conditions, but if future price data changes those conditions, the previous signal disappears or changes.

For instance, consider an indicator that gives a buy signal whenever a candlestick is the highest in the last 10 periods. If a higher candlestick forms later, the previous buy signal could be removed and might appear on this new candlestick instead. To an observer checking the indicator in real-time, it might seem infallible, as past signals that would’ve been unprofitable seemingly never existed.

# 2. Implications of Repainting Strategies

• Misleading Backtests: Repainting can lead to very misleading backtest results. Since repainted indicators can “erase” false signals in hindsight, they may appear more accurate than they truly are in real-time trading.
• Real-time Trading Failures: While an indicator might seem perfect when viewed historically (due to repainting), its performance in real-time can be drastically different and lead to significant losses.
• Reliability Issues: Repainting undermines the trustworthiness of an indicator or strategy. If past signals can change, it’s challenging to have confidence in current signals.

# 3. How Does the Python Code Avoid Repainting?

The provided Python code establishes a trend-following strategy using Heiken Ashi candles and EMA (Exponential Moving Average) conditions. Let’s dissect how it avoids the pitfalls of repainting:

1. Fixed Heiken Ashi Calculation: The Heiken Ashi values are calculated based on fixed formulas. Once a candle is closed, its Heiken Ashi representation doesn’t change with future candles.
2. Utilization of EMAs: EMAs are lagging indicators, meaning they are based on past prices. Once a price is recorded and an EMA value is calculated, it doesn’t change. This is true for the current EMA, mid-term EMA, and long-term EMA used in the code.
3. Static Multipliers for Trends: The code establishes the long-term trend by multiplying the mid-term trend. This ensures the trend determination is based on fixed, historical data and not influenced by future price action. The line `mid_term_ema = np.array(ta.EMA(dataframe['close'], timeperiod=20 * mid_ema_mul))` showcases this, where the mid-term EMA is adjusted by a fixed multiplier. Similarly, the long-term trend EMA is set using a longer period, keeping it less sensitive to short-term price fluctuations and preventing sudden changes that might induce repainting.
4. Explicit Buy and Sell Conditions: The conditions for buy and sell signals are clear-cut and based on comparisons between Heiken Ashi values and the EMAs. Once these conditions are met and a signal is produced, it won’t be altered by subsequent price data.

# 4. Conclusion for Repainting

Repainting is a critical issue to understand and avoid when designing or selecting trading strategies. It can lead to inflated perceptions of a strategy’s accuracy and subsequent disappointments in live trading. The provided Python code offers a robust approach that remains consistent in its signals, avoiding the misleading aspects of repainting and ensuring a transparent, reliable strategy for traders.

# 7. Freqtrade Introduction and Setup Explanation:

We have covered lot of introductory topics in the 1st edition which covers all key basic concepts which I mentioned below, if you are new to “trading”, “algorithm trading”, “freqtrade” platform or “futures trading” concepts, I suggest you to open my previous articles and go through the same.

I’m here to talk about my new strategy which I was working for past few months

Introduction to algorithmic trading and its benefits

What algorithmic trading is and how it can be used in the context of crypto futures trading

Some of the benefits of using algorithmic trading for crypto futures include:

Here are some key features of the freqtrade platform:

How Leverage works and Factors to consider while using Leverage during Trades

# There are a few factors that traders should consider when deciding whether and how to use leverage:

1. Risk appetite: Traders with a higher risk appetite may be more comfortable using larger amounts of leverage, while those who are more risk-averse may prefer to use less leverage or none at all.
2. Trading strategy: Different trading strategies may be more or less suitable for leveraging, depending on the level of risk involved and the trader’s goals.
3. Market conditions: The level of leverage that is appropriate for a trade may also depend on the current market conditions, such as the level of volatility or the overall trend of the market.
4. Trading capital: Traders should also consider their available capital when deciding how much leverage to use, as they will need to have sufficient margin to cover any potential losses.

In general, it’s important for traders to carefully evaluate the potential risks and rewards of using leverage and to use it responsibly, as it can significantly impact the outcome of a trade.

1. There are lot of tutorials about how to connect Freqtrade using docker in a containerized environment. You can refer to any of the many Youtube tutorials on the same.
2. Here, Our main agenda is to show case the backtest and forward test results of the algorithm trading on freqtrade, so, I will focus on that more.
3. If there is a lot of demand and requests in comments for a tutorial on how to setup freqtrade and run your own strategies if requested, I will add that in forth coming article. Thank you

# Resources:

https://youtu.be/ASq2aeUHen8

or

https://youtu.be/PrPGKHCx5qY

or

https://youtu.be/H2OkrvSojOI

I’m giving reference only.

Backtesting is the process of simulating trades using historical market data to evaluate the performance of a trading strategy. Freqtrade includes a backtesting feature that allows users to backtest their trading strategies by specifying a range of dates and a set of market data to use in the simulation.

1. Create a configuration file: Freqtrade requires a configuration file to specify the details of your crypto futures exchange account and your desired trading parameters. To create a configuration file, copy the sample configuration file provided in the freqtrade repository to a new file called “config.json”. Then, edit the file to specify your exchange credentials and desired trading parameters.
2. Prepare your market data: Freqtrade requires a set of market data to use in the backtest. This data should be in the form of a CSV file with columns for the date, open price, high price, low price, close price, and volume of the asset being traded. You can obtain this data from a variety of sources, such as a cryptocurrency exchange or a market data provider.
3. Run the backtest: Once you have your configuration file and market data ready, you can run the backtest by executing the following command:
`freqtrade backtesting --config config.json --strategy MyStrategy --datadir data/`

Replace “MyStrategy” with the name of your strategy function and “data/” with the directory where your market data is stored. This will run the backtest using the settings specified in your configuration file and the market data provided.

1. Review the results: Once the backtest is complete, freqtrade will generate a report with information on the performance of your strategy. This report will include metrics such as the profit/loss, the number of trades executed, and the win/loss ratio of the strategy. You can use this information to evaluate the performance of your strategy and make any necessary adjustments.

You can find the whole code here https://patreon.com/pppicasso

By investing 1000 USDT, (1 USD approximately equal to 1 USDT with 1–2% variance)

for a period of 1019 days from 2021–01–06 00:00:00 up to 2023–10–22 00:00:00 (1019 days)

with maximum open trades at any given point of time being 4

maximum stake in each trade entry being around 200 USDT,

has given a Profit of 3202% Profit return on investment (ROI).

The Absolute Draw-down mentioned from results is at — 12.13%

Daily Win to Lose Ratio is at 519 days of WIN, 309 Days loss and 82 Days of Draw (Open trades which haven’t closed yet)

Average Daily profit is at3.05% per day

Daily Average Trades is 5.25 approximate

Market Returns Have been (if you buy and hold Bitcoin (BTCUSDT) for the above mentioned period the returns are mentioned here, instead of trading) — 21.24%

Time Frame used is 4h

# Key Findings from Results:

1. Profit and ROI: The trading strategy yielded a significant profit of 3106%+ return on investment (ROI) over a span of 1019 days.
2. Drawdown: The absolute drawdown reached a maximum of -12.13%, indicating relatively low risk exposure.
3. Win-Lose Ratio: The daily win-lose ratio showed 19 days of WIN, 309 Days loss and 82 Days of Draw trades.
4. Average Daily Profit: The average daily profit was calculated at 3.05%, suggesting consistent positive returns on most trading days.
5. Market Returns Comparison: The trading strategy outperformed the market, which had a return of 21.24% over the same period.
6. Time Frame: The strategy operated on a 4-hour time frame.

# Tips for Improving Strategy Performance For Algorithmic Trading:

1. Optimize Indicators: Fine-tune the parameters of indicators like ATR, EMA, and ADX to find optimal settings for the specific asset and market conditions.
2. Portfolio Diversification: Consider diversifying the portfolio by incorporating additional assets or using different strategies for various assets to reduce risk.
3. Risk Management: Adjust position sizing and risk parameters to control exposure and manage drawdowns effectively.
4. Backtesting: Thoroughly backtest the strategy over different market conditions and time periods to ensure robustness and adaptability.
5. Hyper-parameter Optimization: Use techniques like grid search or random search to optimize hyper-parameters for better performance.
6. Market Research: Stay updated with market trends, news, and events that could impact the performance of the trading strategy.
8. Regular Evaluation: Periodically review and analyze the strategy’s performance to identify areas for improvement and necessary adjustments.
9. Risk-Reward Ratio: Adjust the risk-reward ratio for trade entries and exits to optimize potential profits while minimizing losses.
10. Adaptability: Modify and adapt the strategy as market conditions change to ensure its relevance and effectiveness.

Remember that trading involves inherent risks, and there’s no guaranteed way to avoid losses. Implementing these tips can enhance the strategy’s potential, but careful risk management and continuous monitoring are essential for long-term success.

Please ensure to thoroughly test any modifications to the code on historical data and conduct proper risk assessment before deploying the strategy in a live trading environment.

# 9. Conclusion

Converting Pinescript code to Python is more than just a syntax swap. It’s about understanding the logic behind the strategy, making sure the conditions are correctly translated, and ensuring that Python’s capabilities, such as using libraries like `numpy` and `pandas`, are fully utilized.

This guide walked you through a systematic conversion process tailored for the freqtrade platform, a popular Python-based platform for trading cryptocurrencies. With these insights and the provided step-by-step translation, you can now bring any Pinescript strategy to life in Python and the freqtrade environment.

Feel free to enhance and customize the article according to your needs. This article provides an overview of the Python implementation of TrendAlert, explains each line of code, and demonstrates its application with different indicators. It also emphasizes the importance of backtesting and customization for successful trading.

It’s important to note that past performance does not guarantee future results, and continuous monitoring and optimization of the algorithm are essential to adapt to changing market conditions. Additionally, it is crucial to exercise proper risk management and conduct thorough testing before deploying the algorithm with real funds.

I hope you have found this article on Algorithmic strategy to be informative and helpful. As a creator, I am dedicated to providing valuable insights and analysis on cryptocurrency, stock market and other assets management.

If you have enjoyed this article and would like to support my ongoing efforts, I would be honored to have you as a member of my Patreon community. As a member, you will have access to exclusive content, early access to new analysis, and the opportunity to be a part of shaping the direction of my research.

Membership starts at just \$10, and you can choose to contribute on a bi-monthly basis. Your support will help me to continue to produce high-quality content and bring you the latest insights on financial analytics.

Patreon https://patreon.com/pppicasso

Regards,