またろうのシストレブログ

マネックス証券が提供しているトレードステーションと、MT4などシストレ関連について色々書きます。株と自動売買、EasyLanguageについても。

シストレ応援キャンペーンですって奥様



トレードステーションの自動売買で5回取引すると、7月の3週間取引手数料が無料になるそうです。

f:id:tsukinowaapp:20180619054805p:plain

info.monex.co.jp

1株から買えるETF株で5回実行すれば、条件はすぐ達成できそうなので
この機会にやってみては?

ちなみに新規にトレステの口座を開設した場合は、
口座開設日の翌営業日から翌々月末まで取引手数料が無料だったりします。

info.monex.co.jp

EasyLanguageの言語仕様 その3


Close[n]は配列ではない?

ストラテジーやインジケーターのソースを見ると、Close[1]みたいな記述を見かけるかと思います。
他の言語では、一般的に配列を示しますが
EasyLanguageに限って言えば、やや意味合いが異なります。

f:id:tsukinowaapp:20180618141317p:plain


トレステのEasyLanguageでは、変数に[n]を付けることで、n本前の計算結果を取得することができます。
OpenやCloseといった予約語だけでなく、自分で宣言した変数についても過去の計算結果を取得できます。
(こういう値のことを履歴値と言うそうです)

以前書いた平均足のコード(再掲載)

inputs: 
	Kai(0); 

vars: 
	AnswerOpen(0),
	AnswerClose(0),
	AnswerHigh(0),
	AnswerLow(0),
	PColor(White),
	BarCount(0);

AnswerHigh = High;
AnswerLow = Low;
AnswerOpen = (AnswerOpen[1] + AnswerClose[1]) / 2;

IF Kai = 1 then
	AnswerClose = (AvgPrice[3] + AvgPrice[2] + AvgPrice[1] + AvgPrice) / 4
ELSE
	AnswerClose = AvgPrice;

IF Date <> Date[1] or CurrentBar = 1 then
BEGIN
	AnswerOpen = OpenD(0);
	AnswerClose = AvgPrice;
	BarCount = 0;
END;

IF BarCount = 1 and Kai = 1 then AnswerClose = (AvgPrice[1] + AvgPrice) / 2;
IF BarCount = 2 and Kai = 1 then AnswerClose = (AvgPrice[2] + AvgPrice[1] + AvgPrice) / 3;

IF AnswerHigh < AnswerOpen then AnswerHigh = AnswerOpen;
IF AnswerHigh < AnswerClose then AnswerHigh = AnswerClose;
IF AnswerLow > AnswerOpen then AnswerLow = AnswerOpen;
IF AnswerLow > AnswerClose then AnswerLow = AnswerClose;

IF AnswerOpen < AnswerClose then
	PColor = Red
ELSE IF AnswerOpen > AnswerClose then
	PColor = Cyan
ELSE
	PColor = White;

BarCount += 1;

Plot1(AnswerHigh, !( "高値" ), PColor, Default, 1);
Plot2(AnswerLow, !( "安値" ), PColor, Default, 1);
Plot3(AnswerOpen, !( "始値" ), PColor, Default, 5);
Plot4(AnswerClose, !( "終値" ), PColor, Default, 5);

始値(AnswerOpen)を算出するには1本前の足の始値終値を合計して2で割ります。
計算式としてはAnswerOpen[1]で「1本前の足の始値」、AnswerClose[1]で「1本前の足の終値」を取得して
それを2で割るので
AnswerOpen = (AnswerOpen[1] + AnswerClose[1]) / 2;
となります。

EasyLanguageでの配列は?

では、EasyLanguageで一般的な配列は使えるのか?って話ですが
宣言にArraysを使うことで利用できます。

arrays:
	DummyArray[6](0);

上記にて0から6までの7要素の1次元配列を宣言し、初期値を0に設定します。
ここで問題なのですが、HighestArrayなどの配列に関する演算関数は
[0]に設定された値を無視する という仕様になっています。
なので、[0]は使用しないことが推奨されています。

一般的な言語(JavaScriptなど)では[0]から使用しますが、EasyLanguageでは[1]から使用すると認識したほうが良いでしょう。

履歴値も配列も同じ[n]で表現されているところが仕様的に微妙ですが、宣言を確認するしかないですね。

トレーリングストップとロスカットを株価ベース(%)で設定する



今日は簡単な自作のストラテジー(決済のみ)を書いてみます。

トレードステーションに付属されている固定トレーリングストップ・固定ロスカットは金額ベースなので
今一つ使い勝手が良くないと感じるかと思います。

なので、株価の何%下がったらトレーリングストップあるいはロスカットを実行するというストラテジーが欲しくなりますね。
以下をコピーしてストラテジーで保存

ロスカット自動設定

[IntrabarOrderGeneration = true]

inputs: 
	Amount(2);

vars:
	Amt(0);

Amt = IntPortion(Close  * (Amount / 100));

SetStopShare;
SetStopLoss(Amt);

Amountにロスカット割合%(株価の何%下がったらロスカット実行)を設定ください。

トレーリングストップ自動設定

[IntrabarOrderGeneration = true]

inputs: 
	PropAmt(11), 
	TrailingPct(10),
	ProfitAmt(0);

vars:
	Amt(0);

Amt = IntPortion(Close  * (PropAmt / 100));

IF ProfitAmt <> 0 and Amt > ProfitAmt then Amt = ProfitAmt;

SetStopShare;
SetPercentTrailing(Amt, TrailingPct);

PropAmt:利益割合%(株価の何%上昇を利益目標とするか)を設定
TrailingPct:決済実行割合%(PropAmt成立後、何%下がったら決済するか)を設定
ProfitAmt:金額ベース(株価から一定金額以上の利益が発生したら、金額ベースに切り替える場合の値を設定。不要ならゼロ)

f:id:tsukinowaapp:20180618083200p:plain

コード解説

IntrabarOrderGeneration とは、ティック(取引)発生時に毎回判定処理を行うかの設定になります。
trueの場合はティック(取引)発生時に毎回判定
falseにすると、チャートの足が確定したタイミングのみの判定となります。

IntPortionは計算結果の整数部のみ取り出す数式です。

SetStopLossあるいはSetPercentTrailingの前にあるSetStopShareは、
「計算を1株あたりで行う」ことを示す予約語となります。

他に「損益額で行う」ことを示すSetStopPosition という予約語がありますが
銘柄や状況によって保持する株数が異なってくると思いますので、計算が面倒になるでしょう。


トレステで平均足を表示する



トレードステーションではチャートを自作して画面に表示することができます。

今回は試しに平均足を作ってみます。
平均足の概要や計算式についてはこのへん。
toushi-kyokasho.com

改良版というのもあるらしい。
orange2.net

平均足を自作して表示する

以下のコードをインジケータ―で新規登録

inputs: 
	Kai(0); 

vars: 
	AnswerOpen(0),
	AnswerClose(0),
	AnswerHigh(0),
	AnswerLow(0),
	PColor(White),
	BarCount(0);

AnswerHigh = High;
AnswerLow = Low;
AnswerOpen = (AnswerOpen[1] + AnswerClose[1]) / 2;

IF Kai = 1 then
	AnswerClose = (AvgPrice[3] + AvgPrice[2] + AvgPrice[1] + AvgPrice) / 4
ELSE
	AnswerClose = AvgPrice;

IF Date <> Date[1] or CurrentBar = 1 then
BEGIN
	AnswerOpen = OpenD(0);
	AnswerClose = AvgPrice;
	BarCount = 0;
END;

IF BarCount = 1 and Kai = 1 then AnswerClose = (AvgPrice[1] + AvgPrice) / 2;
IF BarCount = 2 and Kai = 1 then AnswerClose = (AvgPrice[2] + AvgPrice[1] + AvgPrice) / 3;

IF AnswerHigh < AnswerOpen then AnswerHigh = AnswerOpen;
IF AnswerHigh < AnswerClose then AnswerHigh = AnswerClose;
IF AnswerLow > AnswerOpen then AnswerLow = AnswerOpen;
IF AnswerLow > AnswerClose then AnswerLow = AnswerClose;

IF AnswerOpen < AnswerClose then
	PColor = Red
ELSE IF AnswerOpen > AnswerClose then
	PColor = Cyan
ELSE
	PColor = White;

BarCount += 1;

Plot1(AnswerHigh, !( "高値" ), PColor, Default, 1);
Plot2(AnswerLow, !( "安値" ), PColor, Default, 1);
Plot3(AnswerOpen, !( "始値" ), PColor, Default, 5);
Plot4(AnswerClose, !( "終値" ), PColor, Default, 5);

AvgPriceは関数で、四値(高値・安値・始値終値)を合計して4で割った値を返してくれます。
過去の計算結果もAvgPrice[n]で容易に取得できるので楽ですね。

このまま表示すると恐らく曲線のままなので、「分析テクニックの設定」→対象を選択して「設定」→「スタイル」を選択
f:id:tsukinowaapp:20180617100836p:plain
タイプを以下の通り変更
始値バー高値
終値バー安値
高値: バー高値
安値: バー安値

チャートが元のデータと重ならず、別個に出てしまう場合は
画面上で右クリック→「分析テクニックの設定」→作成した名前を選択→「設定」
「スケーリング」タブをクリックして
スケール位置:元データに軸を合わせる
f:id:tsukinowaapp:20180621075533p:plain
で、元のチャートと重なって表示されるようになります。

f:id:tsukinowaapp:20180621080030p:plain
ついでに「デフォルト」→「はい」をクリックすると変更した設定が
今後新規に作るチャートにも反映されるようになります。

f:id:tsukinowaapp:20180617102314p:plain

Kaiに1を設定すると改良版が表示されます。
f:id:tsukinowaapp:20180617102409p:plain

改良版にすると細かい上げ下げが消えてなだらかになりますが、やや反応が遅れるようにも見えます。
一概にどちらがいいかは難しいところ。
パラボリックSAR等と組み合わせて総合的に判断すると良いかもですね。

よくネットで見かけるアレ足とかソレ足とかも計算式さえ分かれば再現可能かと思います。
移動平均線の上げ下げを色分けしたいのであれば、
上のコードでAverageFCを比較するように改造すれば行けるんじゃないかなと。


EasyLanguageの言語仕様 その2


型の扱い

EasyLanguageではJavaScriptと同じ最初に代入した値で型を決める方式を取っています。
但し、型を明示して設定することも可能です。

JavaScriptの場合

var num = 1;
var str= "0";

EasyLanguageの場合

vars:
    num(1),
    str("0");

型を指定する場合

vars:
    int num(1),
    string str("0");

EasyLanguageでは、型の宣言にvarsとinputsがあります。
varsは内部で持つユーザー変数となりますが
inputsは画面にて任意に設定できる値となります。

f:id:tsukinowaapp:20180616142851p:plain

ストラテジーの場合、inputsで宣言すると後で最適化というバックテストが行えるようになるので
リテラルはinputsで宣言しておくと良いでしょう。

EasyLanguageの言語仕様 その1



今年に入ってから株に興味を持ち始めて色々やってみたものの、
成果が出なくてこれは自動売買でやらないと無理だなという結論に達し
3か月ほどマネックス証券のトレードステーションを触ってみたので
良い機会なので文書化してみようかと思います。

EasyLanguageはEasyではない

結論から先に言うと、ゲームなり業務なりで何らかのアプリケーションを作った経験のある人でないとEasyLanguageを扱うことは難しいかと思います。
(経験者であれば、やや仕様に癖があるもののアジャストはさして難しくないかなあと。)

トレードステーションはEasyLanguageにてチャートを自作したり
ストラテジーを組んで自動売買できたりします。

そのEasyLanguageなのですが、
言語仕様がJavaScriptでもVBでもない独特のものとなっています。
Pascalという言語が基になっているような記述を見つけたのですが、それともやや仕様が異なるようです)

JavaScriptと異なるところ

恐らく最も利用者が多いであろうJavaScriptとの違いを見てみます。

基本構文

JavaScriptとかだと処理の単位をブレース{}で括りますが、EasyLanguageでは
BEGIN~ENDで括ります。

 JavaScriptの場合

var view = 1;
var ro = 0;

if (ro === 0) {
    view = 2;
}

EasyLanguageの場合

vars: 
    view(0),
    ro(1);

if ro = 1 then
begin
    view = 2;
end;

書いていて気づきましたが、EasyLanguageの場合は代入と比較が同じ記法(=)ですね。

セミコロンの扱い

命令の最後にセミコロン(;)を付与するのは同じですが、EasyLanguageの場合やや癖があります。
とくにIF~ELSE文が絡む場合は注意が必要です。

if UPTICKS >= Sikii then
BEGIN
	Alert(!("上昇"));
END
ELSE
if AnswerUP >= Sikii then
BEGIN
	Alert(!("上昇出来高合計"));
END
ELSE
BEGIN
    for ii = 0 to VwapAvg - 1
    BEGIN
        if ii < BarCount then
	BEGIN
            PriceW += (AvgPrice[ii] * AnyVol[ii]);
	END;
    END;
END;

基本は命令の最後に付与しますが、ネストする場合はそれぞれの最後に付与する形になります。
IF文をBEGIN~END句なしに記述すると以下の通りとなります。

IF RoundFlg = 0 then
    Answer = PriceW / ShareW
ELSE IF RoundFlg = 1 then
    Answer = Round(PriceW / ShareW, 0)
ELSE
    Answer = Round(PriceW / ShareW, 1);

最も、エディター(開発環境)でシンタックスエラーを指摘してくれるのですぐに慣れるかと思います。

ちょっと長くなりそうなので記事を分けます。