mt4 (MetaTrader4)使い倒シストレ

メタトレーダー、自作インジケータ、自作EAで完全自動売買。使えるものは何でも使え。
インジケーター、EA(自動売買システム)製作のご依頼はこちらへ
Googolyen FX Factory
スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。


にほんブログ村 為替ブログ FX システムトレード派へ
--/--/--(--) --:--:-- | スポンサー広告 | Trackback(-) | Comment(-)
参照渡しは、とても便利かも!
以前に書いた【グローバル変数を使わずに健康的に】の記事の中で
『参照渡し』を使ったコードを書いたところ、

「&」とは何を意味するのでしょうか?

というご質問をいただきました。
そこで、『参照渡し』についての解説と、便利に使える方法を
いくつかご紹介したいと思います。

まずは『参照渡し』についてです。

MQL4では、関数の引数の値をその関数内で変更しても
変数の値を変更することはできません。


どういうことかというと、案の定ですが…


以下のコードを見てください(笑)。

void func(int arg0) {
arg0++;
}

int start()
{
int param1 = 0;

func(param1);

Comment(param1);
}

func関数とstart関数を定義しました。

・func関数はarg0という引数を受け取り、arg0をインクリメント(1を加算)する関数です。
・start関数はparam1という変数を定義し、func関数を呼び出しています。

この時Comment関数によって表示される値は、
MQL4の仕様では、『0』のままなんです。

つまり
MQL4では、関数の引数【arg0】の値【0】をその関数内で変更【arg0++】しても
変数の値【param1】を変更することはできません【0のまま】。

ってことなんですね。

そこで『参照渡し』の登場です。
『参照渡し』を使えば、関数の引数の値をその関数内で変更した場合
変数の値を変更することができます。


使い方は簡単です。
関数宣言の引数名の前に「&」をつけるだけです。

void func(int &arg0) {
arg0++;
}

int start()
{
int param1 = 0;

func(param1);

Comment(param1);
}


今度はComment関数によって表示される値が『1』になります。
param1の値がちゃんとインクリメントされていますね。

つまり、
『参照渡し』を使えば、関数の引数【arg0】の値【0】をその関数内で変更【arg0++】した場合
変数の値【param1】を変更することができます【1になる!】。

ってことなんです。


これが『参照渡し』と呼ばれる方法です。
実はMQL4の標準関数にも、『参照渡し』は多用されています。
配列関数群の半分くらいに『参照渡し』が使われています。
(参照渡しは配列に使うこともできます)


int ArrayCopy( object&dest[], object source[], int start_dest=0, int start_source=0, int count=WHOLE_ARRAY)
int ArrayCopyRates( double&dest_array[], string symbol=NULL, int timeframe=0)
int ArrayCopySeries( double&array[], int series_index, string symbol=NULL, int timeframe=0)
int ArrayInitialize( double&array[], double value)
int ArrayResize( object&array[], int new_size)
bool ArraySetAsSeries( double&array[], bool set)
int ArraySort( double&array[], int count=WHOLE_ARRAY, int start=0, int sort_dir=MODE_ASCEND)


これはつまり、
この関数に渡した変数は、何かしら変化しますよ~。
ってことなんですね。
(ArrayResize関数は、渡した配列のサイズ(大きさ)を変更する関数です。)

『参照渡し』のイメージはつかめたでしょうか?

さて、続いて便利に使える方法です。

が…


次回につづく!!

にほんブログ村 為替ブログ FX システムトレード派へ
グローバル変数を使わずに健康的に
グローバル変数を、皆さんは多用していらっしゃいまっか?もうかりまっか?

これはほとんどのプログラミング言語に言えることですが、
必要以上のグローバル変数を使うことは、あまりお薦めできません。


それはこちらの説明に書いてありますので、文章で語ることは割愛します(文字での説明が面倒臭いわけではないですよ?(笑))。
その他にもグローバル変数多用の弊害については、様々なサイトに載っていると思うので、一度調べてみてはいかがでしょうか(文字での説明が面倒臭…(略))。

さて、文章で語るよりも、具体的にMQL4プログラムで説明しましょう。
以下のコードを見てください。


/**
* グローバル変数乱用サンプル
* 特に何をするでもなく…
*/
//--- Global variables
double Ma1;
double Ma2;
double Ma3;
double Ma4;

//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
Comment("");
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
Ma1 = iMA(Symbol(), Period(), 14, 0, MODE_SMA, PRICE_CLOSE, 0);
Ma2 = iMA(Symbol(), Period(), 21, 0, MODE_SMA, PRICE_CLOSE, 0);
Ma3 = iMA(Symbol(), Period(), 14, 0, MODE_EMA, PRICE_CLOSE, 0);
Ma4 = iMA(Symbol(), Period(), 21, 0, MODE_EMA, PRICE_CLOSE, 0);

SetMA();

Comment(Ma1, "\n", Ma2, "\n", (Ma1 - Ma3), "\n", (Ma2 - Ma4), "\n");
return(0);
}

//+------------------------------------------------------------------+

void SetMA()
{
Ma1 = iMA(Symbol(), Period(), 21, 0, MODE_SMA, PRICE_CLOSE, 0);
Ma2 = iMA(Symbol(), Period(), 14, 0, MODE_SMA, PRICE_CLOSE, 0);

Ma3 = iMA(Symbol(), Period(), 21, 0, MODE_EMA, PRICE_CLOSE, 0);
Ma4 = iMA(Symbol(), Period(), 14, 0, MODE_EMA, PRICE_CLOSE, 0);
}


私はこのようなプログラムを見ると、鬱になってしまいますが、みなさんはいかがでしょうか?
グローバル変数は、どの関数からも参照(アクセス)することができます。
この例では、start、SetMAの2つの関数で、グローバル変数Ma1~Ma4を参照しています。

今は短いプログラムなので動作を理解するのは簡単ですが、
非常に長く、グローバル変数が乱用されているプログラムを理解するには、多くの労力と時間を要します。


またグローバル変数を利用すると、関数の再利用性が落ちてしまいます。
例えば、他のMQL4プログラムでSetMA関数を利用したい場合、SetMA関数本体とSetMA関数内で使われているグローバル変数を全て記述しなければなりません。
関数はプログラム内で独立性が高ければ高いほど、再利用性が高まるのです。




①プログラムの動作を理解するのに時間と労力がかかる
②プログラム(関数)の再利用性が落ちる


以上の2点を考慮した場合、上記のプログラムは以下のように記述したほうがいいと思います。

int init()
{
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
Comment("");
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
double Ma1, Ma2, Ma3, Ma4;

Ma1 = iMA(Symbol(), Period(), 14, 0, MODE_SMA, PRICE_CLOSE, 0);
Ma2 = iMA(Symbol(), Period(), 21, 0, MODE_SMA, PRICE_CLOSE, 0);
Ma3 = iMA(Symbol(), Period(), 14, 0, MODE_EMA, PRICE_CLOSE, 0);
Ma4 = iMA(Symbol(), Period(), 21, 0, MODE_EMA, PRICE_CLOSE, 0);

SetMA(Ma1, Ma2, Ma3, Ma4);

Comment(Ma1, "\n", Ma2, "\n", (Ma1 - Ma3), "\n", (Ma2 - Ma4), "\n");
return(0);
}

//+------------------------------------------------------------------+

void SetMA(double &ma1, double &ma2, double &ma3, double &ma4)
{
ma1 = iMA(Symbol(), Period(), 21, 0, MODE_SMA, PRICE_CLOSE, 0);
ma2 = iMA(Symbol(), Period(), 14, 0, MODE_SMA, PRICE_CLOSE, 0);

ma3 = iMA(Symbol(), Period(), 21, 0, MODE_EMA, PRICE_CLOSE, 0);
ma4 = iMA(Symbol(), Period(), 14, 0, MODE_EMA, PRICE_CLOSE, 0);
}




ただ、どうしてもグローバル変数を使わなければならない状況もあると思います。
そういう場合はグローバル変数を必要最小限に抑える努力をしてみましょう。
その創意工夫がプログラミング力の向上になると考えています。



健康的なソースファイル作りにお役立てください。

にほんブログ村 為替ブログ FX システムトレード派へ
変数名には文字数制限がある
普段MQL4を使っていると、ふと思うことが色々あります。
その内の一つを今日はご紹介します。

「ちょー長い変数名って使えるんかいな…」


早速実験してみました。


int start()
{
int UWA = 0;
int UWAA = 0;
int UWAAA = 0;
int UWAAAA = 0;
int UWAAAAA = 0;
int UWAAAAAA = 0;
int UWAAAAAAA = 0;
int UWAAAAAAAA = 0;
int UWAAAAAAAAA = 0;
int UWAAAAAAAAAA = 0;
int UWAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = 0;
int UWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = 0;

}

このソースをコンパイルしてみると、見事にエラーに。

「too long variable name : 変数名が長すぎだよー」

どうやら32文字以上の変数名は宣言できないようですね。


補足:「#define」も32文字の制限があるようです。




にほんブログ村 為替ブログ FX システムトレード派へ
#defineを使って健康的に
何かと便利な「#define」ですが、皆さん使っておられるでしょうか?

「#define」を使う利点としては
①値自体に意味を持たせることができ、ソースファイルの可読性がUPする
②設定値を一発で変更することができる

などが挙げられると思います。

①を体験してみましょう。
以下のソースを見てください。

int start()
{
if (DayOfWeek() == 3) {
Print("DayOfWeek function return 3");
}
return (0);
}

このソースファイルを見た瞬間に、何曜日を指しているかお分かりでしょうか?
少し考えたら、
「0が日曜日のことだから、3は水曜日のことだ」
ということは分かると思いますが、
瞬間的に理解するのは「数値と曜日の関係を覚える」以外にありません。

しかし、「#define」を用いて以下のようにソースを書くとどうでしょう。

#define SUNDAY 0 //Sunday
#define MONDAY 1 //Monday
#define TUESDAY 2 //Tuesday
#define WEDNESDAY 3 //Wednesday
#define THURSDAY 4 //Thursday
#define FRIDAY 5 //Friday
#define SATURDAY 6 //Saturday
int start()
{
if (DayOfWeek() == WEDNESDAY) {
Print("DayOfWeek function return 3");
}
return (0);
}

今度はソースコードを見ただけでWEDNESDAY(水曜日)だと理解できますね。
このように「#define」を使えば、値自身に意味を持たせることができるため、
分かりやすいソースコードを書くことができます。


続いて②です。

#property copyright "googolyenfx"
#property link "http://googolyenfx.blog18.fc2.com/"

int init()
{
Comment("Created by googolyenfx http://googolyenfx.blog18.fc2.com/");
return (0);
}

インジケータの表示部に署名を表記したい場合には、上記のようなプログラムになると思います。

しかし突然ブログのURLが変更になった場合のことを考えてみてください。
ソースファイル中の全てのURLを書き変えなくてはなりません。
今はURLが2か所しか書かれていないため、修正は簡単なのですが、
あっちにもこっちにもURLを書いていたらどうなるでしょうか?
(そんなに署名したがる人もいないと思いますが、例え話ですので(笑)。)

そこであらかじめ「#define」を使っておくと、このような状況でもすんなりとURL変更できます。

#define LINK "http://googolyenfx.blog18.fc2.com/"
#property copyright "googolyenfx"
#property link LINK

int init()
{
Comment("Created by googolyenfx " + LINK);
return (0);
}

これでソースファイル中に書かれているURLは1か所になりました。
「#define」で定義されているURLだけを変更すれば、一発で他の場所のURLも変更されるというわけです。



この他にも「#define」を使う場面は多種多様です。


健康的なソースファイル作りにお役立てください。


にほんブログ村 為替ブログ FX システムトレード派へ
Designed by aykm.
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。