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

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

移動平均線大循環分析でストラテジーを組んでみる



今回は少なめのステップ数で、エントリーから決済までやるストラテジーを組んでみようかと思います。
マネックス証券移動平均線大循環分析のインジケーターを配布しています。

info.monex.co.jp

これの中身を参考にして、ストラテジーを組んでみます。

コーディング

ルールとしては、
ロング(買い)は
短期>中期>長期で、全てが上向き、MACDも上向きなら買いエントリー
短期<中期で短期が下向きになったら売り決済
ショート(空売り)は
短期<中期<長期で、全てが下向き、MACDも下向きなら空売りエントリー
短期>中期で短期が上向きになったら買い戻し決済

エントリー開始は9時30分から
14時以降はエントリーしない
14時30分に手仕舞い

[Intrabarordergeneration = true];

inputs: 
	AvgType(0),
	MAGeta(25),
	MALength1(5),
	MALength2(20),
	MALength3(40),
	MACD3SLength(20),
	MACD3LLength(40),
	StartTime(0930),
	EndTime(1430);
	
vars: 
	IntrabarPersist DaijunkanFlg(0),
	IntrabarPersist double MA1(0),
	IntrabarPersist double MA2(0),
	IntrabarPersist double MA3(0),
	IntrabarPersist macd3(0),
	EntryEndTime(1400);
	
EntryEndTime = CalcTime(EndTime, -30);

//Daijunkan
macd3 = MACD(Close, MACD3SLength, MACD3LLength);

IF AvgType = 0 then
BEGIN
	MA1 = XAverage( Close, MALength1 );
	MA2 = XAverage( Close, MALength2 );			
	MA3 = XAverage( Close, MALength3 );
END
ELSE
BEGIN
	MA1 = AverageFC( Close, MALength1 );
	MA2 = AverageFC( Close, MALength2 );			
	MA3 = AverageFC( Close, MALength3 );
END;

DaijunkanFlg = 0;
IF MA1 > MA2 + MAGeta and MA2 > MA3 and MA1 > MA1[1] and MA2 > MA2[1] and MA3 > MA3[1] and macd3 > macd3[1] then DaijunkanFlg = 1;
IF MA1 < MA2 - MAGeta and MA2 < MA3 and MA1 < MA1[1] and MA2 < MA2[1] and MA3 < MA3[1] and macd3 < macd3[1] then DaijunkanFlg = -1;

//
If MarketPosition = 0 and StartTime <= TIME and TIME < EntryEndTime then 
BEGIN
	if DaijunkanFlg = 1 then 
	BEGIN
		Buy (!("買いスタート")) next bar at market;
	END;

	if DaijunkanFlg = -1 then
	BEGIN
		Sellshort (!("空売りスタート")) next bar at market;
	END;
END;

//
IF MarketPosition <> 0 then 
BEGIN
	if MarketPosition = 1 then
	BEGIN
		IF MA1 < MA2 and MA1 < MA1[1] then
		BEGIN
			Sell (!("売り抜け")) next bar at market;
		END;
	END;
	
	if MarketPosition = -1 then 
	BEGIN
		IF MA1 > MA2 and MA1 > MA1[1] then
		BEGIN
			BuyToCover (!("買い戻し")) next bar at market;
		END;
	END;
END;

if EndTime <= TIME and TIME <= 1500 then
BEGIN
	if MarketPosition = 1 then
	BEGIN 
		Sell (!("指定時間売り抜け")) next bar at market;
	END;
	
	if MarketPosition = -1 then
	BEGIN
		BuyToCover (!("指定時間買い戻し")) next bar at market;
	END;
END;

コード解説

インジケーターのソースを見たところ、AverageFCでななくXAverageがデフォルトになっていたので
それに従っています。
XAverageとは何かっていうと、指数加重移動平均だそうです。
中身を見るとこんな計算式になっています。

SmoothingFactor =  2 / ( Length + 1 );
XAverage = XAverage[1] + SmoothingFactor * ( Price - XAverage[1] ) ;

Price は現在の株価です。
1つ前との差分をLengthで割って加算する感じですが、
単純なLengthでなく1足してから割っている所が割と謎ですね。

[Intrabarordergeneration = true];というのは
ティック(取引)が発生したら都度オーダー(発注)の判定処理を行うか、という意味です。
これをfalseにすると、足が完成したタイミングでのみ判定処理を行います。

変数の宣言の前にIntrabarPersist と付いていますが、
これを付けないと、足が完成したタイミングのみで変数が更新される仕様となります。
なので、ティック(取引)毎に値を更新したい場合はIntrabarPersist を宣言しておきます。
(フラグ管理で使う変数にIntrabarPersistがないと、想定しているタイミングで更新されないとかあります)

MarketPosition で現在のエントリー状態を調べることができます。
0でポジションなし、1でロング、-1でショートです。

TIMEで現在の時刻を4桁で拾ってこれます。
TIMEの計算はCalcTimeを使う必要があります。

ちょっとした上下でエントリーしないように
短期と中期の大小比較の際に下駄を履かせています。

バックテストしてみる

以下の条件でバックテストしてみます。
銘柄:任天堂[7974]
足種:2分
期間:20日(2018/05/25~2018/06/21)
数量:100株
ストラテジーの設定はデフォルトのまま

f:id:tsukinowaapp:20180622141510j:plain

(あくまでもバックテストの結果で利益が出たという話ではありません)

f:id:tsukinowaapp:20180622150346p:plain

f:id:tsukinowaapp:20180622150408p:plain

f:id:tsukinowaapp:20180622150431p:plain

実際にはもっと早めに利確するようなロジックを追加していくような感じでしょうか。

しかしこれにもカラクリがあって、手数料を引いていないんですね。
約定金額100万あたり400円ですから、
任天堂の場合1回の取引で1600円、往復3200円っていう…
手数料無料期間を活用するしかないですね。