Quantitative trading turtle strategy

Quantitative trading turtle strategy

The code is only guaranteed to run on ricequant

I will not focus on the turtle strategy here. If you are interested, you can buy a book and read it yourself.

The following is what I transported, and I have bolded the key points.

1. The Turtle Trading Act

The Turtle Trading Law is a well-known public trading system, popularized by the famous commodity speculator Richard Dennis in a trader training class in 1983, and it covers all aspects of the trading system. Its laws cover all aspects of trading and leave no room for traders to make subjective decisions. It has all the components of a complete trading system.

Renowned commodity speculator Richard Dennis wanted to figure out whether great traders were born or nurtured. To this end, in 1983 he recruited 13 people and taught them the basic concepts of futures trading, as well as his own trading methods and principles. "The trainees are called 'turtles' (Mr Dennis said he had just returned from Asia when the programme started and he explained what he said to others, 'We are growing into traders, just like in Singapore they are growing into Turtles')." --Stanley W. Angrist, The Wall Street Journal, September 5, 1989.
The Turtles became the most famous experiment in trading history, as the Turtles earned an average of 80% compounded annually over the next four years. Dennis proved that with a simple set of systems and rules, people with little or no trading experience can become good traders. At the time, the Turtles held Richard Dennis responsible for agreeing not to reveal the rules even after their negotiated 10-year nondisclosure agreement ended in 1993. However, there are individual turtles who make money by selling turtle trading rules on the site. The two original Turtles, Curtis Faith and Arthur Maddock, decided to make the Turtle Trading Rules freely available on their website in order to stop individual Turtles from stealing intellectual property and selling the Turtle Trading Rules to make money.

The turtle trading strategy is a very complete set of trend-following automated trading strategies. This complex strategy has been designed in detail in various aspects such as entry conditions, position control, capital management, stop loss and profit, which can basically be used as a template for the design and development of complex trading strategies.

2. Capture of trend signals

In the capture of trend signals, the Turtle Trading Rule uses a very important technical indicator - the Donchian channel. This channel is very similar to Bollinger Bands, but it is slightly different in the specific calculation method.

The Donchian Channel indicator was invented by Richard Donchian and consists of 3 curves of different colors. The indicator uses the highest price in the period (usually 20, which can be changed in some platform system settings, while others cannot). and the lowest price to show the volatility of the market price. When the channel is narrow, it means that the market volatility is small; otherwise, the channel is wide and the market volatility is relatively large.

When the price breaks through the upper track of the channel, it is a possible buy signal; conversely, when the price breaks through the lower track, it is a possible sell signal. The calculation methods of various indicators of the Tangqi'an Channel are:

Upper rail = Max (highest and low, n), the maximum value of the highest price of n days
Lower rail = Min (lowest price, n), the minimum value of the lowest price of n days
Middle rail = (upper rail + lower rail)/2

Within the framework of multi-factor analysis in the financial sector, this strategy's prediction of price movements after a breakout is based on the assumption of validity of the momentum factor. Of course, the validity of this factor has indeed been rigorously verified, and as a supplement to the Fama-French three-factor model, it is widely used in financial markets.

Of course, we can optimize and use more reasonable trend breakout indicators.

3. Trading Principles

So, since the momentum factor is a publicly available and commonly used factor, why does the Turtle Trading Rule stand out? The answer is very simple. The Turtle Trading Rules define a set of very strict rules for position control, take profit and stop loss. For the sharp rise and fall of the currency market, the turtle trading rule is a weapon to deal with this extreme market. Let's analyze them one by one.

  1. The base unit of the position N

The principle of adding a position in the Turtle Rule is to define a small unit (Unit) so that the expected value fluctuation of the position corresponds to 1% of the total net assets. That is to say, if you buy this small unit of assets, the market value of the position will not change by more than 1% of the total net assets on that day.

So, how to define this small unit? How to estimate the value fluctuation that this small unit can bring? First, in estimating the value fluctuation brought by this small unit (the value fluctuation is called N), the turtle strategy uses a statistical method of historical price fluctuations. The specific calculation formula is as follows:

**TrueRange=Max(High−Low, High−PreClose, PreClose−Low)
N = (sum of N values ​​in the previous 19 days + TrueRange at that time)/20**

Among them, High represents the highest price of the day, Low represents the lowest price of the day, and PreClose represents the closing price of the previous day.

We can see from the definition that the value of N is indeed a good representation of the recent volatility of the asset in price.

In this way, a Unit should be calculated like this:
Unit = (1%*Total_net)/N, total_net is the total net asset value
It can be seen that the price fluctuation range of a Unit's assets = 1% of the total net assets

  1. When to open a position

The action of opening a position comes from the generation of a trend breakout signal. If the current price breaks through the upper track, a buy signal is generated, and if the current price falls below the lower track, a short position signal is generated (if the market supports short selling, some digital asset markets support borrowing Short selling!)
Initial position size = 1 Unit

  1. when to add

If the open bottom position is a long position and the price of the asset has increased by 0.5N on the basis of the previous position (or increase), add a long position of Unit;
if the open bottom position is a short position and the price of the asset On the basis of the last time the position was opened (or added), it fell by 0.5N, and a short position of Unit was added.
We can see that the turtle strategy is actually a strategy of chasing up and down.

  1. How to do dynamic stop loss

If the open bottom position is a long position and the price of the asset has dropped by 2N on the basis of the last position (or increase), sell all positions to stop loss;
if the open bottom position is a short position and the price of the asset is above On the basis of opening a position (or adding a position) once, it has risen by 2N, and then buy cover all positions and stop loss.
Of course, users can customize the dynamic stop loss plan. For example, if the position drops by 0.5N, it will start to partially close the position, instead of waiting for the 2N drop to clear the position in a hurry. After all, the impact cost is there.

  1. How to do take profit, can you customize dynamic take profit?

In the Turtle Rule, the take profit signal is generated as follows:
if the open bottom position is a long position and the current asset price falls below the lower rail of the 10-day Tang Qi'an Channel, then all positions are cleared to end the strategy;
if the open bottom position is a short position and The current asset price rises above the upper track of the 10-day Tangchi'an Channel, and all positions are cleared to end the strategy.
Of course, users can customize the dynamic take profit plan, such as total net assets/initial net assets > 1.5, take profit and leave the market.

The following is the code I have implemented. Compared with the conventional turtle strategy, I have added a strategy of screening stocks before each opening, and I will only operate on the stocks with the largest market capitalization.

The effect is ok, it ran past the CSI 300 index :)

# 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。
import numpy as np
import pandas as pd
import talib
import math

# 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。
def init(context):
    # 在context中保存全局变量
    context.s = []
    context.vis = {}
    context.last_buy_price = {} 
    #上一次买入价格
    context.hold_flag = {}
    #False 
    #是否持有头寸标志,即是否买入
    context.limit_unit = 4 
    #最多买入单元数
    context.unit = {}#0 
    #现在买入一单元股数
    context.add_time = {}#0 
    #买入次数 最多四次
    context.long_time = 55
    context.short_time = 20
    context.ten_time = 10

def CalcATR(high,low,close):
    TR_List = []
    for i in range(1,min(21,len(high),len(close))):
        TR = max(high[i]-low[i],abs(high[i]-close[i-1]),abs(close[i-1]-low[i]))
        TR_List.append(TR)
    ATR = np.array(TR_List).mean()
    return ATR

def CalcUnit(perValue,ATR):#计算unit

    return int((perValue/ATR)/100)*30
    # 乘了个系数,莽

def IN_OR_OUT(high,low,price): #判断入场还是离场
    up = max(high)
    down = min(low) 
    if price>up:
        return 1
    elif price<down:
        return -1
    else:
        return 0 

def Add_OR_Stop(price,lastprice,ATR):
    if price >= lastprice + 0.5*ATR:
        return 1
    elif price <= lastprice - 0.5*ATR:
        return -1
    else:
        return 0    

# before_trading此函数会在每天策略交易开始前被调用,当天只会被调用一次
# 选股策略,选三个满足特征的几个,然后来进行排序
def before_trading(context): # 获得stock list
    num_stocks = 5
    fundamental_df = get_fundamentals(
        query(
            fundamentals.eod_derivative_indicator.pb_ratio,
            fundamentals.eod_derivative_indicator.pe_ratio,
            fundamentals.eod_derivative_indicator.peg_ratio,
        )
        .filter(
            fundamentals.eod_derivative_indicator.pe_ratio<60
        )
        .filter(
            fundamentals.eod_derivative_indicator.pb_ratio<5
        )
        .filter(
            fundamentals.eod_derivative_indicator.peg_ratio<0.9
        )
        .order_by(
            fundamentals.eod_derivative_indicator.market_cap.desc()
        ).limit(
            num_stocks
        )
    )
    '''
    fundamental_df = get_fundamentals(
        query(
            fundamentals.eod_derivative_indicator.market_cap
        ).filter(
            fundamentals.eod_derivative_indicator.market_cap<5e10
        ).order_by(
            fundamentals.eod_derivative_indicator.market_cap.asc()   
        ).limit(
            num_stocks
        )
    )
    '''
    drop_list = []
    for stock in context.s:
        if context.add_time.get(stock,0) == 0:
            drop_list.append(stock)
    for stock in drop_list:
        init_stock(context,stock)
    if len(context.s) < 20:
        for stock in fundamental_df:
            if stock not in context.vis:
                context.s.append(stock)
                context.vis[stock] = 1
    logger.info(str(context.s))


# 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新
def handle_bar(context, bar_dict):
    # 开始编写你的主要的算法逻辑
    stock_list = []
    for stock in context.s:
        stock_list.append(stock)
    for stock in stock_list:
        do_trade(context,stock)

def init_stock(context,stock):
    context.s.remove(stock)
    if stock in context.last_buy_price:
        del context.last_buy_price[stock]
    if stock in context.hold_flag:
        del context.hold_flag[stock]
    if stock in context.unit:
        del context.unit[stock] 
    if stock in context.add_time:
        del context.add_time[stock]
    if stock in context.vis:
        del context.vis[stock]

def do_trade(context,stock):
    high_price = history_bars(stock,context.short_time+1, '1d', 'high')
    low_price = history_bars(stock,context.short_time+1, '1d', 'low')
    close_price = history_bars(stock,context.short_time+2, '1d', 'close')
    close_price_atr = close_price[:-1]

    high_price_55 = history_bars(stock,context.long_time+1, '1d', 'high')
    low_price_55 = history_bars(stock,context.long_time+1, '1d', 'low')
    high_price_10 = history_bars(stock,context.ten_time+1, '1d', 'high')
    low_price_10 = history_bars(stock,context.ten_time+1, '1d', 'low')
    price_minute = history_bars(stock,context.short_time,'1m','close')
    price = price_minute[-1] #股票最新价格
    # 计算ATR
    ATR = CalcATR(high_price,low_price,close_price_atr)
    out = IN_OR_OUT(high_price_55,low_price_55,price) #判断入场还是离场

    if out==1 and context.hold_flag.get(stock,False)==False: #入场
        value = context.portfolio.cash*0.01  # 我的资金的1%
        context.unit[stock] = CalcUnit(value,ATR)
        order_shares(stock, context.unit[stock])
        context.add_time[stock]=1
        context.hold_flag[stock]=True
        context.last_buy_price[stock]=price
    elif out==-1 and context.hold_flag.get(stock,False) ==True: #离场
        order_percent(stock,-1)
        init_stock(context,stock) #重新初始化

    #判断加仓还是止损
    if context.hold_flag.get(stock,False)==True :
        temp = Add_OR_Stop(price,context.last_buy_price.get(stock,0),ATR)
        if temp==1 and context.add_time.get(stock,4) < context.limit_unit:#加仓
            order_shares(stock,context.unit[stock])
            context.last_buy_price[stock]=price
            context.add_time[stock]+=1
        elif temp==-1:
            if context.add_time.get(stock,0) == 1:
                order_percent(stock,-1)
                init_stock(context,stock)
            else:
                order_shares(stock,context.unit.get(stock,0))
                context.add_time[stock]-=1


# after_trading函数会在每天交易结束后被调用,当天只会被调用一次
def after_trading(context):
    pass

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324488367&siteId=291194637