タートルトレーディング戦略は、1980年代にリチャード・デニスとウィリアム・エックハートによって開発されたクラシックなトレンドフォローアプローチです。この戦略は、定義された期間内の市場の最高価格と最安値を追跡することで、エントリーポイントとエグジットポイントを特定します。長期的なトレンドを捉え、持続的な価格変動から利益を得ることを目的としています。

タートルトレーディング戦略の起源

リチャード・デニスは1970年代の伝説的な先物トレーダーで、わずか数千ドルをわずか数年で3億5000万ドルにまで増やしたとされています。デニスは、取引は生まれつきの才能ではなく、学ぶことができるスキルであると信じていました。その証明として、彼は友人のウィリアム・エックハートと「普通の人々をトレーダーとして成功させることができる」という賭けをしました。

デニスはさまざまなバックグラウンドを持つ24人を「タートル」と呼び、2週間の集中的なトレーニングプログラムを提供しました。トレーニングを終え、評価に合格した後、各タートルは資本を与えられ、250,000ドルから2百万ドルの範囲で取引を行いました。その後5年間で、彼らのアカウントは合計で1億7500万ドルに成長しました。

この実験後、デニスは自らが使用したトレーニングシステムを公開し、それがタートルトレーディング戦略として知られるようになりました。この戦略は量的取引の初期の例の一つであり、感情的または主観的な意思決定に対するシステマティックアプローチの力を示しました。

取引ルール

タートルトレーディング戦略はリスク管理を強調しており、これは現代の量的取引に大きな影響を与えました。以下は戦略の主要な要素です:

  1. 市場選択
    この戦略は、十分な流動性とボラティリティを持つ市場、例えば株式、先物、外国為替などで最も効果的です。選ばれた取引対象は活発に取引され、エントリーやエグジットが容易であるべきです。
  2. エントリールール
    タートルはブレイクアウトシステムを使用して取引の開始時期を決定しました:
    • 価格が過去N日間の最高値を超えると買いシグナルが発生します(通常20日間)。
    • 価格が過去N日間の最安値を下回ると売りシグナルが発生します。
  3. ポジションサイズ
    タートルトレーディングは固定リスクモデルを使用してポジションサイズを決定します。通常、1回の取引でのリスクは総資本の特定の割合(例:2%)に制限されます。ポジションサイズは、現在の価格とボラティリティに基づいて計算され、リスクが設定された制限内で管理されます。
  4. ストップロスルール
    リスク管理は戦略の中心です。ストップロスは各取引の開始時に設定され、通常は過去N日間(例:10日または20日)の高値/安値に置かれます。取引が有利な方向に進むと、ストップロスレベルを調整して利益を確定し、ダウンサイドを制限することができます。
  5. エグジットルール
    戦略は事前定義された利益目標を使用して取引を終了します。価格が目標に達した時点でポジションはクローズされます。これらの目標は、市場のボラティリティや特定の戦略目標に基づいてカスタマイズできます。
  6. シグナルフィルタリング
    誤ったシグナルを避けるために、追加のテクニカル指標を使用して確認を行うことができます。例えば、移動平均や相対力指数(RSI)などです。これにより、取引の質が向上し、ノイズを減少させることができます。
  7. バックテストと最適化
    戦略を本番環境で使用する前に、過去のデータでバックテストを行うことが推奨されます。バックテストは、戦略のパフォーマンスを評価し、現在の市場条件に合わせてパラメータを洗練させるために役立ちます。

タートルトレーディング戦略は証明された影響力のあるシステムですが、欠点もあります。範囲取引やトレンドのない市場ではパフォーマンスが低下し、大きなドローダウンが発生する可能性があります。そのため、厳格なリスク管理と規律ある実行が成功の鍵です。

最後に、特定のパラメーターやルールは、個々の好み、リスク許容度、市場の状態に応じて異なる場合があります。戦略を効果的に適応させるためには、カスタマイズと継続的な最適化が重要です。

Javaコード例

import java.util.List;

public class TurtleTradingStrategy {
    public static void main(String[] args) {
        List<Double> prices = 
        int breakoutPeriod = 20; 

        double highestHigh = Double.MIN_VALUE;
        double lowestLow = Double.MAX_VALUE;
        boolean inMarket = false; 
        double entryPrice = 0.0; 

        for (double price : prices) {

            if (price > highestHigh) {
                highestHigh = price;
            }
            if (price < lowestLow) {
                lowestLow = price;
            }

            if (!inMarket && price > highestHigh) {

                inMarket = true;
                entryPrice = price;

            } else if (inMarket && price < lowestLow) {

                inMarket = false;

            }


            if (prices.indexOf(price) >= breakoutPeriod) {
                double previousPrice = prices.get(prices.indexOf(price) - breakoutPeriod);
                if (previousPrice == highestHigh) {

                    highestHigh = calculateHighestHigh(prices, prices.indexOf(price) - breakoutPeriod + 1, prices.indexOf(price));
                }
                if (previousPrice == lowestLow) {

                    lowestLow = calculateLowestLow(prices, prices.indexOf(price) - breakoutPeriod + 1, prices.indexOf(price));
                }
            }
        }
    }

    private static double calculateHighestHigh(List<Double> prices, int startIndex, int endIndex) {
        double highestHigh = Double.MIN_VALUE;
        for (int i = startIndex; i <= endIndex; i++) {
            double price = prices.get(i);
            if (price > highestHigh) {
                highestHigh = price;
            }
        }
        return highestHigh;
    }

    private static double calculateLowestLow(List<Double> prices, int startIndex, int endIndex) {
        double lowestLow = Double.MAX_VALUE;
        for (int i = startIndex; i <= endIndex; i++) {
            double price = prices.get(i);
            if (price < lowestLow) {
                lowestLow = price;
            }
        }
        return lowestLow;
    }
}

Pythonコード例

def turtle_trading_strategy(prices, breakout_period=20, risk_percentage=0.02):
    highest_high = float('-inf')
    lowest_low = float('inf')
    in_market = False
    entry_price = 0.0

    for price in prices:
        if price > highest_high:
            highest_high = price
        if price < lowest_low:
            lowest_low = price

        if not in_market and price > highest_high:
            in_market = True
            entry_price = price


        elif in_market and price < lowest_low:

            in_market = False



        if prices.index(price) >= breakout_period:
            previous_prices = prices[prices.index(price) - breakout_period:prices.index(price)]
            previous_highest_high = max(previous_prices)
            previous_lowest_low = min(previous_prices)
            if previous_highest_high == highest_high:

                highest_high = calculate_highest_high(prices, prices.index(price) - breakout_period + 1, prices.index(price))
            if previous_lowest_low == lowest_low:

                lowest_low = calculate_lowest_low(prices, prices.index(price) - breakout_period + 1, prices.index(price))

def calculate_highest_high(prices, start_index, end_index):
    highest_high = float('-inf')
    for i in range(start_index, end_index + 1):
        price = prices[i]
        if price > highest_high:
            highest_high = price
    return highest_high

def calculate_lowest_low(prices, start_index, end_index):
    lowest_low = float('inf')
    for i in range(start_index, end_index + 1):
        price = prices[i]
        if price < lowest_low:
            lowest_low = price
    return lowest_low