How to Build and Backtest Low‑Frequency Trading Strategies in Python

This article introduces two low‑frequency Python trading strategies—a grid‑based price‑difference approach and an intraday T‑strategy—explains their implementation on the RiceQuant platform, provides sample code, and presents back‑testing results that demonstrate their performance and practical considerations.

Python Crawling & Data Mining
Python Crawling & Data Mining
Python Crawling & Data Mining
How to Build and Backtest Low‑Frequency Trading Strategies in Python

1. Introduction

Hello, I am Snowball. In this article I share Python‑based implementations of stock‑trading functionalities. If you are unfamiliar with stock or derivative trading but interested, you can look up related material yourself.

I will introduce the ideas and source code for several common trading strategies. Quantitative trading involves repeatedly buying and selling stocks, cryptocurrencies, or derivatives as prices fluctuate, aiming to reduce holding costs and maximize returns.

Common strategies include trend, grid, scalping, probabilistic rules, high‑frequency trading, etc. Here I focus on two low‑frequency strategies: a high‑low grid (price‑difference) strategy and an intraday T strategy. For more complex strategies you can search online; I recommend the RiceQuant platform for reference.

2. Requirement Analysis & Implementation Idea

Each trading day a stock moves up or down. To monitor price changes or automate trades, existing broker software often offers paid robot strategies. I propose two approaches:

Use an existing quant platform to write and backtest strategies, then execute them via the broker.

Develop custom code to monitor valuations and handle price movements according to specific needs.

The first approach is low‑cost but limited by the platform; the second costs more but offers full control.

3. Using an Existing Quant Platform for Strategy Development and Backtesting

Using RiceQuant, you first register an account, then create strategies in the platform’s editor. The platform only supports Python scripts.

1) Price‑Difference (Grid) Trading Strategy

Platform screenshot:

Partial code (full code can be obtained later):

# 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新

def handle_bar(context, bar_dict):
    ...
    if newPrice >= context.nextSellPrice:
        logger.info("执行高抛交易,对应价格:{}".format(newPrice))
        amount = context.portfolio.positions[context.s1].quantity
        if amount >= context.tradeNumber:
            logger.info("执行高抛交易,对应数量:{}".format(context.tradeNumber))
            order_shares(context.s1, -context.tradeNumber)
            plot("S", newPrice)
        elif amount >= 100:
            logger.info("执行高抛交易,对应数量:{}".format(amount))
            order_shares(context.s1, -amount)
            plot("S", newPrice)
        calc_next_trade_price(context, newPrice)
        obj = {
            "nextSellPrice": context.nextSellPrice,
            "nextBuyPrice": context.nextBuyPrice,
            "curTradePrice": context.curTradePrice
        }
        context.buyTradeList.append(obj)
    if newPrice <= context.nextBuyPrice:
        logger.info("执行低吸交易,对应价格:{}".format(newPrice))
        amount = int(context.portfolio.cash / newPrice / 100.0) * 100
        if amount >= context.tradeNumber:
            logger.info("执行低吸交易,对应数量:{}".format(context.tradeNumber))
            order_shares(context.s1, context.tradeNumber)
            plot("B", newPrice)
        calc_next_trade_price(context, newPrice)
        obj = {
            "nextSellPrice": context.nextSellPrice,
            "nextBuyPrice": context.nextBuyPrice,
            "curTradePrice": context.curTradePrice
        }
        context.sellTradeList.append(obj)

Select a back‑testing period and run the simulation. The result for China Merchants Bank (stock 600036) shows a sell trigger at +8% and a buy trigger at –8%, with a maximum of three consecutive buy actions.

Backtest profit: 13.628%

Annualized profit: 17.096%

Compared with a benchmark annual return of –6%, the strategy significantly reduces holding cost during price swings. Adjusting parameters can control trade frequency, especially when price movements are large.

2) Intraday T Strategy

Partial code:

# 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新

def handle_bar(context, bar_dict):
    ...
    newPrice = bar_dict[context.s1].last
    if newPrice >= context.nextSellPrice:
        context.lastTradeType = 1
        logger.info("执行高抛交易,对应价格:{}".format(newPrice))
        amount = context.portfolio.positions[context.s1].quantity
        if amount - context.tradeNumber >= 0:
            logger.info("执行高抛交易,对应数量:{}".format(context.tradeNumber))
            order_shares(context.s1, -context.tradeNumber)
            plot("S", newPrice)
        else:
            logger.info("股票数量不足,无法执行高抛交易,对应数量:{}".format(amount))
            return
        calc_next_trade_price(context, newPrice)
        obj = {
            "nextSellPrice": context.nextSellPrice,
            "nextBuyPrice": context.nextBuyPrice,
            "curTradePrice": context.curTradePrice
        }
        context.buyTradeList.append(obj)
    if newPrice <= context.nextBuyPrice:
        context.lastTradeType = 0
        logger.info("执行低吸交易,对应价格:{}".format(newPrice))
        amount = int(context.portfolio.cash / newPrice / 100.0) * 100
        if amount >= context.tradeNumber:
            logger.info("执行低吸交易,对应数量:{}".format(context.tradeNumber))
            order_shares(context.s1, context.tradeNumber)
            plot("B", newPrice)
        else:
            logger.info("现金不足,无法执行低吸交易,对应数量:{}".format(amount))
            return
        calc_next_trade_price(context, newPrice)
        obj = {
            "nextSellPrice": context.nextSellPrice,
            "nextBuyPrice": context.nextBuyPrice,
            "curTradePrice": context.curTradePrice
        }
        context.sellTradeList.append(obj)

The logic is straightforward: sell when price rises 2% and buy when it falls 2%, using 70% of initial capital for buying and locking at least 50% of the position. Back‑testing results are:

Backtest profit: 5.501%

Annualized profit: 6.839%

Benchmark profit: 19.26%

The intraday T (high‑frequency) strategy yields modest long‑term returns and is more suitable for short‑term price movements.

4. Conclusion

I am Snowball. The RiceQuant platform makes it easy to backtest strategies, though its real‑time monitoring and custom logic features are limited and many functions require payment. This article demonstrates how to use Python on an existing quant platform to develop and backtest strategies, hoping to aid your learning.

Pythonquantitative tradingbacktestingAlgorithmic TradingGrid StrategyIntraday T Strategy
Python Crawling & Data Mining
Written by

Python Crawling & Data Mining

Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.