ストップロスとリミットを設定

このチュートリアルではストップロス(クローズ逆指値)とリミット(クローズ指値)のオーダーを行います。
以前作成したストラテジーJavaファイル(ChartUsage.java)を変更します。

まず初めに、新しいインポートを追加し、余分なインポートを削除します。
前回、IChartObjectオブジェクトに"signal-up"と"signal-down"を割り当てていましたが、
今回はより具体的なIChartDependentChartObjectオブジェクトを使用します。

このオブジェクトを使用する事で、チャートにオブジェクトを追加する時にバーに固執せずに表示する事が出来ます
(IChartObjectオブジェクトでは不可能)。




import com.dukascopy.api.drawings.IChartDependentChartObject;
import com.dukascopy.api.drawings.ITriangleChartObject;
import com.dukascopy.api.drawings.ITextChartObject;

//2. 不要なインポートを削除
//import java.awt.Font;




新しいインスタンス変数を定義します。



private int     uniqueOrderCounter   = 1;
private SMATrend previousSMADirection = SMATrend.NOT_SET;
private SMATrend currentSMADirection  = SMATrend.NOT_SET;
private Map<IOrder, Boolean> createdOrderMap = new HashMap<IOrder, Boolean>();
private int shorLineCounter;
private int textCounterOldSL;
private int textCounterNewSL;



ストップロスとリミットのオーダーをするので、ストラテジー起動時に必要な値を設定出来るようにパラメータを追加する必要があります。
breakEventPips変数はストップロスレベル変更に使用します。
pipsでこのレベルに到達した時、ストップロスオーダーのレベルはエントリー価格に設定されます
(同値撤退限定のトレーリングストップみたいなもの)。




@Configurable("ストップロス(pips)")
public int    stopLossPips   = 10;
@Configurable("リミット(pips)")
public int    takeProfitPips = 10;
@Configurable("ブレークイーブン(pips)")
public double breakEventPips = 5;



SMAトレンド状態の全てのパターンの定数を持つ列挙を定義します。




private enum SMATrend {
    UP, DOWN, NOT_SET;
}








ブレークイーブン(同値撤退トレーリングストップ)

全ての通貨ペアのtick更新時に呼び出されるonTickについて考慮する必要があります。
特定の通貨ペアだけフィルタリングするようにしなければなりません。

後でonBarメソッドにて、全ての新しいオーダーを Mapオブジェクト に追加します。
ブレークイーブンレベル到達によって既にストップロスレベルが移動しているか、Mapでオーダーを確認します。
まだ移動していない場合、含み益がbreakEventPipsパラメータよりも大きいか確認します。
含み益がブレークイーブンレベルに到達しているなら、ストップロスレベルをエントリー価格のレベルに変更する事が出来ます。

ストップロスの値がエントリー価格に設定されたら、チャート上に視覚的な三角形の変更プロセス(後述するaddBreakToChartメソッドを呼びます)を表示します。
最後に、ストップロスオーダーを変更し、マップのエントリーを更新します。

onTickメソッドの実装は以下の通りになります。

public void onTick(Instrument instrument, ITick tick) throws JFException {

    // 通貨ペアでフィルタリング
    if ( instrument != myInstrument) {
        return;
    }

    // 拡張forループ
    for ( Map.Entry<IOrder, Boolean> entry : createdOrderMap.entrySet() ) {
        IOrder   currentOrder = entry.getKey();
        boolean currentValue = entry.getValue();

        if ( currentValue == false && currentOrder.getProfitLossInPips() >= breakEventPips ) {
            printMe( currentOrder.getProfitLossInPips() + "pipsリミットのポジションのストップロスはエントリーレートに移動しました。");
            addBreakToChart( currentOrder, tick, currentOrder.getStopLossPrice(), currentOrder.getOpenPrice() );

            // ストップロス変更を表示するラインをチャートに追加
            currentOrder.setStopLossPrice( currentOrder.getOpenPrice() );
            entry.setValue( true );
        }
    }
}// onTickメソッド終了








SMAによるトレード

前回作成したonBarメソッドを変更します。
新しいオーダーをする際にSMATrend列挙を用いてチェックするようにします。
更にストップロスとリミットの設定も行います。

前回との違いは、既にポジションを持っていたとしてもそのポジションをクローズしない所です。
ストップロスやリミットに到達した時は、ポジションは自動的にクローズされます。
それと、全ての新しいオーダーは、後でonTickメソッドでチェックするのでMapに記録します。


    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {            

        // 通貨ペアと時間軸でフィルタリング
        if (!instrument.equals(myInstrument) || !period.equals(myPeriod)) {
            return; // 終了
        }

        int candlesBefore = 2, candlesAfter = 0;
        long completedBarTimeL = myOfferSide == OfferSide.ASK ? askBar.getTime() : bidBar.getTime();
        double sma[] = indicators.sma(instrument, period, myOfferSide, IIndicators.AppliedPrice.CLOSE,
                smaTimePeriod, Filter.NO_FILTER, candlesBefore, completedBarTimeL, candlesAfter);
    
        IEngine.OrderCommand myCommand = null;
        printMe( String.format("SMAの値: 2つ前 = %.5f; 1つ前 = %.5f", sma[SECOND_TO_LAST], sma[PREV]));        

        if( sma[PREV] > sma[SECOND_TO_LAST]){
            printMe("SMA上昇"); // インジケータが上昇している
            myCommand = IEngine.OrderCommand.BUY;
            currentSMADirection = SMATrend.UP;
        } else if ( sma[PREV] < sma[SECOND_TO_LAST]){
            printMe("SMA下降"); // インジケータが下降している
            myCommand = IEngine.OrderCommand.SELL;
            currentSMADirection = SMATrend.DOWN;
        } else {
            return;
        }

        double lastTickBid           = history.getLastTick(myInstrument).getBid();
        double lastTickAsk           = history.getLastTick(myInstrument).getAsk();
        double stopLossValueForLong  = myInstrument.getPipValue() * stopLossPips;
        double stopLossValueForShort = myInstrument.getPipValue() * takeProfitPips;
        double stopLossPrice   = myCommand.isLong() ? (lastTickBid - stopLossValueForLong ) : (lastTickAsk + stopLossValueForLong);
        double takeProfitPrice = myCommand.isLong() ? (lastTickBid + stopLossValueForShort) : (lastTickAsk - stopLossValueForShort);

        // SMAトレンドが変わったら、新しいオーダーを行う
        if ( currentSMADirection != previousSMADirection ) {
            previousSMADirection = currentSMADirection;
            IOrder newOrder      = engine.submitOrder("MyStrategyOrder" + uniqueOrderCounter++, instrument, myCommand,
                                                       0.001, 0, 1, stopLossPrice, takeProfitPrice);
            createdOrderMap.put(newOrder, false);
    
            if( openedChart == null ){
                return;
            }

            long   time  = bidBar.getTime() + myPeriod.getInterval(); // ISignalDownChartObjectを現在のバーに描画する
            double space = myInstrument.getPipValue() * 2;            // ISignalDownChartObject用にバーの上限のマージンを設定する

            IChartDependentChartObject signal = myCommand.isLong()
                    ? factory.createSignalUp(  "signalUpKey"   + signals++, time, bidBar.getLow()  - space)
                    : factory.createSignalDown("signalDownKey" + signals++, time, bidBar.getHigh() + space);

            signal.setStickToCandleTimeEnabled(false);
            signal.setText("MyStrategyOrder" + (uniqueOrderCounter - 1));
            openedChart.addToMainChart(signal);
        }
    
    } // onBarメソッド終了








チャートにインジケータ追加

addToChartメソッドを変更し、チャートのチェックは新しい(checkChart)メソッドで行います。



    private boolean addToChart(IChart chart){
        if ( !checkChart(chart) ) {
            return false;
        }

        chart.addIndicator(indicators.getIndicator("SMA"), new Object[] {smaTimePeriod},
                new Color[]{Color.BLUE}, new DrawingStyle[]{DrawingStyle.LINE}, new int[]{3});

        if(addOHLC){
    
            IOhlcChartObject ohlc = null;
            for (IChartObject obj : chart.getAll()) {
                if (obj instanceof IOhlcChartObject) {
                    ohlc = (IOhlcChartObject) obj;
                }
            }
    
            if (ohlc == null) {
                ohlc = chart.getChartObjectFactory().createOhlcInformer();
                ohlc.setPreferredSize(new Dimension(100, 200));
                chart.addToMainChart(ohlc);
            }
    
            // OHLCインデックスを表示
            ohlc.setShowIndicatorInfo(true);
        }
        return true;
    }// addToChartメソッドの終了



チャートをチェックするメソッド:



private boolean checkChart(IChart chart) {
    if (chart == null ) {
        printMeError( myInstrument + " のチャートが開かれていません");
        return false;
    }
    if (chart.getSelectedOfferSide() != this.myOfferSide) {
        printMeError( "チャートのオーダータイプ(アスク/ビッド)と一致していません:" + this.myOfferSide);
        return false;
    }
    if (chart.getSelectedPeriod() != this.myPeriod) {
        printMeError(this.myPeriod + "の時間軸チャートが開かれていません。");
        return false;
    }
    if (chart.getFilter() != this.filter) {
        printMeError("chart filter is not " + this.filter);
        return false;
    }
    return true;
}




チャート上にブレークイーブントライアングルをプロット

チャート上のストップロス変更を視覚的に表示するaddBreakToChartメソッドを実装します。
このメソッドはストップロスオーダーが変更されたら、チャート上に三角形のオブジェクトを追加します。
緑の三角形はロングポジションのストップロス変更で、赤い三角形はショートポジションのストップロス変更を表しています。

この三角形は新しいオーダーを行った時に開始し、ストップロス変更時が終点です。
古いストップロスと新しいストップロスの値をテキストで三角形の所に表示します。



private void addBreakToChart(IOrder changedOrder, ITick tick, double oldSL, double newSL) throws JFException {
    if ( openedChart == null ) {
        return;
    }

    ITriangleChartObject orderSLTriangle = factory.createTriangle("Triangle " + shorLineCounter++,
            changedOrder.getFillTime(), changedOrder.getOpenPrice(), tick.getTime(), oldSL, tick.getTime(), newSL);

    Color lineColor = oldSL > newSL ? Color.RED : Color.GREEN;
    orderSLTriangle.setColor(lineColor);
    orderSLTriangle.setLineStyle(LineStyle.SOLID);
    orderSLTriangle.setLineWidth(1);
    orderSLTriangle.setStickToCandleTimeEnabled(false);
    openedChart.addToMainChart(orderSLTriangle);

    // テキスト描画
    String breakTextOldSL       = String.format(" Old SL: %.5f", oldSL);
    String breakTextNewSL       = String.format(" New SL: %.5f", newSL);
    double textVerticalPosition = oldSL > newSL ? newSL - myInstrument.getPipValue() : newSL + myInstrument.getPipValue();
    ITextChartObject textOldSL   = factory.createText("textKey1" + textCounterOldSL++, tick.getTime(), oldSL);
    ITextChartObject textNewSL   = factory.createText("textKey2" + textCounterNewSL++, tick.getTime(), newSL);

    textOldSL.setText(breakTextOldSL);
    textNewSL.setText(breakTextNewSL);
    textOldSL.setStickToCandleTimeEnabled(false);
    textNewSL.setStickToCandleTimeEnabled(false);
    openedChart.addToMainChart(textOldSL);
    openedChart.addToMainChart(textNewSL);
}



サンプルソースコード:StopLossStrategy.java
ストップロスの詳細については、ストップロス価格の設定の項目参照。






ストラテジーのテスト

次のパラメータ設定でテストを行います。


緑矢印はロングオーダー時に、赤矢印はショートオーダー時に作成されます。
三角形の右側には、ストップロス変更時に古いストップレベルと新しいストップレベルが表示されます。
三角形の左端はオーダー時のレベルになります。ストップレベル変更時に目で追い易くなります。









スポンサーリンク

スポンサーリンク
検索
リファレンスツリー


Copyright ©2016 JForexAPIで自動売買させ隊! All Rights Reserved.


Top

inserted by FC2 system