データフィード

このセクションでは、同じストラテジーロジックを使って、10分バーから蓮子2pipsバー(または30秒のカスタムバー)へフィードデータ型を変更します。
異なるデータフィードで動作するストラテジーを作成するには、IFeedListenerインターフェースを実装したクラスを作成する必要があります。
このクラスはIFeedListener.onFeedDataメソッドを実装する必要があります。
このメソッドはフィードデータを受信する度に呼び出されます。

サンプルコードの例は、以前作成したStopLossStrategy.javaを変更します。



フィードタイプの宣言

以下インポートを追加します。




import com.dukascopy.api.IIndicators.AppliedPrice;
import com.dukascopy.api.feed.IFeedDescriptor;
import com.dukascopy.api.feed.IFeedListener;
import com.dukascopy.api.feed.util.RenkoFeedDescriptor;
import com.dukascopy.api.feed.util.TimePeriodAggregationFeedDescriptor;



フィードデータを取得するIFeedListenerインターフェースを実装する必要があります。
IStrategyインターフェースが実装されている同じクラスにIFeedListenerインターフェースを実装します。




public class Feeds implements IStrategy, IFeedListener {
    // クラスの実装
}



コード内で複数のデータフィードタイプを使用している場合、使用している通貨ペア、オーダータイプ、価格期間、時間軸をフィード登録する必要があります。
これらの値は全てIFeedDescriptor要素から取得出来ます。
フィードタイプに応じて、今まで使用していた同じ役割の変数をIFeedDescriptorメソッドから呼ばれる変数に置換します。
なので、myInstrumentとmyOfferSideとmyPeriodのパラメータは削除します。
この例では、ストラテジー起動時に2種類のフィードタイプのどちらかを選択出来るようにするので、新しいパラメータを追加します。
ユーザーが選択したフィードを登録する必要があります。
その為、新しいenum型を宣言します。

このenum型は定数のIFeedDescriptor変数(final修飾子付き変数)の為のコンストラクタを持っています。
これにより、選択されたデータフィード(通貨ペア、時間軸等)についての情報を取得するenum(FeedType)のコンストラクタを使う事が出来ます。




@Configurable("フィードタイプ")
public FeedType myFeed = FeedType.RENKO_2_PIPS_EURGBP_BID;

public enum FeedType {

    // 列挙の定義
    RENKO_2_PIPS_EURGBP_BID (  new RenkoFeedDescriptor(Instrument.EURGBP, PriceRange.TWO_PIPS, OfferSide.BID)),
    TIME_BAR_30_SEC_EURGBP_BID (new TimePeriodAggregationFeedDescriptor(Instrument.EURGBP, Period.THIRTY_SECS,
                                OfferSide.BID, Filter.WEEKENDS));

    // フィールド変数
    private final IFeedDescriptor feedDescriptor;

    // コンストラクタ
    FeedType(IFeedDescriptor feedDescriptor) {
        this.feedDescriptor = feedDescriptor;
    }

    // Getメソッド
    public IFeedDescriptor getFeedDescriptor(){
        return feedDescriptor;
    }      
}








フィードの登録

onStartメソッドで、指定されたフィードタイプを登録します。
フィード登録のコードを追加します。



    public void onStart(IContext context) throws JFException {
        this.engine        = context.getEngine();
        this.console       = context.getConsole();
        this.history       = context.getHistory();
        this.context       = context;
        this.indicators    = context.getIndicators();
        this.userInterface = context.getUserInterface();
        this.openedChart = context.getChart(myFeed.getFeedDescriptor().getInstrument());
        this.factory     = openedChart.getChartObjectFactory();

        Set<Instrument> instruments = new HashSet<Instrument>();
        instruments.add(myFeed.getFeedDescriptor().getInstrument());
        context.setSubscribedInstruments(instruments, true);

        if( drawSMA ) {
            if( !addToChart(openedChart) ){
                printMeError("チャート上にインジケータをプロット出来ませんでした。チャートの設定値を確認して下さい。");
            }
        }

        // フィード登録
        context.subscribeToFeed(myFeed.getFeedDescriptor(), this);

    } // onStartメソッド終了









IFeedListenerインターフェースの実装

前回onBarメソッドに書いたコードを全てonFeedDataメソッドに移動します。
データフィードを使用しているので、onBarメソッドで実行する必要が無くなりました。
新しいデータを受信する度にロジックを実行するようにします。
IFeedListenerインターフェース実装する為に必要なデータを取得しまう。
このインターフェースはonFeedDataメソッドの為だけに宣言されます。
前回作成したストラテジーとの違いは、IFeedDescriptorオブジェクトから取得して通貨ペアとオーダータイプの値です。

メソッドの一部(例えば、IIndicators.calculateIndicator等)をJFExceptionに投げるので、コードは全てをtry-catchブロックに入れます。
IBarオブジェクトはITimedDataオブジェクト(IBarインタフェースはITimedDataインターフェースの拡張)をダウンキャストして受け取ります。
IFeedDescriptorオブジェクトを使用しているので、IIndicators.smaメソッドの代わりにIIndicators.calculateIndicatorメソッドを使っています、 その為、インジケータのフィードは少し異なる方法で検索します。





    @Override
    public void onFeedData(IFeedDescriptor feedDescriptor, ITimedData feedData) {

        Instrument myInstrument = feedDescriptor.getInstrument();
        OfferSide myOfferSide = feedDescriptor.getOfferSide();

        try {
            if ( !(feedData instanceof IBar) ) {
                printMeError("ティックフィードデータは使えません。");
                return;
            }

            IBar bar = (IBar) feedData;

            int  candlesBefore = 2, candlesAfter = 0;
            long completedBarTimeL = bar.getTime();

            Object[] smaObjectsFeed = indicators.calculateIndicator(feedDescriptor, new OfferSide[]{myOfferSide}, "SMA",
                                         new AppliedPrice[]{AppliedPrice.CLOSE}, new Object[]{smaTimePeriod}, candlesBefore, 
                                         feedData.getTime(), candlesAfter);
            double[] sma = (double[]) smaObjectsFeed[0]; // sma has just 1 output            


            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++, myInstrument, myCommand, 
                                                           0.001, 0, 1, stopLossPrice, takeProfitPrice);
                createdOrderMap.put(newOrder, false);
    
                if( openedChart == null ){
                    return;
                }

                // IFeedDescriptorオブジェクトから現在の時間軸を取得
                long   time  = history.getFeedData(feedDescriptor, 0).getTime(); // 現在のバーにISignalDownChartObjectを描画する為の時間
                double space = myInstrument.getPipValue() * 2; // ISignalDownChartObjectの為に、バーの上または下にマージンを設ける
                IChartDependentChartObject signal = myCommand.isLong()
                        ? factory.createSignalUp(  "signalUpKey"   + signals++, time, bar.getLow()  - space)
                        : factory.createSignalDown("signalDownKey" + signals++, time, bar.getHigh() + space);

                signal.setText("MyStrategyOrder" + (uniqueOrderCounter - 1));
                openedChart.addToMainChart(signal);
            }
        } catch (Exception e) {

        }

    }



onBarメソッドの中身は空っぽのまま残っています。




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








チャートチェックメソッドの変更

チャートチェックメソッドでは、通貨ペアとオーダータイプオブジェクトの取得方法を置換します。
代わりにIFeedDescriptorオブジェクトを使用します。
チャートチェックメソッドのロジックもまた、前回作成したソースから少し異なった方法に変更します。
データフィードのタイプに応じてチャートをチェックする必要があります。



    private boolean checkChart(IChart chart) {
        if (chart == null ) {
            printMeError( myFeed.getFeedDescriptor().getInstrument() + " のチャートが開かれていません。" );
            return false;
        }
        if (chart.getSelectedOfferSide() != myFeed.getFeedDescriptor().getOfferSide()) {
            printMeError( myFeed.getFeedDescriptor().getOfferSide() + "のオーダータイプのチャートが開かれていません。" );
            return false;
        }

        if (chart.getFeedDescriptor().getDataType() == DataType.RENKO) {
            if (chart.getPriceRange() != myFeed.getFeedDescriptor().getPriceRange()) {
                printMeError(myFeed.getFeedDescriptor().getPriceRange() + "の価格期間のチャートが開かれていません。" );
                return false;
            }
        } else if (chart.getFeedDescriptor().getDataType() == DataType.TIME_PERIOD_AGGREGATION) {
            if (chart.getSelectedPeriod() != myFeed.getFeedDescriptor().getPeriod()) {
                printMeError( myFeed.getFeedDescriptor().getPeriod() + "の時間軸のチャートが開かれていません。" );
                return false;
            }
        }

        if (chart.getFilter() != this.filter) {
            printMeError( this.filter + "のチャートフィルターではありません " );
            return false;
        }
        return true;
    }



サンプルソースコード:Feeds.java






ストラテジーのテスト

この例では30秒足と2pips価格期間を使います。
ストラテジーを起動する前に、パラメータで指定する期間のチャートを開く必要があります。
チャートに新しい期間の選択を追加するには、

"ツール" ⇒ "オプション設定"を選択します。


オプション設定のウインドウが開いたら、"期間"クリックします。


30秒足を追加するには、"時間ベースの期間"のラジオボタンをクリックします。
"Units"で"Sec"を選択し、"タイム・フレーム"で"30秒"を選択し、ウインドウ中央の  ボタンをクリックします。





蓮子2pips足を追加するには、"価格ベースの期間"のラジオボタンをクリックします。
"種類"で"練行足"を選択し、"数量"で"2 ピップス"を選択し、ウインドウ中央の  ボタンをクリックします。










蓮子フィードでのテスト

蓮子2pipsのテストを行うには以下のパラメータ設定でストラテジーを起動します。




蓮子2pipsフィードタイプでの結果です。
SMAインジケータとロング/ショートオーダーがチャートに追加されている事が分かります。








カスタム時間足でのテスト

30秒足のテストを行うには以下のパラメータ設定でストラテジーを起動します。




30秒足フィードタイプでの結果です。






スポンサーリンク

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


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


Top

inserted by FC2 system