無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

Typeを作ってみた。

前に構想した「Type」機能をちょっと実装してみました。Typeの生成とチェックAPIのみ。コンテナにはまだ組み込んでいません。あとテストも途中までしかできてないです。

こんな感じで使います。

// テスト用モデル
var TestObject = function(){}
TestObject.prototype = {
    A: function(){},
    B: function(){},
    C: function(){}
};
var TestObject2 = function(){}
TestObject2.prototype = {
    B: function(){},
    C: function(){}
};
var obj  = new TestObject();
var obj2 = new TestObject2();

var assert = YAHOO.util.Assert;

// ユーテイリティへの参照
var t = container.types;

// メソッドA,Bを持つType
var type = t.has( "C", "A" );

// isImplementor() でオブジェクトが指定されたメソッドを持つか評価する。
assert.isTrue( type.isImplementor(obj) );
assert.isFalse( type.isImplementor(obj2) );

// メソッドA,またはCを持つType
type = t.hasAny( "C", /A/ ); // 正規表現も指定できる。また、引数の数に制限はない。

assert.isTrue( type.isImplementor(obj) );
assert.isTrue( type.isImplementor(obj2) );

// Typeのネストも可能
type = t.has(
    "C",
    t.hasAny( "A", /X/)
);
assert.isTrue( type.isImplementor(obj) );
assert.isFalse( type.isImplementor(obj2) );

type = t.hasAny(
    "C",
    t.has( "A", /X/)
);
assert.isTrue( type.isImplementor(obj) );
assert.isTrue( type.isImplementor(obj2) );
  • container.typesで定義されたユーティリティAPIを利用して作成する。
  • has()で「指定された引数の条件のメソッドをすべて持つオブジェクトにマッチするType」を生成。
  • hasAny()で「指定された引数の条件のメソッドのいずれかを持つオブジェクトにマッチするType」を生成する。
  • has(),hasAny()の引数では「文字列」「正規表現」「Type」のいずれかを指定できる。
    • 文字列の場合、同名のメソッドを持つことが条件となる。
    • 正規表現の場合、それとマッチするメソッドを持つことが条件となる。
    • Typeが渡せるので、条件のネストも可能。
  • 引数の数に制限はない。

実装

container.jsより抜粋。クラス構成は検索条件とかでよく見るヤツです。

/**
 * タイプ
 */
container.Type = function() {}
container.Type.prototype = {

    /**
     * 同じタイプであるか評価します。
     * @param {container.Type} that タイプ
     * @return 同じであればtrue
     */
    equals: function( that ) {},

    /**
     * オブジェクトがTypeの条件を満たすか評価します。
     * @param {Object} obj オブジェクト
     * @return 条件を満たす場合true
     */
    isImplementor: function( obj ) {}
}

/**
 * ユーテイリティ
 */
container.types =  {

    /**
     * 指定されたメソッドをすべて実装することを示すTypeを生成する。
     * @param {String or Regexp or container.Type} methods メソッド名、正規表現またはcontainer.Type
     * @return 指定されたメソッドをすべて実装することを示すcontainer.Type
     */
    has: function() {
        return new container.inner.types.And( container.types._createTypes( arguments ));
    },
    /**
     * 指定されたメソッドのいずれかを実装することを示すTypeを生成する。
     * @param {String or Regexp or container.Type} methods メソッド名、正規表現またはcontainer.Type
     * @return 指定されたメソッドのいずれかを実装することを示すcontainer.Type
     */
    hasAny: function() {
        return new container.inner.types.Or( container.types._createTypes( arguments ));
    },

    /**
     * 指定された型の条件を満たさないことを示すTypeを生成する。
     * @param {Type} type Type
     * @return 指定された型の条件を満たさないことを示すType
     */
    not: function( type ) {
        return new container.inner.types.Not( container.types._createType(type) );
    },

    _createTypes: function ( list ) {
        var types = [];
        for ( var i=0; i < list.length; i++ ) {
        	types.push( container.types._createType( list[i] ));
        }
        return types;
    },
    _createType: function ( item ) {
        if ( item instanceof RegExp ) {
            return new container.inner.types.RegexpMethod(item);
        } else if ( item instanceof container.Type ) {
            return  item ;
        } else if ( typeof item == "string"  ) {
            return  new container.inner.types.Method(item);
        } else {
            throw "illegal argument.";
        }
    }
}

container.inner.types = {}

/**
 * 完全一致
 */
container.inner.types.Method = function( name ) {
    this.name = name;
}
container.inner.types.Method.prototype = new container.Type();
container.inner.types.Method.prototype.equals = function( that ) {
    if ( !that || !( that instanceof container.inner.types.Method ) ){
        return false;
    }
    return this.name == that.name;
}
container.inner.types.Method.prototype.isImplementor = function( obj ) {
    return typeof obj[this.name] == "function";
}

/**
 * 正規表現一致
 */
container.inner.types.RegexpMethod = function( exp ) {
    this.exp = exp;
}
container.inner.types.RegexpMethod.prototype = new container.Type();
container.inner.types.RegexpMethod.prototype.equals = function( that ) {
    if ( !that || !( that instanceof container.inner.types.RegexpMethod ) ){
        return false;
    }
    return this.exp.ignoreCase == that.exp.ignoreCase
        && this.exp.global  == that.exp.global
        && this.exp.source == that.exp.source;
}
container.inner.types.RegexpMethod.prototype.isImplementor = function( obj ) {
    for ( var key in obj ) {
        if ( typeof obj[key] == "function" && this.exp.test( key ) ) {
            return true;
        }
    }
    return false;
}

/**
 * And
 */
container.inner.types.And = function(types) {
    this.types = types;
}
container.inner.types.And.prototype = new container.Type();
container.inner.types.And.prototype.equals = function( that ) {
    if ( !that || !( that instanceof container.inner.types.And ) ){
        return false;
    }
    if ( this.types.length != that.types.length ){
        return false;
    }
    for ( var i=0; i < this.types.length; i++ ) {
        var a = this.types[i];
        var b = that.types[i];
        if ( !a.equals(b) ) { return false; }
    }
    return true;
}
container.inner.types.And.prototype.isImplementor = function( obj ) {
    for ( var i=0; i < this.types.length; i++ ) {
        if ( !this.types[i].isImplementor(obj)) {
            return false;
        }
    }
    return true;
}

/**
 * Or
 */
container.inner.types.Or = function(types) {
    this.types = types;
}
container.inner.types.Or.prototype = new container.Type();
container.inner.types.Or.prototype.equals = function( that ) {
    if ( !that || !( that instanceof container.inner.types.Or ) ){
        return false;
    }
    if ( this.types.length != that.types.length ){
        return false;
    }
    for ( var i=0; i < this.types.length; i++ ) {
        var a = this.types[i];
        var b = that.types[i];
        if ( !a.equals(b) ) { return false; }
    }
    return true;
}
container.inner.types.Or.prototype.isImplementor = function( obj ) {
    for ( var i=0; i < this.types.length; i++ ) {
        if ( this.types[i].isImplementor(obj)) {
            return true;
        }
    }
    return false;
}

/**
 * Not
 */
container.inner.types.Not = function(type) {
    this.type = type;
}
container.inner.types.Not.prototype = new container.Type();
container.inner.types.Not.prototype.equals = function( that ) {
    if ( !that || !( that instanceof container.inner.types.Not ) ){
        return false;
    }
    return this.type.equals( that.type );
}
container.inner.types.Not.prototype.isImplementor = function( obj ) {
    return  !this.type.isImplementor(obj);
}

テストケース

テストケースも一応。NotとTypeのネストのテストが未。

var TypeTest = new YAHOO.tool.TestCase({

    name: "TypeTest",

    setUp: function () {},
    tearDown: function () {},

    /**
     * container.types.has()のテスト。
     */
    testHas: function () {
        var assert = YAHOO.util.Assert;
        var t = container.types;

        var TestObject = function(){}
        TestObject.prototype = {
            A: function(){},
            B: function(){},
            C: function(){},
            hoo:  function(){},
            X: "",
            Y: 1
        };
        var TestObject2 = function(){}
        TestObject2.prototype = {
            B: function(){},
            C: function(){},
            foo:  function(){},
            X: "",
            Y: 1
        };

        var obj  = new TestObject();
        var obj2 = new TestObject2();

        var type = t.has( "A" );
        assert.isTrue(  type.isImplementor(obj) );
        assert.isFalse( type.isImplementor(obj2) );

        type = t.has( "C" );
        assert.isTrue( type.isImplementor(obj) );
        assert.isTrue( type.isImplementor(obj2) );

        type = t.has( "X" );
        assert.isFalse( type.isImplementor(obj) );
        assert.isFalse( type.isImplementor(obj2) );

        type = t.has( /A/ );
        assert.isTrue( type.isImplementor(obj) );
        assert.isFalse( type.isImplementor(obj2) );

        type = t.has( /[a-zA-z]oo/ );
        assert.isTrue( type.isImplementor(obj) );
        assert.isTrue( type.isImplementor(obj2) );

        type = t.has( /[a-zA-z]ooo/ );
        assert.isFalse( type.isImplementor(obj) );
        assert.isFalse( type.isImplementor(obj2) );

        assert.isTrue(  t.has( "A" ).equals(t.has( "A" )) );
        assert.isFalse( t.has( "A" ).equals(t.has( "B" )) );
        assert.isFalse( t.has( "A" ).equals(t.has( /A/ )) );

        assert.isTrue(  t.has( /A/ ).equals(t.has( /A/ )) );
        assert.isFalse( t.has( /A/ ).equals(t.has( /B/ )) );
        assert.isFalse( t.has( /A/ ).equals(t.has( "A" )) );


        type = t.has( "C", /B/ );
        assert.isTrue( type.isImplementor(obj) );
        assert.isTrue( type.isImplementor(obj2) );

        type = t.has( /[a-zA-z]oo/, "A", "B" );
        assert.isTrue( type.isImplementor(obj) );
        assert.isFalse( type.isImplementor(obj2) );

        assert.isTrue(  type.equals(t.has( /[a-zA-z]oo/, "A", "B" )) );
        assert.isFalse( type.equals(t.has( /[a-zA-z]oo/, "X", "B" )) );
        assert.isFalse( type.equals(t.has( /[a-zA-z]oo/, "B" )) );
        assert.isFalse( type.equals(t.has( "B" )) );
        assert.isFalse( type.equals(t.has( /A/ )) );

        assert.isFalse(  type.equals(t.hasAny( /[a-zA-z]oo/, "A", "B" )) );
    },

    /**
     * container.types.hasAny()のテスト。
     */
    testHasAny: function () {
        var assert = YAHOO.util.Assert;
        var t = container.types;

        var TestObject = function(){}
        TestObject.prototype = {
            A: function(){},
            B: function(){},
            C: function(){},
            hoo:  function(){},
            X: "",
            Y: 1
        };
        var TestObject2 = function(){}
        TestObject2.prototype = {
            B: function(){},
            C: function(){},
            foo:  function(){},
            X: "",
            Y: 1
        };

        var obj  = new TestObject();
        var obj2 = new TestObject2();

        var type = t.hasAny( "A" );
        assert.isTrue(  type.isImplementor(obj) );
        assert.isFalse( type.isImplementor(obj2) );

        type = t.hasAny( "C" );
        assert.isTrue( type.isImplementor(obj) );
        assert.isTrue( type.isImplementor(obj2) );

        type = t.hasAny( "X" );
        assert.isFalse( type.isImplementor(obj) );
        assert.isFalse( type.isImplementor(obj2) );

        type = t.hasAny( /A/ );
        assert.isTrue( type.isImplementor(obj) );
        assert.isFalse( type.isImplementor(obj2) );

        type = t.hasAny( /[a-zA-z]oo/ );
        assert.isTrue( type.isImplementor(obj) );
        assert.isTrue( type.isImplementor(obj2) );

        type = t.hasAny( /[a-zA-z]ooo/ );
        assert.isFalse( type.isImplementor(obj) );
        assert.isFalse( type.isImplementor(obj2) );

        assert.isTrue(  t.hasAny( "A" ).equals(t.hasAny( "A" )) );
        assert.isFalse( t.hasAny( "A" ).equals(t.hasAny( "B" )) );
        assert.isFalse( t.hasAny( "A" ).equals(t.hasAny( /A/ )) );

        assert.isTrue(  t.hasAny( /A/ ).equals(t.hasAny( /A/ )) );
        assert.isFalse( t.hasAny( /A/ ).equals(t.hasAny( /B/ )) );
        assert.isFalse( t.hasAny( /A/ ).equals(t.hasAny( "A" )) );


        type = t.hasAny( "C", /B/ );
        assert.isTrue( type.isImplementor(obj) );
        assert.isTrue( type.isImplementor(obj2) );

        type = t.hasAny( /X/, "A", "Y" );
        assert.isTrue( type.isImplementor(obj) );
        assert.isFalse( type.isImplementor(obj2) );

        type = t.hasAny( /[a-zA-z]oo/, "A", "B" );
        assert.isTrue( type.isImplementor(obj) );
        assert.isTrue( type.isImplementor(obj2) );

        assert.isTrue(  type.equals(t.hasAny( /[a-zA-z]oo/, "A", "B" )) );
        assert.isFalse( type.equals(t.hasAny( /[a-zA-z]oo/, "X", "B" )) );
        assert.isFalse( type.equals(t.hasAny( /[a-zA-z]oo/, "B" )) );
        assert.isFalse( type.equals(t.hasAny( "B" )) );
        assert.isFalse( type.equals(t.hasAny( /A/ )) );

        assert.isFalse(  type.equals(t.has( /[a-zA-z]oo/, "A", "B" )) );

    },

    testBasic : function() {
        var TestObject = function(){}
        TestObject.prototype = {
            A: function(){},
            B: function(){},
            C: function(){}
        };
        var TestObject2 = function(){}
        TestObject2.prototype = {
            B: function(){},
            C: function(){}
        };
        var obj  = new TestObject();
        var obj2 = new TestObject2();

        var assert = YAHOO.util.Assert;

        // ユーテイリティへの参照
        var t = container.types;

        // メソッドA,Bを持つType
        var type = t.has( "C", "A" );

        // isImplementor() でオブジェクトが指定されたメソッドを持つか評価する。
        assert.isTrue( type.isImplementor(obj) );
        assert.isFalse( type.isImplementor(obj2) );

        // メソッドA,またはCを持つType
        type = t.hasAny( "C", /A/ ); // 正規表現も指定できる。また、引数の数に制限はない。

        assert.isTrue( type.isImplementor(obj) );
        assert.isTrue( type.isImplementor(obj2) );

        // Typeのネストも可能
        type = t.has(
            "C",
            t.hasAny( "A", /X/)
        );
        assert.isTrue( type.isImplementor(obj) );
        assert.isFalse( type.isImplementor(obj2) );

        type = t.hasAny(
            "C",
            t.has( "A", /X/)
        );
        assert.isTrue( type.isImplementor(obj) );
        assert.isTrue( type.isImplementor(obj2) );

    }
});