<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>EA開発 アーカイブ - 自動売買を作ろう！</title>
	<atom:link href="https://mql-programing.com/archives/tag/ea%e9%96%8b%e7%99%ba/feed/" rel="self" type="application/rss+xml" />
	<link>https://mql-programing.com/archives/tag/ea開発/</link>
	<description>MQLプログラミング学習サイト</description>
	<lastBuildDate>Wed, 01 Apr 2026 05:05:54 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://mql-programing.com/main29/wp-content/uploads/2021/02/cropped-ブログアイコン-32x32.jpg</url>
	<title>EA開発 アーカイブ - 自動売買を作ろう！</title>
	<link>https://mql-programing.com/archives/tag/ea開発/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>【MQL4】チャート設定定数を完全理解！ENUM_CHART_PROPERTY_INTEGER・STRING・DOUBLEの使い方</title>
		<link>https://mql-programing.com/archives/13083/%e3%80%90mql4%e3%80%91%e3%83%81%e3%83%a3%e3%83%bc%e3%83%88%e8%a8%ad%e5%ae%9a%e5%ae%9a%e6%95%b0%e3%82%92%e5%ae%8c%e5%85%a8%e7%90%86%e8%a7%a3%ef%bc%81enum_chart_property_integer%e3%83%bbstring%e3%83%bbd/</link>
		
		<dc:creator><![CDATA[朝日奈りさ]]></dc:creator>
		<pubDate>Wed, 29 Apr 2026 01:00:00 +0000</pubDate>
				<category><![CDATA[定数]]></category>
		<category><![CDATA[【辞書】MQLリファレンス]]></category>
		<category><![CDATA[ChartSetInteger]]></category>
		<category><![CDATA[MQL4]]></category>
		<category><![CDATA[EA開発]]></category>
		<category><![CDATA[チャート設定]]></category>
		<category><![CDATA[ENUM_CHART_PROPERTY]]></category>
		<guid isPermaLink="false">https://mql-programing.com/?p=13083</guid>

					<description><![CDATA[<p>EAやインジケーターを開発していると、「チャートの背景色をプログラムから変更したい」「グリッドを非表示にしたい」「ローソク足の色を統一したい」といった場面に出くわすことがあります。 MQL4では、チャートの見た目や動作を [&#8230;]</p>
<p>投稿 <a href="https://mql-programing.com/archives/13083/%e3%80%90mql4%e3%80%91%e3%83%81%e3%83%a3%e3%83%bc%e3%83%88%e8%a8%ad%e5%ae%9a%e5%ae%9a%e6%95%b0%e3%82%92%e5%ae%8c%e5%85%a8%e7%90%86%e8%a7%a3%ef%bc%81enum_chart_property_integer%e3%83%bbstring%e3%83%bbd/">【MQL4】チャート設定定数を完全理解！ENUM_CHART_PROPERTY_INTEGER・STRING・DOUBLEの使い方</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[<p>EAやインジケーターを開発していると、「チャートの背景色をプログラムから変更したい」「グリッドを非表示にしたい」「ローソク足の色を統一したい」といった場面に出くわすことがあります。</p>
<p>MQL4では、チャートの見た目や動作を制御するための<strong>チャートプロパティ定数</strong>が用意されています。この記事では、<strong>ENUM_CHART_PROPERTY_INTEGER</strong>、<strong>ENUM_CHART_PROPERTY_STRING</strong>、<strong>ENUM_CHART_PROPERTY_DOUBLE</strong>の3種類の列挙型を中心に、チャート設定の操作方法をわかりやすく解説します。</p>
<h2><span id="toc1">チャートプロパティを操作する関数の全体像</span></h2>
<p>MQL4では、チャートプロパティの値を「設定する関数」と「取得する関数」がデータ型ごとにペアで用意されています。</p>
<table border="1" cellpadding="8" cellspacing="0" style="border-collapse: collapse; width: 100%; margin: 1em 0;">
<thead>
<tr style="background-color: #f0f0f0;">
<th>データ型</th>
<th>設定する関数</th>
<th>取得する関数</th>
<th>対応する列挙型</th>
</tr>
</thead>
<tbody>
<tr>
<td>整数型（long）</td>
<td>ChartSetInteger()</td>
<td>ChartGetInteger()</td>
<td>ENUM_CHART_PROPERTY_INTEGER</td>
</tr>
<tr>
<td>浮動小数点型（double）</td>
<td>ChartSetDouble()</td>
<td>ChartGetDouble()</td>
<td>ENUM_CHART_PROPERTY_DOUBLE</td>
</tr>
<tr>
<td>文字列型（string）</td>
<td>ChartSetString()</td>
<td>ChartGetString()</td>
<td>ENUM_CHART_PROPERTY_STRING</td>
</tr>
</tbody>
</table>
<p>これらの関数の第1引数にはチャートIDを指定します。<strong>0を指定すると現在のチャート</strong>を意味します。第2引数に、これから説明する列挙型の定数を渡すことで、どのプロパティを操作するかを指定します。</p>
<h2><span id="toc2">ENUM_CHART_PROPERTY_INTEGER — 整数型プロパティ</span></h2>
<p>最も種類が多く、よく使うのがこの整数型プロパティです。チャートの表示/非表示の切り替え、色の設定、モードの変更など幅広い操作ができます。</p>
<h3><span id="toc3">表示モード系のプロパティ</span></h3>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse: collapse; width: 100%; margin: 1em 0; font-size: 0.95em;">
<thead>
<tr style="background-color: #f0f0f0;">
<th>定数名</th>
<th>説明</th>
<th>設定値</th>
</tr>
</thead>
<tbody>
<tr>
<td>CHART_MODE</td>
<td>チャートの表示タイプ</td>
<td>CHART_BARS / CHART_CANDLES / CHART_LINE</td>
</tr>
<tr>
<td>CHART_FOREGROUND</td>
<td>価格チャートを前面に表示するか</td>
<td>true / false</td>
</tr>
<tr>
<td>CHART_SHIFT</td>
<td>右端にシフト（余白）を設けるか</td>
<td>true / false</td>
</tr>
<tr>
<td>CHART_AUTOSCROLL</td>
<td>自動スクロール（最新バーへ自動移動）</td>
<td>true / false</td>
</tr>
<tr>
<td>CHART_SCALE</td>
<td>チャートのスケール（0〜5）</td>
<td>0（縮小）〜 5（拡大）</td>
</tr>
</tbody>
</table>
<h3><span id="toc4">表示要素の ON/OFF 系プロパティ</span></h3>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse: collapse; width: 100%; margin: 1em 0; font-size: 0.95em;">
<thead>
<tr style="background-color: #f0f0f0;">
<th>定数名</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>CHART_SHOW_GRID</td>
<td>グリッド線の表示/非表示</td>
</tr>
<tr>
<td>CHART_SHOW_PERIOD_SEP</td>
<td>期間区切り線の表示/非表示</td>
</tr>
<tr>
<td>CHART_SHOW_ASK_LINE</td>
<td>Ask（買値）ラインの表示/非表示</td>
</tr>
<tr>
<td>CHART_SHOW_BID_LINE</td>
<td>Bid（売値）ラインの表示/非表示</td>
</tr>
<tr>
<td>CHART_SHOW_DATE_SCALE</td>
<td>横軸（日時スケール）の表示/非表示</td>
</tr>
<tr>
<td>CHART_SHOW_PRICE_SCALE</td>
<td>縦軸（価格スケール）の表示/非表示</td>
</tr>
<tr>
<td>CHART_SHOW_OHLC</td>
<td>四本値（OHLC）の表示/非表示</td>
</tr>
<tr>
<td>CHART_SHOW_ONE_CLICK</td>
<td>ワンクリックトレードパネルの表示/非表示</td>
</tr>
<tr>
<td>CHART_SHOW_VOLUMES</td>
<td>出来高の表示モード</td>
</tr>
</tbody>
</table>
<h3><span id="toc5">色の設定用プロパティ</span></h3>
<p>チャートの配色もすべてプログラムから制御できます。color型の値を指定します。</p>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse: collapse; width: 100%; margin: 1em 0; font-size: 0.95em;">
<thead>
<tr style="background-color: #f0f0f0;">
<th>定数名</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>CHART_COLOR_BACKGROUND</td>
<td>チャートの背景色</td>
</tr>
<tr>
<td>CHART_COLOR_FOREGROUND</td>
<td>前景色（軸やテキストの色）</td>
</tr>
<tr>
<td>CHART_COLOR_GRID</td>
<td>グリッド線の色</td>
</tr>
<tr>
<td>CHART_COLOR_CHART_UP</td>
<td>上昇バー / ローソク足の外枠・ヒゲの色</td>
</tr>
<tr>
<td>CHART_COLOR_CHART_DOWN</td>
<td>下降バー / ローソク足の外枠・ヒゲの色</td>
</tr>
<tr>
<td>CHART_COLOR_CANDLE_BULL</td>
<td>陽線（Bull）の実体の色</td>
</tr>
<tr>
<td>CHART_COLOR_CANDLE_BEAR</td>
<td>陰線（Bear）の実体の色</td>
</tr>
<tr>
<td>CHART_COLOR_CHART_LINE</td>
<td>ラインチャートの色</td>
</tr>
<tr>
<td>CHART_COLOR_ASK</td>
<td>Askラインの色</td>
</tr>
<tr>
<td>CHART_COLOR_BID</td>
<td>Bidラインの色</td>
</tr>
<tr>
<td>CHART_COLOR_STOP_LEVEL</td>
<td>ストップレベルの色</td>
</tr>
</tbody>
</table>
<h3><span id="toc6">読み取り専用のプロパティ</span></h3>
<p>以下のプロパティは値の取得のみ可能で、プログラムから変更はできません（読み取り専用 = r/o）。</p>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse: collapse; width: 100%; margin: 1em 0; font-size: 0.95em;">
<thead>
<tr style="background-color: #f0f0f0;">
<th>定数名</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>CHART_WINDOWS_TOTAL</td>
<td>チャートウィンドウの総数（サブウィンドウ含む）</td>
</tr>
<tr>
<td>CHART_WIDTH_IN_BARS</td>
<td>チャートの幅（バー数単位）</td>
</tr>
<tr>
<td>CHART_WIDTH_IN_PIXELS</td>
<td>チャートの幅（ピクセル単位）</td>
</tr>
<tr>
<td>CHART_HEIGHT_IN_PIXELS</td>
<td>チャートの高さ（ピクセル単位）</td>
</tr>
<tr>
<td>CHART_FIRST_VISIBLE_BAR</td>
<td>画面上で最初に見えるバーの番号</td>
</tr>
<tr>
<td>CHART_VISIBLE_BARS</td>
<td>画面上に表示されているバーの本数</td>
</tr>
<tr>
<td>CHART_IS_OBJECT</td>
<td>オブジェクトとしてのチャートかどうか</td>
</tr>
</tbody>
</table>
<h3><span id="toc7">実践サンプル：チャートの配色をカスタマイズする</span></h3>
<p>以下はEAの<code>OnInit()</code>内でチャートの見た目を一括変更する例です。</p>
<pre><code class="language-mql4">int OnInit()
{
   // チャート表示をローソク足に変更
   ChartSetInteger(0, CHART_MODE, CHART_CANDLES);
   
   // 背景色をダークブルーに設定
   ChartSetInteger(0, CHART_COLOR_BACKGROUND, clrMidnightBlue);
   
   // グリッドを非表示にする（背景色と同色でも可）
   ChartSetInteger(0, CHART_SHOW_GRID, false);
   
   // 陽線（Bull）の色設定
   ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, clrDodgerBlue);
   ChartSetInteger(0, CHART_COLOR_CHART_UP, clrDodgerBlue);
   
   // 陰線（Bear）の色設定
   ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, clrMediumOrchid);
   ChartSetInteger(0, CHART_COLOR_CHART_DOWN, clrMediumOrchid);
   
   // Askラインを表示する
   ChartSetInteger(0, CHART_SHOW_ASK_LINE, true);
   
   // 設定を反映
   ChartRedraw();
   
   return(INIT_SUCCEEDED);
}</code></pre>
<p><strong>ポイント：</strong>ChartSetInteger()を呼んだだけでは画面にすぐ反映されないことがあります。確実に描画を更新したい場合は、最後に<code>ChartRedraw()</code>を呼びましょう。</p>
<h2><span id="toc8">ENUM_CHART_PROPERTY_DOUBLE — 浮動小数点型プロパティ</span></h2>
<p>Double型のプロパティは数が少なく、主にチャートの価格範囲を取得するために使います。</p>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse: collapse; width: 100%; margin: 1em 0; font-size: 0.95em;">
<thead>
<tr style="background-color: #f0f0f0;">
<th>定数名</th>
<th>説明</th>
<th>備考</th>
</tr>
</thead>
<tbody>
<tr>
<td>CHART_PRICE_MIN</td>
<td>チャート上の最小価格</td>
<td>読み取り専用</td>
</tr>
<tr>
<td>CHART_PRICE_MAX</td>
<td>チャート上の最大価格</td>
<td>読み取り専用</td>
</tr>
<tr>
<td>CHART_SHIFT_SIZE</td>
<td>右端シフトの割合（10〜50%）</td>
<td>設定可能</td>
</tr>
<tr>
<td>CHART_FIXED_POSITION</td>
<td>固定位置（左端からの割合%）</td>
<td>設定可能</td>
</tr>
<tr>
<td>CHART_FIXED_MAX</td>
<td>固定スケール時の最大価格</td>
<td>設定可能</td>
</tr>
<tr>
<td>CHART_FIXED_MIN</td>
<td>固定スケール時の最小価格</td>
<td>設定可能</td>
</tr>
</tbody>
</table>
<h3><span id="toc9">実践サンプル：現在のチャート価格範囲を取得する</span></h3>
<pre><code class="language-mql4">void OnTick()
{
   // 現在チャートに表示されている価格範囲を取得
   double priceMin = ChartGetDouble(0, CHART_PRICE_MIN);
   double priceMax = ChartGetDouble(0, CHART_PRICE_MAX);
   
   Print("表示中の価格範囲: ", priceMin, " ～ ", priceMax);
}</code></pre>
<p><code>CHART_PRICE_MIN</code>と<code>CHART_PRICE_MAX</code>は、画面上に「今見えている」範囲の最小・最大価格です。スクロールやズームに応じて動的に変化するため、現在の表示状態を知りたいときに便利です。</p>
<h2><span id="toc10">ENUM_CHART_PROPERTY_STRING — 文字列型プロパティ</span></h2>
<p>文字列型のプロパティは現在1つだけです。</p>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse: collapse; width: 100%; margin: 1em 0; font-size: 0.95em;">
<thead>
<tr style="background-color: #f0f0f0;">
<th>定数名</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>CHART_COMMENT</td>
<td>チャートの左上に表示されるコメント文字列</td>
</tr>
</tbody>
</table>
<h3><span id="toc11">実践サンプル：チャートにコメントを表示する</span></h3>
<pre><code class="language-mql4">void OnTick()
{
   // ChartSetString でチャートコメントを設定
   string info = "スプレッド: " + IntegerToString(SymbolInfoInteger(_Symbol, SYMBOL_SPREAD))
               + " / Bid: " + DoubleToString(Bid, _Digits);
   
   ChartSetString(0, CHART_COMMENT, info);
   ChartRedraw();
}

// コメントの取得
void ShowCurrentComment()
{
   string currentComment = ChartGetString(0, CHART_COMMENT);
   Print("現在のコメント: ", currentComment);
}</code></pre>
<p><code>ChartSetString()</code>による<code>CHART_COMMENT</code>の設定は、<code>Comment()</code>関数と同様にチャート左上にテキストを表示します。<code>Comment()</code>関数との違いは、チャートIDを指定できるため<strong>他のチャートウィンドウに対してもコメントを設定できる</strong>点です。</p>
<h2><span id="toc12">応用テクニック：チャートの設定を保存・復元する</span></h2>
<p>EAやインジケーターでチャートの見た目を変更する場合、終了時に元の設定に戻すのがマナーです。以下のパターンを覚えておきましょう。</p>
<pre><code class="language-mql4">// グローバル変数に元の設定を保存
color g_origBgColor;
bool  g_origShowGrid;

int OnInit()
{
   // 元の設定を保存
   g_origBgColor  = (color)ChartGetInteger(0, CHART_COLOR_BACKGROUND);
   g_origShowGrid = (bool)ChartGetInteger(0, CHART_SHOW_GRID);
   
   // 新しい設定を適用
   ChartSetInteger(0, CHART_COLOR_BACKGROUND, clrBlack);
   ChartSetInteger(0, CHART_SHOW_GRID, false);
   ChartRedraw();
   
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   // 元の設定を復元
   ChartSetInteger(0, CHART_COLOR_BACKGROUND, g_origBgColor);
   ChartSetInteger(0, CHART_SHOW_GRID, g_origShowGrid);
   ChartRedraw();
}</code></pre>
<p>こうすることで、EAを取り外したときにチャートが元の見た目に戻ります。ユーザーにとって親切な設計になりますので、ぜひ習慣にしてください。</p>
<h2><span id="toc13">よくある注意点とつまずきポイント</span></h2>
<h3><span id="toc14">① ChartRedraw()を忘れない</span></h3>
<p>チャートプロパティを変更する関数は、実際にはイベントキューにコマンドを追加するだけです。画面への即時反映が必要な場合は、<code>ChartRedraw()</code>を明示的に呼びましょう。</p>
<h3><span id="toc15">② 第1引数のチャートID</span></h3>
<p>第1引数に<strong>0</strong>を指定すると「現在のチャート」を意味します。別のチャートを操作したい場合は、<code>ChartID()</code>や<code>ChartFirst()</code>/<code>ChartNext()</code>で取得したIDを使います。</p>
<h3><span id="toc16">③ 読み取り専用プロパティに注意</span></h3>
<p><code>CHART_WIDTH_IN_PIXELS</code>や<code>CHART_PRICE_MIN</code>などの読み取り専用（r/o）プロパティに対してSet関数を呼んでも、値は変更されません。公式リファレンスで「r/o」の表記を確認しましょう。</p>
<h3><span id="toc17">④ 新しく開いたチャートの操作タイミング</span></h3>
<p><code>ChartOpen()</code>で新しくチャートを開いた直後は、まだデータが読み込まれていない場合があります。<code>CHART_PRICE_MIN</code>や<code>CHART_PRICE_MAX</code>を取得しても0が返ることがあるため、少し待つか、次のティックで取得するようにしましょう。</p>
<h2><span id="toc18">まとめ</span></h2>
<p>MQL4のチャートプロパティ定数は、大きく<strong>3つの列挙型</strong>に分類されます。</p>
<ul>
<li><strong>ENUM_CHART_PROPERTY_INTEGER</strong>：色・表示切替・モード設定など（最も種類が多い）</li>
<li><strong>ENUM_CHART_PROPERTY_DOUBLE</strong>：価格範囲・スケール関連</li>
<li><strong>ENUM_CHART_PROPERTY_STRING</strong>：チャートコメント</li>
</ul>
<p>操作には<code>ChartSetInteger()</code>/<code>ChartGetInteger()</code>、<code>ChartSetDouble()</code>/<code>ChartGetDouble()</code>、<code>ChartSetString()</code>/<code>ChartGetString()</code>の6つの関数を使い分けます。</p>
<p>特に、EAやインジケーターで<strong>チャートの配色カスタマイズ</strong>や<strong>情報表示</strong>を行う際に必須の知識となりますので、まずは本記事のサンプルコードを動かして、チャートプロパティの変更を体験してみてください！</p>
<p>投稿 <a href="https://mql-programing.com/archives/13083/%e3%80%90mql4%e3%80%91%e3%83%81%e3%83%a3%e3%83%bc%e3%83%88%e8%a8%ad%e5%ae%9a%e5%ae%9a%e6%95%b0%e3%82%92%e5%ae%8c%e5%85%a8%e7%90%86%e8%a7%a3%ef%bc%81enum_chart_property_integer%e3%83%bbstring%e3%83%bbd/">【MQL4】チャート設定定数を完全理解！ENUM_CHART_PROPERTY_INTEGER・STRING・DOUBLEの使い方</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【MQL4】ENUM_APPLIED_PRICE（価格定数）完全ガイド｜PRICE_CLOSEからPRICE_WEIGHTEDまで7種類を徹底解説</title>
		<link>https://mql-programing.com/archives/13074/%e3%80%90mql4%e3%80%91enum_applied_price%ef%bc%88%e4%be%a1%e6%a0%bc%e5%ae%9a%e6%95%b0%ef%bc%89%e5%ae%8c%e5%85%a8%e3%82%ac%e3%82%a4%e3%83%89%ef%bd%9cprice_close%e3%81%8b%e3%82%89price_weighted%e3%81%be/</link>
		
		<dc:creator><![CDATA[朝日奈りさ]]></dc:creator>
		<pubDate>Sun, 26 Apr 2026 01:00:00 +0000</pubDate>
				<category><![CDATA[【辞書】MQLリファレンス]]></category>
		<category><![CDATA[定数]]></category>
		<category><![CDATA[iMA関数]]></category>
		<category><![CDATA[ENUM_APPLIED_PRICE]]></category>
		<category><![CDATA[MQL4]]></category>
		<category><![CDATA[EA開発]]></category>
		<category><![CDATA[価格定数]]></category>
		<guid isPermaLink="false">https://mql-programing.com/?p=13074</guid>

					<description><![CDATA[<p>MQL4でインジケーター関数を使うとき、「どの価格を基準に計算するか」を指定する場面が頻繁にあります。たとえば移動平均線を計算するとき、終値を使うのか、高値と安値の平均を使うのかで結果が変わりますよね。 この「どの価格を [&#8230;]</p>
<p>投稿 <a href="https://mql-programing.com/archives/13074/%e3%80%90mql4%e3%80%91enum_applied_price%ef%bc%88%e4%be%a1%e6%a0%bc%e5%ae%9a%e6%95%b0%ef%bc%89%e5%ae%8c%e5%85%a8%e3%82%ac%e3%82%a4%e3%83%89%ef%bd%9cprice_close%e3%81%8b%e3%82%89price_weighted%e3%81%be/">【MQL4】ENUM_APPLIED_PRICE（価格定数）完全ガイド｜PRICE_CLOSEからPRICE_WEIGHTEDまで7種類を徹底解説</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[<p>MQL4でインジケーター関数を使うとき、「どの価格を基準に計算するか」を指定する場面が頻繁にあります。たとえば移動平均線を計算するとき、終値を使うのか、高値と安値の平均を使うのかで結果が変わりますよね。</p>
<p>この「どの価格を使うか」を指定するために用意されているのが、<strong>ENUM_APPLIED_PRICE</strong>（適用価格の列挙型）です。全部で7種類の定数があり、iMA()やiRSI()などの組み込み関数で頻繁に使われます。</p>
<p>この記事では、7つの価格定数それぞれの意味と計算式、そして実際のコードでの使い方をわかりやすく解説します。</p>
<h2><span id="toc1">ENUM_APPLIED_PRICEとは？</span></h2>
<p>ENUM_APPLIED_PRICEは、MQL4で定義されている<strong>列挙型（enum）</strong>のひとつです。テクニカル指標の計算に使う「価格の種類」を指定するために使います。</p>
<p>たとえば、移動平均線を計算する<code>iMA()</code>関数のシグネチャを見てみましょう。</p>
<pre><code class="language-mql4">double iMA(
   string       symbol,           // 通貨ペア
   int          timeframe,        // 時間足
   int          ma_period,        // 期間
   int          ma_shift,         // シフト
   int          ma_method,        // 移動平均の種類
   int          applied_price,    // 適用価格 ← ここ！
   int          shift             // バーのインデックス
);
</code></pre>
<p>この<strong>applied_price</strong>の部分に、ENUM_APPLIED_PRICEの定数を指定します。どの定数を選ぶかによって、計算結果が変わってくるわけです。</p>
<h2><span id="toc2">7つの価格定数一覧</span></h2>
<p>ENUM_APPLIED_PRICEには、以下の7つの定数が定義されています。</p>
<table border="1" cellpadding="8" cellspacing="0" style="border-collapse: collapse; width: 100%;">
<thead>
<tr style="background-color: #f0f0f0;">
<th>定数名</th>
<th>値</th>
<th>説明</th>
<th>計算式</th>
</tr>
</thead>
<tbody>
<tr>
<td>PRICE_CLOSE</td>
<td>0</td>
<td>終値</td>
<td>Close</td>
</tr>
<tr>
<td>PRICE_OPEN</td>
<td>1</td>
<td>始値</td>
<td>Open</td>
</tr>
<tr>
<td>PRICE_HIGH</td>
<td>2</td>
<td>高値</td>
<td>High</td>
</tr>
<tr>
<td>PRICE_LOW</td>
<td>3</td>
<td>安値</td>
<td>Low</td>
</tr>
<tr>
<td>PRICE_MEDIAN</td>
<td>4</td>
<td>中間値</td>
<td>(High + Low) / 2</td>
</tr>
<tr>
<td>PRICE_TYPICAL</td>
<td>5</td>
<td>典型値</td>
<td>(High + Low + Close) / 3</td>
</tr>
<tr>
<td>PRICE_WEIGHTED</td>
<td>6</td>
<td>加重終値</td>
<td>(High + Low + Close + Close) / 4</td>
</tr>
</tbody>
</table>
<h3><span id="toc3">PRICE_CLOSE（終値）— 値: 0</span></h3>
<p>もっとも一般的に使われる適用価格です。各ローソク足の<strong>終値（Close）</strong>を使って計算します。特にこだわりがなければ、まずはこれを選んでおけば問題ありません。多くのトレーダーやテクニカル分析の教科書でも、終値ベースの計算がデフォルトとされています。</p>
<h3><span id="toc4">PRICE_OPEN（始値）— 値: 1</span></h3>
<p>各ローソク足の<strong>始値（Open）</strong>を使って計算します。始値はバーの開始時点の価格なので、「そのバーが始まった瞬間にわかる値」という特徴があります。バックテストやリアルタイム処理で、確定済みの値だけを使いたい場合に選ばれることがあります。</p>
<h3><span id="toc5">PRICE_HIGH（高値）— 値: 2</span></h3>
<p>各ローソク足の<strong>高値（High）</strong>を使って計算します。高値ベースの移動平均線は、レジスタンスライン（上値抵抗線）のような役割として活用できます。</p>
<h3><span id="toc6">PRICE_LOW（安値）— 値: 3</span></h3>
<p>各ローソク足の<strong>安値（Low）</strong>を使って計算します。安値ベースの移動平均線は、サポートライン（下値支持線）のような役割として活用できます。PRICE_HIGHと組み合わせて移動平均チャネルを作る使い方が人気です。</p>
<h3><span id="toc7">PRICE_MEDIAN（中間値）— 値: 4</span></h3>
<p>計算式は <strong>(High + Low) / 2</strong> です。ローソク足の高値と安値のちょうど中間の価格、つまりそのバーの「値幅の中心」を使います。終値の偏りを排除し、そのバーの価格帯の中心で計算したいときに使います。</p>
<h3><span id="toc8">PRICE_TYPICAL（典型値）— 値: 5</span></h3>
<p>計算式は <strong>(High + Low + Close) / 3</strong> です。Median Price（中間値）に終値を加えて3で割った値で、中間値よりも<strong>実際の値動きの結果（終値）を反映</strong>した価格になります。CCI（商品チャネル指数）などのインジケーターでは、このTypical Priceが標準的に使われています。</p>
<h3><span id="toc9">PRICE_WEIGHTED（加重終値）— 値: 6</span></h3>
<p>計算式は <strong>(High + Low + Close + Close) / 4</strong> です。Typical Price（典型値）の計算式で終値を2回カウントすることで、<strong>終値により大きな比重</strong>を置いた価格です。「値幅全体も考慮したいけど、やっぱり終値を重視したい」という場合に適しています。</p>
<p>この3つの関係性を整理すると、次のようになります。</p>
<ul>
<li><strong>Median Price</strong>（HL/2）：ローソク足の値幅の中間値</li>
<li><strong>Typical Price</strong>（HLC/3）：中間値に終値を加え、より実際の値動きに近づけた値</li>
<li><strong>Weighted Close</strong>（HLCC/4）：さらに終値の比重を高め、終値に近づけた値</li>
</ul>
<h2><span id="toc10">実際のコードでの使い方</span></h2>
<h3><span id="toc11">iMA関数での基本的な使用例</span></h3>
<p>もっとも基本的な使い方です。20期間の単純移動平均線を終値ベースで計算します。</p>
<pre><code class="language-mql4">void OnTick()
{
   // 20期間SMAを終値(PRICE_CLOSE)で計算
   double ma_close = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_CLOSE, 0);

   // 20期間SMAを典型値(PRICE_TYPICAL)で計算
   double ma_typical = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_TYPICAL, 0);

   Print("終値ベースSMA: ", ma_close);
   Print("典型値ベースSMA: ", ma_typical);
}
</code></pre>
<p>同じ期間・同じ移動平均の種類でも、適用価格を変えるだけで計算結果が変わることがわかります。</p>
<h3><span id="toc12">iRSI関数での使用例</span></h3>
<p>RSI（相対力指数）でも適用価格を指定できます。</p>
<pre><code class="language-mql4">void OnTick()
{
   // 14期間RSIを終値で計算
   double rsi = iRSI(NULL, 0, 14, PRICE_CLOSE, 0);

   if(rsi > 70)
   {
      Print("RSIが70を超えました（買われすぎ）: ", rsi);
   }
   else if(rsi < 30)
   {
      Print("RSIが30を下回りました（売られすぎ）: ", rsi);
   }
}
</code></pre>
<h3><span id="toc13">HIGH/LOWを使った移動平均チャネルの作成例</span></h3>
<p>PRICE_HIGHとPRICE_LOWを組み合わせると、価格を挟み込むようなチャネル（帯）を作ることができます。</p>
<pre><code class="language-mql4">void OnTick()
{
   int period = 20;

   // 高値ベースの移動平均（上側バンド）
   double upper = iMA(NULL, 0, period, 0, MODE_SMA, PRICE_HIGH, 0);

   // 安値ベースの移動平均（下側バンド）
   double lower = iMA(NULL, 0, period, 0, MODE_SMA, PRICE_LOW, 0);

   // 終値ベースの移動平均（中央線）
   double middle = iMA(NULL, 0, period, 0, MODE_SMA, PRICE_CLOSE, 0);

   Print("上側: ", upper, " 中央: ", middle, " 下側: ", lower);

   // 現在価格が上側バンドを超えたら
   if(Ask > upper)
   {
      Print("価格が移動平均チャネルの上側を突破！");
   }
   // 現在価格が下側バンドを下回ったら
   if(Bid < lower)
   {
      Print("価格が移動平均チャネルの下側を突破！");
   }
}
</code></pre>
<p>このように、適用価格を変えるだけで同じiMA関数から異なる性質のラインを引くことができます。</p>
<h2><span id="toc14">input変数でユーザーに選ばせる方法</span></h2>
<p>EAやカスタムインジケーターを作るとき、適用価格をユーザーがパラメーター画面から選べるようにしたいですよね。MQL4では、<strong>ENUM_APPLIED_PRICEをinput変数の型として使う</strong>ことで、自動的にドロップダウンリストが表示されます。</p>
<pre><code class="language-mql4">// パラメーター設定
input int                 MAPeriod     = 20;            // 移動平均の期間
input ENUM_MA_METHOD      MAMethod     = MODE_SMA;      // 移動平均の種類
input ENUM_APPLIED_PRICE  MAPrice      = PRICE_CLOSE;   // 適用価格

void OnTick()
{
   double ma = iMA(NULL, 0, MAPeriod, 0, MAMethod, MAPrice, 0);
   Print("MA値: ", ma);
}
</code></pre>
<p>このように書くだけで、MetaTraderのパラメーター入力画面に「適用価格」のドロップダウンリストが自動生成されます。ユーザーは「Close price」「Open price」「Median Price (HL/2)」…といった選択肢から直感的に選ぶことができます。</p>
<p>int型で宣言してユーザーに数値を手入力させるよりも、<strong>はるかに使いやすく、入力ミスも防げる</strong>優れた方法です。EAやインジケーターを配布する場合は、ぜひこの書き方を使いましょう。</p>
<h2><span id="toc15">定数の整数値を直接使う場合の注意</span></h2>
<p>ENUM_APPLIED_PRICEの各定数には整数値（0〜6）が割り当てられているため、数値を直接指定しても動作します。</p>
<pre><code class="language-mql4">// 定数名を使う場合（推奨）
double ma1 = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_CLOSE, 0);

// 整数値を直接使う場合（非推奨）
double ma2 = iMA(NULL, 0, 20, 0, MODE_SMA, 0, 0);
</code></pre>
<p>上の2行はどちらも同じ結果になりますが、<strong>整数値を直接書く方法はおすすめしません</strong>。理由は以下の通りです。</p>
<ul>
<li><strong>可読性が低い</strong>：「0」だけでは何の価格かすぐにわからない</li>
<li><strong>保守性が悪い</strong>：後から見たとき、あるいは他の人が見たときに意味が伝わらない</li>
<li><strong>タイプミスに気づきにくい</strong>：定数名なら打ち間違えればコンパイルエラーになるが、数値だと範囲外の値でも気づきにくい</li>
</ul>
<p>常に<strong>PRICE_CLOSE</strong>や<strong>PRICE_TYPICAL</strong>のような定数名を使うようにしましょう。</p>
<h2><span id="toc16">どの適用価格を選ぶべきか？</span></h2>
<p>7種類もあると「結局どれを使えばいいの？」と迷いますよね。以下に用途別の目安をまとめます。</p>
<table border="1" cellpadding="8" cellspacing="0" style="border-collapse: collapse; width: 100%;">
<thead>
<tr style="background-color: #f0f0f0;">
<th>用途・場面</th>
<th>おすすめの適用価格</th>
</tr>
</thead>
<tbody>
<tr>
<td>一般的なトレンド分析</td>
<td>PRICE_CLOSE（最も標準的）</td>
</tr>
<tr>
<td>ノイズを減らしたい</td>
<td>PRICE_TYPICAL または PRICE_MEDIAN</td>
</tr>
<tr>
<td>終値重視だがノイズも減らしたい</td>
<td>PRICE_WEIGHTED</td>
</tr>
<tr>
<td>レジスタンスライン的に使いたい</td>
<td>PRICE_HIGH</td>
</tr>
<tr>
<td>サポートライン的に使いたい</td>
<td>PRICE_LOW</td>
</tr>
<tr>
<td>CCIなど特定のインジケーター</td>
<td>PRICE_TYPICAL（標準仕様に従う）</td>
</tr>
</tbody>
</table>
<p>迷ったときは<strong>PRICE_CLOSE</strong>を選んでおけば、まず間違いありません。そこから最適化やバックテストを行って、他の価格定数を試してみるのがよいでしょう。</p>
<h2><span id="toc17">まとめ</span></h2>
<p>ENUM_APPLIED_PRICEは、テクニカル指標の計算に「どの価格を使うか」を指定するための列挙型です。今回のポイントを振り返りましょう。</p>
<ul>
<li><strong>7種類の定数</strong>がある：PRICE_CLOSE（終値）、PRICE_OPEN（始値）、PRICE_HIGH（高値）、PRICE_LOW（安値）、PRICE_MEDIAN（中間値）、PRICE_TYPICAL（典型値）、PRICE_WEIGHTED（加重終値）</li>
<li><strong>iMA()やiRSI()</strong>などの組み込み関数で、applied_priceパラメーターに指定して使う</li>
<li><strong>input変数の型</strong>にENUM_APPLIED_PRICEを使えば、ドロップダウンリストで選択できるようになる</li>
<li>整数値の直接指定は動作するが、<strong>可読性の観点から定数名を使うべき</strong></li>
<li>迷ったら<strong>PRICE_CLOSE</strong>が最も無難で一般的</li>
</ul>
<p>適用価格の選択はインジケーターの計算結果に直接影響するため、それぞれの意味を理解しておくことが大切です。この記事を参考に、自分のEAやインジケーターに最適な適用価格を選んでみてください。</p>
<p>投稿 <a href="https://mql-programing.com/archives/13074/%e3%80%90mql4%e3%80%91enum_applied_price%ef%bc%88%e4%be%a1%e6%a0%bc%e5%ae%9a%e6%95%b0%ef%bc%89%e5%ae%8c%e5%85%a8%e3%82%ac%e3%82%a4%e3%83%89%ef%bd%9cprice_close%e3%81%8b%e3%82%89price_weighted%e3%81%be/">【MQL4】ENUM_APPLIED_PRICE（価格定数）完全ガイド｜PRICE_CLOSEからPRICE_WEIGHTEDまで7種類を徹底解説</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【MQL4】時間足定数（ENUM_TIMEFRAMES）完全ガイド｜PERIOD_M1〜PERIOD_MN1の一覧と実践的な使い方</title>
		<link>https://mql-programing.com/archives/13071/%e3%80%90mql4%e3%80%91%e6%99%82%e9%96%93%e8%b6%b3%e5%ae%9a%e6%95%b0%ef%bc%88enum_timeframes%ef%bc%89%e5%ae%8c%e5%85%a8%e3%82%ac%e3%82%a4%e3%83%89%ef%bd%9cperiod_m1%e3%80%9cperiod_mn1%e3%81%ae%e4%b8%80/</link>
		
		<dc:creator><![CDATA[朝日奈りさ]]></dc:creator>
		<pubDate>Sat, 25 Apr 2026 01:00:00 +0000</pubDate>
				<category><![CDATA[【辞書】MQLリファレンス]]></category>
		<category><![CDATA[定数]]></category>
		<category><![CDATA[時間足]]></category>
		<category><![CDATA[マルチタイムフレーム]]></category>
		<category><![CDATA[ENUM_TIMEFRAMES]]></category>
		<category><![CDATA[MQL4]]></category>
		<category><![CDATA[EA開発]]></category>
		<guid isPermaLink="false">https://mql-programing.com/?p=13071</guid>

					<description><![CDATA[<p>MQL4でEAやインジケーターを作っていると、「1時間足の移動平均線を取得したい」「日足のローソク足データを参照したい」といった場面が頻繁に出てきます。そんなときに使うのが時間足定数（ENUM_TIMEFRAMES）です [&#8230;]</p>
<p>投稿 <a href="https://mql-programing.com/archives/13071/%e3%80%90mql4%e3%80%91%e6%99%82%e9%96%93%e8%b6%b3%e5%ae%9a%e6%95%b0%ef%bc%88enum_timeframes%ef%bc%89%e5%ae%8c%e5%85%a8%e3%82%ac%e3%82%a4%e3%83%89%ef%bd%9cperiod_m1%e3%80%9cperiod_mn1%e3%81%ae%e4%b8%80/">【MQL4】時間足定数（ENUM_TIMEFRAMES）完全ガイド｜PERIOD_M1〜PERIOD_MN1の一覧と実践的な使い方</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[<p>MQL4でEAやインジケーターを作っていると、「1時間足の移動平均線を取得したい」「日足のローソク足データを参照したい」といった場面が頻繁に出てきます。そんなときに使うのが<strong>時間足定数（ENUM_TIMEFRAMES）</strong>です。</p>
<p>この記事では、MQL4で使える時間足定数をすべて一覧で紹介し、基本的な使い方からマルチタイムフレーム分析への応用まで、実践的なコード例とともに解説します。</p>
<h2><span id="toc1">ENUM_TIMEFRAMESとは？</span></h2>
<p>ENUM_TIMEFRAMESは、MetaTraderのチャート時間足を表す<strong>列挙型（enum）</strong>です。列挙型とは、あらかじめ決められた名前付きの定数をグループ化したもので、「どの時間足か」をプログラム上でわかりやすく指定するために使います。</p>
<p>例えば、1時間足を指定するときに数値の <code>60</code> と書くよりも、<code>PERIOD_H1</code> と書いたほうが圧倒的に読みやすいですよね。これが時間足定数を使う最大のメリットです。</p>
<h2><span id="toc2">時間足定数の一覧（MQL4）</span></h2>
<p>MQL4で使用できる時間足定数は、特殊な <code>PERIOD_CURRENT</code> を含めて全部で<strong>10個</strong>です。以下の表にまとめました。</p>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse: collapse; width: 100%; text-align: center;">
<thead>
<tr style="background-color: #f0f0f0;">
<th>定数名</th>
<th>整数値</th>
<th>意味</th>
<th>1本あたりの秒数</th>
</tr>
</thead>
<tbody>
<tr>
<td>PERIOD_CURRENT</td>
<td>0</td>
<td>現在のチャートの時間足</td>
<td>（チャートに依存）</td>
</tr>
<tr>
<td>PERIOD_M1</td>
<td>1</td>
<td>1分足</td>
<td>60秒</td>
</tr>
<tr>
<td>PERIOD_M5</td>
<td>5</td>
<td>5分足</td>
<td>300秒</td>
</tr>
<tr>
<td>PERIOD_M15</td>
<td>15</td>
<td>15分足</td>
<td>900秒</td>
</tr>
<tr>
<td>PERIOD_M30</td>
<td>30</td>
<td>30分足</td>
<td>1,800秒</td>
</tr>
<tr>
<td>PERIOD_H1</td>
<td>60</td>
<td>1時間足</td>
<td>3,600秒</td>
</tr>
<tr>
<td>PERIOD_H4</td>
<td>240</td>
<td>4時間足</td>
<td>14,400秒</td>
</tr>
<tr>
<td>PERIOD_D1</td>
<td>1440</td>
<td>日足</td>
<td>86,400秒</td>
</tr>
<tr>
<td>PERIOD_W1</td>
<td>10080</td>
<td>週足</td>
<td>604,800秒</td>
</tr>
<tr>
<td>PERIOD_MN1</td>
<td>43200</td>
<td>月足</td>
<td>約2,592,000秒</td>
</tr>
</tbody>
</table>
<p>MQL4の整数値は<strong>「分」を基準</strong>にしています。例えば PERIOD_H1 は60分なので整数値が60、PERIOD_D1 は1440分（24時間×60分）なので1440です。この規則を覚えておくと、値の意味がすぐに理解できます。</p>
<h2><span id="toc3">MQL5との違いに注意</span></h2>
<p>MQL4からMQL5へコードを移植する際に、最もハマりやすいポイントの一つがこの時間足定数の整数値の違いです。</p>
<p>MQL5ではビットシフトを用いた全く異なる整数値が割り当てられています。</p>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse: collapse; width: 100%; text-align: center;">
<thead>
<tr style="background-color: #f0f0f0;">
<th>定数名</th>
<th>MQL4の整数値</th>
<th>MQL5の整数値</th>
</tr>
</thead>
<tbody>
<tr>
<td>PERIOD_M1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>PERIOD_M5</td>
<td>5</td>
<td>5</td>
</tr>
<tr>
<td>PERIOD_H1</td>
<td>60</td>
<td>16385</td>
</tr>
<tr>
<td>PERIOD_D1</td>
<td>1440</td>
<td>16408</td>
</tr>
<tr>
<td>PERIOD_W1</td>
<td>10080</td>
<td>32769</td>
</tr>
<tr>
<td>PERIOD_MN1</td>
<td>43200</td>
<td>49153</td>
</tr>
</tbody>
</table>
<p>分足（M1〜M30）まではMQL4とMQL5で同じ値ですが、<strong>H1以上は完全に異なります</strong>。定数名（PERIOD_H1など）を使っていれば問題ありませんが、整数値をハードコードしていると移植時にバグの原因になります。常に定数名を使う習慣をつけましょう。</p>
<h2><span id="toc4">基本的な使い方</span></h2>
<h3><span id="toc5">iMA()で別の時間足の移動平均線を取得する</span></h3>
<p>最もよく使うパターンが、<code>iMA()</code> などのテクニカル指標関数に時間足を指定するケースです。</p>
<pre><code class="language-mql4">// 現在の通貨ペアの1時間足で、20期間の単純移動平均線を取得
double ma_h1 = iMA(NULL, PERIOD_H1, 20, 0, MODE_SMA, PRICE_CLOSE, 0);

// 日足の20期間移動平均線を取得
double ma_d1 = iMA(NULL, PERIOD_D1, 20, 0, MODE_SMA, PRICE_CLOSE, 0);
</code></pre>
<p>第1引数の <code>NULL</code> は現在の通貨ペアを意味し、第2引数に時間足定数を指定します。</p>
<h3><span id="toc6">iClose()で別の時間足の終値を取得する</span></h3>
<pre><code class="language-mql4">// 日足の1本前（昨日）の終値を取得
double yesterday_close = iClose(NULL, PERIOD_D1, 1);

// 4時間足の現在のバーの始値を取得
double h4_open = iOpen(NULL, PERIOD_H4, 0);
</code></pre>
<h3><span id="toc7">Period()で現在の時間足を取得する</span></h3>
<pre><code class="language-mql4">// 現在のチャートの時間足を取得
int current_tf = Period();

// 現在の時間足が1時間足かどうか判定
if(Period() == PERIOD_H1)
{
    Print("現在のチャートは1時間足です");
}
</code></pre>
<p><code>Period()</code> 関数は現在のチャートの時間足を整数値で返します。PERIOD_CURRENTを指定したときと同じ時間足のデータが取得されます。</p>
<h2><span id="toc8">実践テクニック</span></h2>
<h3><span id="toc9">inputパラメーターでドロップダウン選択にする</span></h3>
<p>EAのパラメーターに <code>ENUM_TIMEFRAMES</code> 型を使うと、MetaTraderのパラメーター設定画面で<strong>ドロップダウンリストから時間足を選択</strong>できるようになります。これは非常に便利なテクニックです。</p>
<pre><code class="language-mql4">input ENUM_TIMEFRAMES InpTimeframe = PERIOD_H1; // 分析する時間足
input int             InpMAPeriod  = 20;         // 移動平均線の期間

void OnTick()
{
    double ma = iMA(NULL, InpTimeframe, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
    // ユーザーが選択した時間足のMAを使って売買判断
}
</code></pre>
<p>ユーザーが数値を手入力する必要がなく、選択ミスも防げるので、EA配布時にも親切な設計になります。</p>
<h3><span id="toc10">PeriodSeconds()で時間足を秒数に変換する</span></h3>
<pre><code class="language-mql4">// 現在の時間足の1本あたりの秒数を取得
int seconds = PeriodSeconds(PERIOD_H1);
Print("1時間足の1本 = ", seconds, "秒"); // 3600秒

// 引数を省略すると現在のチャートの時間足が使われる
int current_seconds = PeriodSeconds();
</code></pre>
<p>時間計算を行う場面（例：「次のバーが生成されるまで何秒か」など）で非常に役立ちます。</p>
<h3><span id="toc11">マルチタイムフレーム分析のEAサンプル</span></h3>
<p>実践的な例として、日足のトレンド方向を確認してからエントリーする簡易EAのロジックを紹介します。</p>
<pre><code class="language-mql4">input ENUM_TIMEFRAMES InpEntryTF  = PERIOD_H1;  // エントリー判断の時間足
input ENUM_TIMEFRAMES InpFilterTF = PERIOD_D1;  // トレンドフィルターの時間足
input int             InpMAPeriod = 20;          // MA期間

void OnTick()
{
    // 上位足（日足）のMAでトレンド方向を判定
    double ma_filter = iMA(NULL, InpFilterTF, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
    double price_filter = iClose(NULL, InpFilterTF, 0);
    
    bool uptrend   = (price_filter > ma_filter);
    bool downtrend = (price_filter < ma_filter);
    
    // エントリー足のMAでエントリーシグナルを判定
    double ma_entry = iMA(NULL, InpEntryTF, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
    double price_entry = iClose(NULL, InpEntryTF, 0);
    
    // 日足が上昇トレンド かつ 1時間足で価格がMAを上抜け → 買いシグナル
    if(uptrend &#038;&#038; price_entry > ma_entry)
    {
        // 買い注文のロジック
        Print("買いシグナル検出！");
    }
    
    // 日足が下降トレンド かつ 1時間足で価格がMAを下抜け → 売りシグナル
    if(downtrend && price_entry < ma_entry)
    {
        // 売り注文のロジック
        Print("売りシグナル検出！");
    }
}
</code></pre>
<p>このように、時間足定数を活用すれば<strong>マルチタイムフレーム分析</strong>のロジックを簡潔に書くことができます。</p>
<h2><span id="toc12">よくある注意点・トラブル</span></h2>
<h3><span id="toc13">整数値の直書きは避ける</span></h3>
<p>以下のように整数値を直接書くのは避けましょう。</p>
<pre><code class="language-mql4">// &#x274c; 悪い例：何を意味しているのかわかりにくい
double ma = iMA(NULL, 60, 20, 0, MODE_SMA, PRICE_CLOSE, 0);

// &#x2705; 良い例：PERIOD_H1と書けば一目で1時間足とわかる
double ma = iMA(NULL, PERIOD_H1, 20, 0, MODE_SMA, PRICE_CLOSE, 0);
</code></pre>
<p>可読性が下がるだけでなく、MQL5へ移植する際にバグの原因になります。</p>
<h3><span id="toc14">ヒストリーデータ不足に注意</span></h3>
<p>別の時間足のデータを参照するとき、MetaTraderにその時間足の<strong>ヒストリーデータが十分にダウンロードされていない</strong>場合があります。特にバックテスト時に、上位足のデータが不足していると正しい結果が得られません。</p>
<p>必要な時間足のチャートを一度開いてデータを読み込ませるか、スクリプトで事前にデータの存在を確認する処理を入れておくと安心です。</p>
<h3><span id="toc15">PERIOD_CURRENTと0の違い</span></h3>
<p><code>PERIOD_CURRENT</code> の整数値は <code>0</code> です。関数に <code>0</code> を渡しても <code>PERIOD_CURRENT</code> を渡しても同じ動作になりますが、コードの意図を明確にするために <code>PERIOD_CURRENT</code> を使うことをおすすめします。</p>
<h2><span id="toc16">まとめ</span></h2>
<p>MQL4の時間足定数（ENUM_TIMEFRAMES）について、重要なポイントを整理します。</p>
<ul>
<li><strong>PERIOD_M1〜PERIOD_MN1</strong>の9つの時間足定数と、<strong>PERIOD_CURRENT</strong>（現在のチャートの時間足）が使える</li>
<li>MQL4の整数値は<strong>「分」が基準</strong>（H1=60, D1=1440など）</li>
<li>MQL5では<strong>H1以上の整数値が全く異なる</strong>ため、移植時は必ず定数名を使う</li>
<li><code>input ENUM_TIMEFRAMES</code> でパラメーター化すると、<strong>ドロップダウン選択</strong>が自動生成されて便利</li>
<li><code>PeriodSeconds()</code> で時間足を秒数に変換でき、時間計算に活用できる</li>
<li>マルチタイムフレーム分析では、上位足のデータ（ヒストリー）が十分にあるか確認が必要</li>
</ul>
<p>時間足定数はEA開発で日常的に使う基本中の基本です。まずは <code>iMA()</code> や <code>iClose()</code> に異なる時間足を指定するところから試してみてください。マルチタイムフレーム分析ができるようになると、EA戦略の幅が大きく広がりますよ！</p>
<p>投稿 <a href="https://mql-programing.com/archives/13071/%e3%80%90mql4%e3%80%91%e6%99%82%e9%96%93%e8%b6%b3%e5%ae%9a%e6%95%b0%ef%bc%88enum_timeframes%ef%bc%89%e5%ae%8c%e5%85%a8%e3%82%ac%e3%82%a4%e3%83%89%ef%bd%9cperiod_m1%e3%80%9cperiod_mn1%e3%81%ae%e4%b8%80/">【MQL4】時間足定数（ENUM_TIMEFRAMES）完全ガイド｜PERIOD_M1〜PERIOD_MN1の一覧と実践的な使い方</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【MQL4】グローバル変数関数の使い方を徹底解説！GlobalVariableSet / Get / Check / Del</title>
		<link>https://mql-programing.com/archives/13068/%e3%80%90mql4%e3%80%91%e3%82%b0%e3%83%ad%e3%83%bc%e3%83%90%e3%83%ab%e5%a4%89%e6%95%b0%e9%96%a2%e6%95%b0%e3%81%ae%e4%bd%bf%e3%81%84%e6%96%b9%e3%82%92%e5%be%b9%e5%ba%95%e8%a7%a3%e8%aa%ac%ef%bc%81globalv/</link>
		
		<dc:creator><![CDATA[朝日奈りさ]]></dc:creator>
		<pubDate>Fri, 24 Apr 2026 01:00:00 +0000</pubDate>
				<category><![CDATA[【辞書】MQLリファレンス]]></category>
		<category><![CDATA[変数]]></category>
		<category><![CDATA[MQL4]]></category>
		<category><![CDATA[EA開発]]></category>
		<category><![CDATA[グローバル変数]]></category>
		<category><![CDATA[GlobalVariableSet]]></category>
		<category><![CDATA[MetaTrader4]]></category>
		<guid isPermaLink="false">https://mql-programing.com/?p=13068</guid>

					<description><![CDATA[<p>MQL4でEA（自動売買プログラム）やインジケーターを開発していると、「MT4を再起動しても値を保持しておきたい」「複数のEA間でデータを共有したい」という場面に遭遇します。そんなときに活躍するのが、クライアントターミナ [&#8230;]</p>
<p>投稿 <a href="https://mql-programing.com/archives/13068/%e3%80%90mql4%e3%80%91%e3%82%b0%e3%83%ad%e3%83%bc%e3%83%90%e3%83%ab%e5%a4%89%e6%95%b0%e9%96%a2%e6%95%b0%e3%81%ae%e4%bd%bf%e3%81%84%e6%96%b9%e3%82%92%e5%be%b9%e5%ba%95%e8%a7%a3%e8%aa%ac%ef%bc%81globalv/">【MQL4】グローバル変数関数の使い方を徹底解説！GlobalVariableSet / Get / Check / Del</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[<p>MQL4でEA（自動売買プログラム）やインジケーターを開発していると、「MT4を再起動しても値を保持しておきたい」「複数のEA間でデータを共有したい」という場面に遭遇します。そんなときに活躍するのが、<strong>クライアントターミナルのグローバル変数</strong>（以下「ターミナルグローバル変数」）です。</p>
<p>この記事では、ターミナルグローバル変数を操作するための主要関数 ── <code>GlobalVariableSet</code>、<code>GlobalVariableGet</code>、<code>GlobalVariableCheck</code>、<code>GlobalVariableDel</code> を中心に、使い方と注意点をわかりやすく解説します。</p>
<h2><span id="toc1">ターミナルグローバル変数とは？── 2種類の「グローバル変数」に注意</span></h2>
<p>MQL4には「グローバル変数」と呼ばれるものが<strong>2種類</strong>あります。ここを混同すると大きな混乱のもとになるので、最初にしっかり区別しましょう。</p>
<h3><span id="toc2">① MQL4プログラム内のグローバル変数</span></h3>
<p>関数の外（<code>OnInit()</code>や<code>OnTick()</code>の外側）で宣言する変数のことです。プログラム全体からアクセスできますが、<strong>EAをチャートから外したりMT4を終了すると値は消えます</strong>。</p>
<pre><code class="language-mql5">// プログラム内グローバル変数の例
int g_tickCount = 0;  // プログラム内のどの関数からもアクセス可能

void OnTick()
{
    g_tickCount++;
    Print("ティック回数: ", g_tickCount);
}
</code></pre>
<h3><span id="toc3">② クライアントターミナルのグローバル変数（本記事の主役）</span></h3>
<p>MT4のメニュー「ツール → グローバル変数」（ショートカット：F3キー）で確認できる変数です。こちらは<strong>MT4を終了してもデータが保持</strong>されます。さらに、同じMT4上で動作している<strong>すべてのEA・インジケーターからアクセス可能</strong>なので、プログラム間のデータ共有にも使えます。</p>
<p>ターミナルグローバル変数の特徴をまとめると、次のとおりです。</p>
<ul>
<li><strong>データ型は double 型のみ</strong>（文字列や整数を直接格納することはできません）</li>
<li><strong>最後のアクセスから4週間</strong>保持され、その後は自動的に削除される</li>
<li>同一MT4上の全MQL4プログラムからアクセス可能</li>
<li><code>GlobalVariable</code>系の専用関数を使って操作する</li>
</ul>
<h2><span id="toc4">主要なグローバル変数関数一覧</span></h2>
<p>以下が、ターミナルグローバル変数を操作するための主要関数です。</p>
<table border="1" cellpadding="8" cellspacing="0" style="border-collapse: collapse; width: 100%;">
<thead>
<tr style="background-color: #f0f0f0;">
<th>関数名</th>
<th>機能</th>
<th>戻り値</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>GlobalVariableSet()</code></td>
<td>値を設定（存在しなければ新規作成）</td>
<td>datetime（最終アクセス時刻）/ 0（失敗）</td>
</tr>
<tr>
<td><code>GlobalVariableGet()</code></td>
<td>値を取得</td>
<td>double（格納されている値）</td>
</tr>
<tr>
<td><code>GlobalVariableCheck()</code></td>
<td>変数の存在を確認</td>
<td>true（存在する）/ false（存在しない）</td>
</tr>
<tr>
<td><code>GlobalVariableDel()</code></td>
<td>変数を削除</td>
<td>true（成功）/ false（失敗）</td>
</tr>
<tr>
<td><code>GlobalVariablesTotal()</code></td>
<td>変数の総数を取得</td>
<td>int（変数の数）</td>
</tr>
<tr>
<td><code>GlobalVariablesDeleteAll()</code></td>
<td>変数を一括削除</td>
<td>int（削除された数）</td>
</tr>
<tr>
<td><code>GlobalVariableName()</code></td>
<td>インデックスから変数名を取得</td>
<td>string（変数名）</td>
</tr>
</tbody>
</table>
<p>この中でも特に使用頻度の高い4つの関数を、コード例とともに詳しく見ていきましょう。</p>
<h2><span id="toc5">GlobalVariableSet() ── 値の設定・新規作成</span></h2>
<p>ターミナルグローバル変数に値を設定する関数です。指定した名前の変数が存在しない場合は、<strong>自動的に新しい変数が作成</strong>されます。</p>
<pre><code class="language-mql5">// 構文
datetime GlobalVariableSet(
    string name,   // グローバル変数名
    double value   // 設定する値
);
</code></pre>
<p>戻り値は、成功した場合に<strong>最終アクセス時刻（datetime型）</strong>、失敗した場合に<strong>0</strong>が返ります。</p>
<pre><code class="language-mql5">void OnInit()
{
    // グローバル変数 "MyEA_BuyPrice" に値を設定
    datetime dt = GlobalVariableSet("MyEA_BuyPrice", 150.250);
    
    if(dt != 0)
        Print("設定成功！ アクセス時刻: ", TimeToString(dt));
    else
        Print("設定失敗。エラー: ", GetLastError());
}
</code></pre>
<h2><span id="toc6">GlobalVariableGet() ── 値の取得</span></h2>
<p>ターミナルグローバル変数から値を読み取る関数です。戻り値は<strong>double型</strong>です。</p>
<pre><code class="language-mql5">// 構文
double GlobalVariableGet(
    string name   // グローバル変数名
);
</code></pre>
<p>指定した名前の変数が存在しない場合は<strong>0が返り</strong>、エラーコードがセットされます。</p>
<pre><code class="language-mql5">void OnTick()
{
    double buyPrice = GlobalVariableGet("MyEA_BuyPrice");
    
    if(GetLastError() == 0)
        Print("保存されていた買値: ", buyPrice);
    else
        Print("グローバル変数が見つかりません");
}
</code></pre>
<p><strong>&#x1f4a1; ポイント：</strong>戻り値が0なのか、それとも「本当に0が格納されている」のか区別がつかない場合があります。確実に存在を確認したい場合は、次に紹介する <code>GlobalVariableCheck()</code> と組み合わせましょう。</p>
<h2><span id="toc7">GlobalVariableCheck() ── 存在の確認</span></h2>
<p>指定した名前のターミナルグローバル変数が存在するかどうかを確認する関数です。</p>
<pre><code class="language-mql5">// 構文
bool GlobalVariableCheck(
    string name   // グローバル変数名
);
</code></pre>
<p>変数が存在する場合は <code>true</code>、存在しない場合は <code>false</code> を返します。</p>
<pre><code class="language-mql5">void OnInit()
{
    string gvName = "MyEA_BuyPrice";
    
    // 変数が存在するか先に確認してから値を取得する
    if(GlobalVariableCheck(gvName))
    {
        double val = GlobalVariableGet(gvName);
        Print(gvName, " の値: ", val);
    }
    else
    {
        Print(gvName, " は存在しません。初期値を設定します。");
        GlobalVariableSet(gvName, 0.0);
    }
}
</code></pre>
<p>このように、<code>GlobalVariableCheck()</code> → <code>GlobalVariableGet()</code> の順で呼び出すのが安全なパターンです。</p>
<h2><span id="toc8">GlobalVariableDel() ── 変数の削除</span></h2>
<p>不要になったターミナルグローバル変数を削除する関数です。</p>
<pre><code class="language-mql5">// 構文
bool GlobalVariableDel(
    string name   // グローバル変数名
);
</code></pre>
<p>削除に成功した場合は <code>true</code>、失敗した場合は <code>false</code> を返します。</p>
<pre><code class="language-mql5">void OnDeinit(const int reason)
{
    // EA終了時にグローバル変数をクリーンアップ
    if(GlobalVariableDel("MyEA_BuyPrice"))
        Print("グローバル変数を削除しました");
    else
        Print("削除失敗。エラー: ", GetLastError());
}
</code></pre>
<h2><span id="toc9">実践例：EA再起動後もポジション情報を保持する</span></h2>
<p>ここまでの関数を組み合わせた実践的なサンプルを見てみましょう。EAがポジションを持ったときにチケット番号をターミナルグローバル変数に保存し、MT4再起動後でも管理を継続できるようにします。</p>
<pre><code class="language-mql5">#property strict

// EA固有のプレフィックスをつけて名前衝突を防ぐ
string gvPrefix = "SampleEA_";

//+------------------------------------------------------------------+
//| 初期化処理                                                        |
//+------------------------------------------------------------------+
void OnInit()
{
    string gvTicket = gvPrefix + Symbol() + "_Ticket";
    
    // 前回保存したチケット番号があるか確認
    if(GlobalVariableCheck(gvTicket))
    {
        int ticket = (int)GlobalVariableGet(gvTicket);
        if(ticket > 0)
        {
            Print("前回のチケット番号を復元: ", ticket);
            // 必要に応じてポジション情報を再取得する処理を追加
        }
    }
    else
    {
        Print("保存済みチケットなし。新規稼働を開始します。");
    }
}

//+------------------------------------------------------------------+
//| ティック処理                                                      |
//+------------------------------------------------------------------+
void OnTick()
{
    string gvTicket = gvPrefix + Symbol() + "_Ticket";
    
    // 新規注文を出す処理（簡略化）
    int ticket = OrderSend(Symbol(), OP_BUY, 0.01, Ask, 3, 0, 0, "SampleEA", 12345, 0, clrBlue);
    
    if(ticket > 0)
    {
        // チケット番号をグローバル変数に保存
        GlobalVariableSet(gvTicket, (double)ticket);
        Print("チケット ", ticket, " をグローバル変数に保存しました");
    }
}

//+------------------------------------------------------------------+
//| 終了処理                                                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // パラメータ変更やチャート切替時はデータを保持
    // 手動削除(REASON_REMOVE)の場合のみクリーンアップ
    if(reason == REASON_REMOVE)
    {
        string gvTicket = gvPrefix + Symbol() + "_Ticket";
        GlobalVariableDel(gvTicket);
        Print("EA削除のため、グローバル変数をクリーンアップしました");
    }
}
</code></pre>
<h2><span id="toc10">グローバル変数を使うときの注意点</span></h2>
<h3><span id="toc11">1. 名前の衝突に注意 ── プレフィックスをつけよう</span></h3>
<p>ターミナルグローバル変数は同じMT4上の<strong>全プログラムで共有</strong>されます。異なるEAが同じ名前の変数を使うと、互いに値を上書きしてしまい不具合の原因になります。上のサンプルのように、<strong>EA名＋通貨ペア名をプレフィックスとしてつける</strong>のがベストプラクティスです。</p>
<h3><span id="toc12">2. 格納できるのは double 型のみ</span></h3>
<p>ターミナルグローバル変数に格納できるのは<strong>double型の値だけ</strong>です。整数（int）を保存したい場合はキャストが必要です。また、<strong>long型の大きな値</strong>（例：チャートIDなど）を格納すると、doubleの精度の問題で値が正確に復元できないことがあるので注意が必要です。</p>
<h3><span id="toc13">3. 4週間でデータが消える</span></h3>
<p>クライアントターミナルのグローバル変数は、最後のアクセスから4週間クライアントターミナルに保持され、その後自動的に削除されます。長期間EAを停止する場合は、この点を意識しておきましょう。定期的にアクセス（読み書き）すればタイマーはリセットされます。</p>
<h3><span id="toc14">4. 不要な変数は削除する</span></h3>
<p>使わなくなったグローバル変数を放置すると、F3キーで確認したときに一覧が煩雑になります。EA終了時に適切に <code>GlobalVariableDel()</code> で削除するか、<code>GlobalVariablesDeleteAll()</code> でプレフィックス指定の一括削除を行いましょう。</p>
<pre><code class="language-mql5">// プレフィックスを指定して一括削除
int deleted = GlobalVariablesDeleteAll("SampleEA_");
Print(deleted, " 個のグローバル変数を削除しました");
</code></pre>
<h2><span id="toc15">補足：その他の便利な関数</span></h2>
<p>主要4関数以外にも、覚えておくと便利な関数を紹介します。</p>
<ul>
<li><strong><code>GlobalVariablesTotal()</code></strong> ── 現在のターミナルグローバル変数の総数を取得</li>
<li><strong><code>GlobalVariableName(index)</code></strong> ── インデックス番号から変数名を取得（ループで全変数を列挙する際に便利）</li>
<li><strong><code>GlobalVariableSetOnCondition()</code></strong> ── 現在値が指定値と一致する場合のみ更新する（排他制御に利用可能）</li>
<li><strong><code>GlobalVariableTemp()</code></strong> ── MT4終了時に自動削除される一時的なグローバル変数を作成</li>
<li><strong><code>GlobalVariablesFlush()</code></strong> ── メモリ上のグローバル変数をディスクに強制保存</li>
</ul>
<h2><span id="toc16">まとめ</span></h2>
<p>ターミナルグローバル変数は、MQL4プログラミングにおいて<strong>データの永続化やプログラム間のデータ共有</strong>を実現するための重要な仕組みです。今回紹介した4つの基本関数を押さえておけば、多くの場面で活用できます。</p>
<ul>
<li><code>GlobalVariableSet()</code> で値を保存</li>
<li><code>GlobalVariableGet()</code> で値を取得</li>
<li><code>GlobalVariableCheck()</code> で存在を確認</li>
<li><code>GlobalVariableDel()</code> で不要な変数を削除</li>
</ul>
<p>名前の衝突を避けるためにプレフィックスをつけること、double型しか格納できないこと、4週間の有効期限があることを忘れずに、安全で堅牢なEA開発に役立ててください！</p>
<p>**記事のポイント：**</p>
<p>| 項目 | 内容 |</p>
<p>|&#8212;|&#8212;|</p>
<p>| **タイトル** | 【MQL4】グローバル変数関数の使い方を徹底解説！GlobalVariableSet / Get / Check / Del |</p>
<p>| **タグ** | MQL4, グローバル変数, GlobalVariableSet, EA開発, MetaTrader4 |</p>
<p>| **文字数** | 約8,900文字（HTML含む） / 本文テキスト約3,000文字相当 |</p>
<p>| **構成** | 導入 → 2種類のグローバル変数の区別 → 関数一覧表 → 4関数の詳細解説（構文＋コード例） → 実践サンプル → 注意点4つ → 補足関数 → まとめ |</p>
<p>記事の特徴：</p>
<p>&#8211; **初心者が最も混同しやすい「2種類のグローバル変数」の違い**を冒頭で明確に解説</p>
<p>&#8211; 各関数に**構文・戻り値・実用コードサンプル**を掲載</p>
<p>&#8211; **実践例**として「EA再起動後もチケット番号を保持する」リアルなユースケースを提示</p>
<p>&#8211; **注意点**では名前衝突・double型制限・4週間有効期限・long型精度問題など、実開発で陥りやすい落とし穴をカバー</p>
<p>&#8211; 補足として `GlobalVariableSetOnCondition` や `GlobalVariableTemp` など発展的な関数も紹介</p>
<p>投稿 <a href="https://mql-programing.com/archives/13068/%e3%80%90mql4%e3%80%91%e3%82%b0%e3%83%ad%e3%83%bc%e3%83%90%e3%83%ab%e5%a4%89%e6%95%b0%e9%96%a2%e6%95%b0%e3%81%ae%e4%bd%bf%e3%81%84%e6%96%b9%e3%82%92%e5%be%b9%e5%ba%95%e8%a7%a3%e8%aa%ac%ef%bc%81globalv/">【MQL4】グローバル変数関数の使い方を徹底解説！GlobalVariableSet / Get / Check / Del</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【MQL4】知っておきたいユーティリティ関数6選！Sleep・RefreshRates・IsTradeAllowed・IsConnected・IsTesting・IsOptimizationの使い方</title>
		<link>https://mql-programing.com/archives/13065/%e3%80%90mql4%e3%80%91%e7%9f%a5%e3%81%a3%e3%81%a6%e3%81%8a%e3%81%8d%e3%81%9f%e3%81%84%e3%83%a6%e3%83%bc%e3%83%86%e3%82%a3%e3%83%aa%e3%83%86%e3%82%a3%e9%96%a2%e6%95%b06%e9%81%b8%ef%bc%81sleep%e3%83%bbr/</link>
		
		<dc:creator><![CDATA[朝日奈りさ]]></dc:creator>
		<pubDate>Thu, 23 Apr 2026 01:00:00 +0000</pubDate>
				<category><![CDATA[【中級編】MQLプログラムの読み方・書き方]]></category>
		<category><![CDATA[バックテスト]]></category>
		<category><![CDATA[MQL4]]></category>
		<category><![CDATA[EA開発]]></category>
		<category><![CDATA[ユーティリティ関数]]></category>
		<category><![CDATA[Sleep]]></category>
		<guid isPermaLink="false">https://mql-programing.com/?p=13065</guid>

					<description><![CDATA[<p>EA（自動売買プログラム）を作っていると、「注文を出す前にサーバーと接続できているか確認したい」「バックテスト中は処理を軽くしたい」といった場面に必ず出くわします。こうした場面で活躍するのが、MQL4に用意されたユーティ [&#8230;]</p>
<p>投稿 <a href="https://mql-programing.com/archives/13065/%e3%80%90mql4%e3%80%91%e7%9f%a5%e3%81%a3%e3%81%a6%e3%81%8a%e3%81%8d%e3%81%9f%e3%81%84%e3%83%a6%e3%83%bc%e3%83%86%e3%82%a3%e3%83%aa%e3%83%86%e3%82%a3%e9%96%a2%e6%95%b06%e9%81%b8%ef%bc%81sleep%e3%83%bbr/">【MQL4】知っておきたいユーティリティ関数6選！Sleep・RefreshRates・IsTradeAllowed・IsConnected・IsTesting・IsOptimizationの使い方</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[<p>EA（自動売買プログラム）を作っていると、「注文を出す前にサーバーと接続できているか確認したい」「バックテスト中は処理を軽くしたい」といった場面に必ず出くわします。こうした場面で活躍するのが、MQL4に用意された<strong>ユーティリティ関数</strong>たちです。</p>
<p>今回は、EA開発で特に使用頻度が高い以下の<strong>6つのユーティリティ関数</strong>をまとめて解説します。</p>
<ul>
<li><strong>Sleep()</strong> — 処理の一時停止</li>
<li><strong>RefreshRates()</strong> — 価格データの最新化</li>
<li><strong>IsTradeAllowed()</strong> — 自動売買の許可状態を確認</li>
<li><strong>IsConnected()</strong> — サーバー接続の確認</li>
<li><strong>IsTesting()</strong> — バックテスト中かどうかの判定</li>
<li><strong>IsOptimization()</strong> — 最適化モードかどうかの判定</li>
</ul>
<p>それぞれの基本的な使い方から、最後に6つすべてを組み合わせた実践テンプレートまで紹介しますので、ぜひ最後までお読みください。</p>
<h2><span id="toc1">Sleep() — ミリ秒単位で処理を一時停止する</span></h2>
<h3><span id="toc2">基本構文</span></h3>
<pre><code class="language-mql4">void Sleep(int milliseconds);
</code></pre>
<p><strong>Sleep()</strong>は、指定したミリ秒（1000ミリ秒＝1秒）だけEAの処理を一時停止する関数です。注文のリトライ処理やサーバーとの通信待ちなどで頻繁に使われます。</p>
<h3><span id="toc3">使用例：注文失敗時のリトライ</span></h3>
<p>注文送信が失敗した場合、少し間をおいてからリトライするのが一般的なパターンです。</p>
<pre><code class="language-mql4">int ticket = -1;
int retryCount = 3;

for(int i = 0; i < retryCount; i++)
{
    ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "Buy Order", 0, 0, clrBlue);

    if(ticket > 0)
    {
        Print("注文成功！ チケット番号: ", ticket);
        break;
    }
    else
    {
        int err = GetLastError();
        Print("注文失敗（", i + 1, "回目） エラー: ", err);
        Sleep(1000);  // 1秒待ってからリトライ
    }
}
</code></pre>
<h3><span id="toc4">Sleep()の注意点</span></h3>
<ul>
<li><strong>ストラテジーテスターでは無視されます。</strong>バックテスト中にSleep()を呼んでも、実際には一時停止しません。テスト速度に影響を与えないための仕様です。</li>
<li>Sleep()の内部では<strong>約0.1秒ごと</strong>にEAの停止フラグがチェックされています。そのため、Sleep(10000)（10秒停止）を実行中でも、ユーザーがEAを停止すれば比較的すぐに処理が終了します。</li>
<li>カスタムインジケーターの中では使用できません。EAおよびスクリプト専用の関数です。</li>
</ul>
<h2><span id="toc5">RefreshRates() — 価格データを最新の状態に更新する</span></h2>
<h3><span id="toc6">基本構文</span></h3>
<pre><code class="language-mql4">bool RefreshRates();
</code></pre>
<p><strong>RefreshRates()</strong>は、Bid、Ask、Volumeなどの定義済み変数を最新のサーバーデータに更新する関数です。更新に成功するとtrueを返します。</p>
<h3><span id="toc7">なぜRefreshRates()が必要なのか</span></h3>
<p>EAの<code>OnTick()</code>が呼び出された瞬間に、BidやAskには最新の値がセットされます。しかし、その後にSleep()で待機したり、重い計算処理を行ったりすると、BidやAskの値が古くなってしまう可能性があります。</p>
<p>つまり、<strong>Sleep()の後にはRefreshRates()を呼ぶのが鉄則</strong>です。</p>
<h3><span id="toc8">使用例：Sleep()とRefreshRates()のセット</span></h3>
<pre><code class="language-mql4">// 注文失敗 → 待機 → 価格を更新してリトライ
Sleep(1000);
RefreshRates();  // Bid/Askを最新に更新

// 更新後のAskで再度注文
ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "Retry Order", 0, 0, clrBlue);
</code></pre>
<p>RefreshRates()を呼ばずに古いAsk値で注文を出すと、「Off quotes（無効な価格）」エラーが発生する原因になります。注意しましょう。</p>
<h2><span id="toc9">IsTradeAllowed() — 自動売買が許可されているか確認する</span></h2>
<h3><span id="toc10">基本構文</span></h3>
<pre><code class="language-mql4">bool IsTradeAllowed();
</code></pre>
<p><strong>IsTradeAllowed()</strong>は、EAによる自動売買が許可されている場合にtrueを返す関数です。具体的には、以下の2つの条件を確認しています。</p>
<ul>
<li>MetaTraderのツールバーにある<strong>「自動売買」ボタンがON</strong>になっているか</li>
<li>他のEAやスクリプトが取引コンテキストを使用中（ビジー状態）でないか</li>
</ul>
<h3><span id="toc11">使用例：注文前の安全チェック</span></h3>
<pre><code class="language-mql4">void OnTick()
{
    // 自動売買が許可されていなければ何もしない
    if(!IsTradeAllowed())
    {
        Print("自動売買が無効です。ツールバーの自動売買ボタンを確認してください。");
        return;
    }

    // ここから注文ロジック
    // ...
}
</code></pre>
<h3><span id="toc12">取引コンテキストのビジー状態に対処する</span></h3>
<p>同一のMetaTrader上で複数のEAが動作している場合、1つのEAが注文処理を行っている間は他のEAの取引がブロックされます。このような場合は、少し待ってから再確認するのが有効です。</p>
<pre><code class="language-mql4">// 取引コンテキストが空くまで待機（最大5秒）
for(int i = 0; i < 10; i++)
{
    if(IsTradeAllowed())
        break;

    Print("取引コンテキストがビジー状態です。待機中...");
    Sleep(500);
}
</code></pre>
<h2><span id="toc13">IsConnected() — サーバーとの接続状態を確認する</span></h2>
<h3><span id="toc14">基本構文</span></h3>
<pre><code class="language-mql4">bool IsConnected();
</code></pre>
<p><strong>IsConnected()</strong>は、MetaTraderクライアントがブローカーのサーバーと接続されている場合にtrueを返す関数です。</p>
<h3><span id="toc15">使用例：接続チェック</span></h3>
<pre><code class="language-mql4">void OnTick()
{
    if(!IsConnected())
    {
        Print("サーバーに接続されていません！ 注文処理をスキップします。");
        return;
    }

    // 接続確認OK → 通常の処理へ
}
</code></pre>
<h3><span id="toc16">VPS運用時に特に重要</span></h3>
<p>VPS（仮想専用サーバー）でEAを24時間稼働させている場合、ネットワークの一時的な切断は避けられません。IsConnected()で接続状態をチェックし、切断時にはアラートを出すなどの処理を組み込んでおくと安心です。</p>
<pre><code class="language-mql4">static datetime lastAlertTime = 0;

if(!IsConnected())
{
    // 5分に1回だけアラート
    if(TimeCurrent() - lastAlertTime > 300)
    {
        Alert("サーバー接続が切断されています！");
        lastAlertTime = TimeCurrent();
    }
    return;
}
</code></pre>
<h2><span id="toc17">IsTesting() — バックテスト中かどうかを判定する</span></h2>
<h3><span id="toc18">基本構文</span></h3>
<pre><code class="language-mql4">bool IsTesting();
</code></pre>
<p><strong>IsTesting()</strong>は、EAがストラテジーテスター上で動作しているときにtrueを返す関数です。ライブ口座やデモ口座で動かしている場合はfalseになります。</p>
<h3><span id="toc19">使用例：テスト時にGUI処理をスキップして高速化</span></h3>
<p>バックテスト（特にビジュアルモードではない通常テスト）では、画面への描画処理は不要です。Comment()やObjectCreate()といった描画関数をスキップすることで、テスト速度を大幅に向上できます。</p>
<pre><code class="language-mql4">// グローバル変数としてフラグを用意
bool gIsTesting = false;

int OnInit()
{
    // init()内で1度だけ判定すれば十分
    gIsTesting = IsTesting();
    return(INIT_SUCCEEDED);
}

void OnTick()
{
    // テスト中でなければ画面に情報を表示
    if(!gIsTesting)
    {
        Comment("Bid: ", Bid, "  Ask: ", Ask, "  Spread: ", MarketInfo(Symbol(), MODE_SPREAD));
    }

    // 売買ロジック...
}
</code></pre>
<p><strong>ポイント：</strong>IsTesting()の戻り値はEAの実行中に変わることはありません。そのため、<code>OnInit()</code>内で一度だけ判定してグローバル変数に保存すれば十分です。OnTick()のたびに呼び出す必要はなく、わずかですがパフォーマンスの改善につながります。</p>
<h2><span id="toc20">IsOptimization() — 最適化モードかどうかを判定する</span></h2>
<h3><span id="toc21">基本構文</span></h3>
<pre><code class="language-mql4">bool IsOptimization();
</code></pre>
<p><strong>IsOptimization()</strong>は、ストラテジーテスターの最適化モードで実行されているときにtrueを返す関数です。最適化モードでは、パラメータの組み合わせを大量にテストするため、不要な処理を極力省くことが重要になります。</p>
<h3><span id="toc22">使用例：最適化中はPrint()を抑制する</span></h3>
<p>最適化モードでは、<strong>Print()による出力がログに記録されません</strong>。つまり、Print()を呼んでもデバッグの役に立たないだけでなく、処理のオーバーヘッドだけが残ります。</p>
<pre><code class="language-mql4">bool gIsOptimization = false;

int OnInit()
{
    gIsOptimization = IsOptimization();
    return(INIT_SUCCEEDED);
}

void OnTick()
{
    // 最適化中はデバッグ出力をスキップ
    if(!gIsOptimization)
    {
        Print("現在のBid: ", Bid, " Ask: ", Ask);
    }

    // 売買ロジック...
}
</code></pre>
<h3><span id="toc23">IsTesting()との使い分け</span></h3>
<p>IsTesting()とIsOptimization()の関係を整理しておきましょう。</p>
<table>
<thead>
<tr>
<th>状態</th>
<th>IsTesting()</th>
<th>IsOptimization()</th>
</tr>
</thead>
<tbody>
<tr>
<td>ライブ口座 / デモ口座</td>
<td>false</td>
<td>false</td>
</tr>
<tr>
<td>バックテスト（通常）</td>
<td>true</td>
<td>false</td>
</tr>
<tr>
<td>バックテスト（ビジュアルモード）</td>
<td>true</td>
<td>false</td>
</tr>
<tr>
<td>最適化モード</td>
<td>true</td>
<td>true</td>
</tr>
</tbody>
</table>
<p>最適化モードのときはIsTesting()もtrueになります。つまり「IsTesting()がtrueかつIsOptimization()がfalse」であれば通常のバックテスト、「両方ともtrue」であれば最適化中ということになります。</p>
<h2><span id="toc24">実践テンプレート：6つの関数を組み合わせた安全な注文処理</span></h2>
<p>ここまで紹介した6つの関数をすべて組み合わせた、実践的な注文処理テンプレートを紹介します。実際のEA開発でそのまま活用できる構成です。</p>
<pre><code class="language-mql4">//--- グローバル変数
bool gIsTesting      = false;
bool gIsOptimization = false;

//+------------------------------------------------------------------+
//| 初期化関数                                                         |
//+------------------------------------------------------------------+
int OnInit()
{
    // 実行環境フラグを初期化時に1度だけ判定
    gIsTesting      = IsTesting();
    gIsOptimization = IsOptimization();

    if(!gIsOptimization)
        Print("EA初期化完了 テストモード: ", gIsTesting);

    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| 安全な買い注文関数                                                  |
//+------------------------------------------------------------------+
int SafeBuyOrder(double lots, int slippage, double sl, double tp, string comment)
{
    int maxRetry = 3;
    int ticket   = -1;

    //--- 1. サーバー接続チェック（テスト時はスキップ）
    if(!gIsTesting &amp;&amp; !IsConnected())
    {
        Print("エラー: サーバーに接続されていません");
        return(-1);
    }

    //--- 2. 自動売買許可チェック
    if(!IsTradeAllowed())
    {
        Print("エラー: 自動売買が許可されていません");
        return(-1);
    }

    //--- 3. リトライループ
    for(int i = 0; i < maxRetry; i++)
    {
        // 価格データを最新に更新
        RefreshRates();

        // 注文送信
        ticket = OrderSend(Symbol(), OP_BUY, lots, Ask, slippage, sl, tp, comment, 0, 0, clrBlue);

        if(ticket > 0)
        {
            if(!gIsOptimization)
                Print("買い注文成功！ チケット: ", ticket, " 価格: ", Ask);
            break;
        }
        else
        {
            int err = GetLastError();
            if(!gIsOptimization)
                Print("買い注文失敗（", i + 1, "/", maxRetry, "） エラーコード: ", err);

            // 最後のリトライでなければ待機
            if(i < maxRetry - 1)
            {
                Sleep(1000);  // 1秒待機（テスターでは無視される）
            }
        }
    }

    return(ticket);
}

//+------------------------------------------------------------------+
//| ティックごとの処理                                                  |
//+------------------------------------------------------------------+
void OnTick()
{
    //--- 画面表示（通常バックテスト・最適化時はスキップ）
    if(!gIsTesting)
    {
        Comment("EA稼働中 | Bid: ", Bid, " | Ask: ", Ask,
                " | 接続: ", (IsConnected() ? "OK" : "NG"),
                " | 自動売買: ", (IsTradeAllowed() ? "許可" : "不可"));
    }

    //--- ここに売買条件を記述 ---
    // 例: 買い条件を満たしたら注文
    // int ticket = SafeBuyOrder(0.1, 3, 0, 0, "Sample EA");
}

//+------------------------------------------------------------------+
//| 終了処理                                                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    if(!gIsOptimization)
        Print("EA停止 理由コード: ", reason);

    // テスト時でなければコメントをクリア
    if(!gIsTesting)
        Comment("");
}
</code></pre>
<p>このテンプレートでは、以下のポイントを押さえています。</p>
<ul>
<li><strong>OnInit()で環境フラグを一度だけ判定</strong> — IsTesting()やIsOptimization()を毎ティック呼ぶ無駄を排除</li>
<li><strong>注文前にIsConnected()とIsTradeAllowed()をチェック</strong> — 接続切れや自動売買無効時のエラーを未然に防止</li>
<li><strong>リトライ時にSleep() + RefreshRates()をセットで使用</strong> — 待機後に最新価格を取得してから再注文</li>
<li><strong>最適化中はPrint()をスキップ</strong> — 不要な処理のオーバーヘッドを削減</li>
<li><strong>テスト中はComment()による画面描画をスキップ</strong> — バックテストの高速化</li>
</ul>
<h2><span id="toc25">まとめ</span></h2>
<p>今回紹介した6つのユーティリティ関数を一覧表で振り返りましょう。</p>
<table>
<thead>
<tr>
<th>関数名</th>
<th>用途</th>
<th>主な使いどころ</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sleep()</td>
<td>処理の一時停止</td>
<td>注文リトライ時の待機</td>
</tr>
<tr>
<td>RefreshRates()</td>
<td>価格データの更新</td>
<td>Sleep()の後、重い計算の後</td>
</tr>
<tr>
<td>IsTradeAllowed()</td>
<td>自動売買許可の確認</td>
<td>注文送信前のチェック</td>
</tr>
<tr>
<td>IsConnected()</td>
<td>サーバー接続の確認</td>
<td>注文送信前、VPS運用時</td>
</tr>
<tr>
<td>IsTesting()</td>
<td>バックテスト判定</td>
<td>GUI処理のスキップ</td>
</tr>
<tr>
<td>IsOptimization()</td>
<td>最適化モード判定</td>
<td>Print()の抑制</td>
</tr>
</tbody>
</table>
<p>これらの関数は単体で使うだけでなく、<strong>組み合わせて使うことで真価を発揮</strong>します。特に「Sleep() → RefreshRates()」のセットや、「IsTesting() / IsOptimization()による処理の出し分け」は、EA開発における定番テクニックです。</p>
<p>今回紹介した実践テンプレートをベースに、ご自身のEAに安全で効率的な処理を組み込んでみてください。堅牢なEAを作る第一歩になるはずです。</p>
<p>投稿 <a href="https://mql-programing.com/archives/13065/%e3%80%90mql4%e3%80%91%e7%9f%a5%e3%81%a3%e3%81%a6%e3%81%8a%e3%81%8d%e3%81%9f%e3%81%84%e3%83%a6%e3%83%bc%e3%83%86%e3%82%a3%e3%83%aa%e3%83%86%e3%82%a3%e9%96%a2%e6%95%b06%e9%81%b8%ef%bc%81sleep%e3%83%bbr/">【MQL4】知っておきたいユーティリティ関数6選！Sleep・RefreshRates・IsTradeAllowed・IsConnected・IsTesting・IsOptimizationの使い方</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【MQL4】市場情報を取得する関数を完全解説！MarketInfo・SymbolInfoDouble・SymbolInfoInteger・SymbolInfoStringの使い方</title>
		<link>https://mql-programing.com/archives/13062/%e3%80%90mql4%e3%80%91%e5%b8%82%e5%a0%b4%e6%83%85%e5%a0%b1%e3%82%92%e5%8f%96%e5%be%97%e3%81%99%e3%82%8b%e9%96%a2%e6%95%b0%e3%82%92%e5%ae%8c%e5%85%a8%e8%a7%a3%e8%aa%ac%ef%bc%81marketinfo%e3%83%bbsymbol/</link>
		
		<dc:creator><![CDATA[朝日奈りさ]]></dc:creator>
		<pubDate>Wed, 22 Apr 2026 01:00:00 +0000</pubDate>
				<category><![CDATA[【中級編】MQLプログラムの読み方・書き方]]></category>
		<category><![CDATA[MQL4]]></category>
		<category><![CDATA[EA開発]]></category>
		<category><![CDATA[SymbolInfoDouble]]></category>
		<category><![CDATA[市場情報関数]]></category>
		<category><![CDATA[MarketInfo]]></category>
		<guid isPermaLink="false">https://mql-programing.com/?p=13062</guid>

					<description><![CDATA[<p>EA（自動売買）を開発するとき、「現在のスプレッドはいくつ？」「このブローカーのストップレベルは？」「1pipあたりの価値は？」といった市場情報の取得は欠かせません。MQL4には、これらの情報を取得するための関数がいくつ [&#8230;]</p>
<p>投稿 <a href="https://mql-programing.com/archives/13062/%e3%80%90mql4%e3%80%91%e5%b8%82%e5%a0%b4%e6%83%85%e5%a0%b1%e3%82%92%e5%8f%96%e5%be%97%e3%81%99%e3%82%8b%e9%96%a2%e6%95%b0%e3%82%92%e5%ae%8c%e5%85%a8%e8%a7%a3%e8%aa%ac%ef%bc%81marketinfo%e3%83%bbsymbol/">【MQL4】市場情報を取得する関数を完全解説！MarketInfo・SymbolInfoDouble・SymbolInfoInteger・SymbolInfoStringの使い方</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[<p>EA（自動売買）を開発するとき、「現在のスプレッドはいくつ？」「このブローカーのストップレベルは？」「1pipあたりの価値は？」といった市場情報の取得は欠かせません。MQL4には、これらの情報を取得するための関数がいくつか用意されています。</p>
<p>この記事では、<strong>MarketInfo関数</strong>と、より新しい<strong>SymbolInfoDouble・SymbolInfoInteger・SymbolInfoString関数</strong>の使い方を、実践的なコード例とともに徹底解説します。</p>
<h2><span id="toc1">MarketInfo関数 ― MQL4の基本</span></h2>
<p>MarketInfo関数は、気配値表示ウィンドウに表示されている通貨ペアのマーケット情報を取得するための、MQL4で最も古くから使われている関数です。</p>
<h3><span id="toc2">基本構文</span></h3>
<pre><code class="language-mql4">double MarketInfo(string symbol, int type);
</code></pre>
<p>第1引数に通貨ペア名（例：&#8221;USDJPY&#8221;）、第2引数にMODE定数を指定します。戻り値はすべてdouble型です。</p>
<h3><span id="toc3">主なMODE定数一覧</span></h3>
<table>
<thead>
<tr>
<th>MODE定数</th>
<th>値</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>MODE_BID</td>
<td>9</td>
<td>現在のBid価格</td>
</tr>
<tr>
<td>MODE_ASK</td>
<td>10</td>
<td>現在のAsk価格</td>
</tr>
<tr>
<td>MODE_POINT</td>
<td>11</td>
<td>1ポイントの値（例：0.00001）</td>
</tr>
<tr>
<td>MODE_DIGITS</td>
<td>12</td>
<td>小数点以下の桁数</td>
</tr>
<tr>
<td>MODE_SPREAD</td>
<td>13</td>
<td>スプレッド（ポイント単位）</td>
</tr>
<tr>
<td>MODE_STOPLEVEL</td>
<td>14</td>
<td>ストップレベル（ポイント単位）</td>
</tr>
<tr>
<td>MODE_LOTSIZE</td>
<td>15</td>
<td>1ロットあたりの契約サイズ</td>
</tr>
<tr>
<td>MODE_TICKVALUE</td>
<td>16</td>
<td>1ティックあたりの価値（口座通貨建て）</td>
</tr>
<tr>
<td>MODE_TICKSIZE</td>
<td>17</td>
<td>1ティックのサイズ</td>
</tr>
<tr>
<td>MODE_SWAPLONG</td>
<td>18</td>
<td>ロングポジションのスワップ</td>
</tr>
<tr>
<td>MODE_SWAPSHORT</td>
<td>19</td>
<td>ショートポジションのスワップ</td>
</tr>
<tr>
<td>MODE_MINLOT</td>
<td>24</td>
<td>最小ロット数</td>
</tr>
<tr>
<td>MODE_LOTSTEP</td>
<td>25</td>
<td>ロットのステップ</td>
</tr>
<tr>
<td>MODE_MAXLOT</td>
<td>26</td>
<td>最大ロット数</td>
</tr>
<tr>
<td>MODE_MARGININIT</td>
<td>28</td>
<td>初期証拠金</td>
</tr>
<tr>
<td>MODE_MARGINREQUIRED</td>
<td>31</td>
<td>1ロットあたりの必要証拠金</td>
</tr>
<tr>
<td>MODE_FREEZELEVEL</td>
<td>33</td>
<td>フリーズレベル（ポイント単位）</td>
</tr>
</tbody>
</table>
<h3><span id="toc4">基本的な使用例</span></h3>
<pre><code class="language-mql4">void OnStart()
{
    string sym = Symbol(); // 現在のチャートの通貨ペア

    double bid       = MarketInfo(sym, MODE_BID);
    double ask       = MarketInfo(sym, MODE_ASK);
    double spread    = MarketInfo(sym, MODE_SPREAD);
    double stopLevel = MarketInfo(sym, MODE_STOPLEVEL);
    double tickValue = MarketInfo(sym, MODE_TICKVALUE);
    double minLot    = MarketInfo(sym, MODE_MINLOT);

    PrintFormat("Bid=%.5f  Ask=%.5f  Spread=%.0f  StopLevel=%.0f",
                bid, ask, spread, stopLevel);
    PrintFormat("TickValue=%.5f  MinLot=%.2f", tickValue, minLot);
}
</code></pre>
<p>MarketInfo関数はシンプルで使いやすいですが、戻り値がすべてdouble型のため、本来は整数値であるスプレッドや桁数もdoubleで返ってきます。キャストが必要になる場面がある点は覚えておきましょう。</p>
<h2><span id="toc5">SymbolInfo系関数 ― より型安全な新しい方法</span></h2>
<p>MQL4のビルド600以降では、MarketInfoの代替として<strong>SymbolInfo系関数</strong>が使えるようになりました。これらはMQL5と共通の関数であり、将来的なMQL5移行を見据えるなら、こちらを使うのがおすすめです。</p>
<p>SymbolInfo系関数は、取得するデータの型に応じて3つに分かれています。</p>
<table>
<thead>
<tr>
<th>関数名</th>
<th>戻り値の型</th>
<th>主な用途</th>
</tr>
</thead>
<tbody>
<tr>
<td>SymbolInfoDouble</td>
<td>double</td>
<td>価格、スワップ、ロット情報など</td>
</tr>
<tr>
<td>SymbolInfoInteger</td>
<td>long（整数）</td>
<td>スプレッド、桁数、ストップレベルなど</td>
</tr>
<tr>
<td>SymbolInfoString</td>
<td>string</td>
<td>通貨名、シンボル説明など</td>
</tr>
</tbody>
</table>
<h2><span id="toc6">SymbolInfoDouble ― double型の市場情報を取得</span></h2>
<p>SymbolInfoDoubleには2つの書式があります。</p>
<h3><span id="toc7">書式1：戻り値で直接受け取る</span></h3>
<pre><code class="language-mql4">double SymbolInfoDouble(string symbol, ENUM_SYMBOL_INFO_DOUBLE prop_id);
</code></pre>
<h3><span id="toc8">書式2：参照引数で受け取る（成否判定付き）</span></h3>
<pre><code class="language-mql4">bool SymbolInfoDouble(string symbol, ENUM_SYMBOL_INFO_DOUBLE prop_id, double &amp;value);
</code></pre>
<p>書式2はboolを返すため、取得が成功したかどうかを判定できます。安全なコードを書きたい場合はこちらを推奨します。</p>
<h3><span id="toc9">主なプロパティID</span></h3>
<table>
<thead>
<tr>
<th>プロパティID</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>SYMBOL_BID</td>
<td>現在のBid価格</td>
</tr>
<tr>
<td>SYMBOL_ASK</td>
<td>現在のAsk価格</td>
</tr>
<tr>
<td>SYMBOL_POINT</td>
<td>1ポイントの値</td>
</tr>
<tr>
<td>SYMBOL_TRADE_TICK_VALUE</td>
<td>1ティックの価値</td>
</tr>
<tr>
<td>SYMBOL_TRADE_TICK_SIZE</td>
<td>1ティックのサイズ</td>
</tr>
<tr>
<td>SYMBOL_TRADE_CONTRACT_SIZE</td>
<td>契約サイズ</td>
</tr>
<tr>
<td>SYMBOL_VOLUME_MIN</td>
<td>最小ロット</td>
</tr>
<tr>
<td>SYMBOL_VOLUME_MAX</td>
<td>最大ロット</td>
</tr>
<tr>
<td>SYMBOL_VOLUME_STEP</td>
<td>ロットステップ</td>
</tr>
<tr>
<td>SYMBOL_SWAP_LONG</td>
<td>ロングスワップ</td>
</tr>
<tr>
<td>SYMBOL_SWAP_SHORT</td>
<td>ショートスワップ</td>
</tr>
<tr>
<td>SYMBOL_MARGIN_INITIAL</td>
<td>初期証拠金</td>
</tr>
</tbody>
</table>
<h3><span id="toc10">コード例</span></h3>
<pre><code class="language-mql4">void OnStart()
{
    string sym = Symbol();

    // 書式1：直接取得
    double bid = SymbolInfoDouble(sym, SYMBOL_BID);
    double ask = SymbolInfoDouble(sym, SYMBOL_ASK);
    PrintFormat("Bid=%.5f  Ask=%.5f", bid, ask);

    // 書式2：成否判定付き
    double tickValue;
    if(SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE, tickValue))
        PrintFormat("TickValue = %.5f", tickValue);
    else
        Print("TickValue の取得に失敗しました");
}
</code></pre>
<h2><span id="toc11">SymbolInfoInteger ― 整数型の市場情報を取得</span></h2>
<p>スプレッドや桁数など、整数で扱うべき情報を<strong>long型</strong>で返します。MarketInfoではdoubleで返っていたものが正しい型で取得できるようになりました。</p>
<h3><span id="toc12">主なプロパティID</span></h3>
<table>
<thead>
<tr>
<th>プロパティID</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>SYMBOL_SPREAD</td>
<td>スプレッド（ポイント単位）</td>
</tr>
<tr>
<td>SYMBOL_DIGITS</td>
<td>小数点以下の桁数</td>
</tr>
<tr>
<td>SYMBOL_TRADE_STOPS_LEVEL</td>
<td>ストップレベル（ポイント単位）</td>
</tr>
<tr>
<td>SYMBOL_TRADE_FREEZE_LEVEL</td>
<td>フリーズレベル（ポイント単位）</td>
</tr>
<tr>
<td>SYMBOL_TRADE_EXEMODE</td>
<td>約定方式</td>
</tr>
<tr>
<td>SYMBOL_TIME</td>
<td>最終ティックの時刻</td>
</tr>
</tbody>
</table>
<pre><code class="language-mql4">void OnStart()
{
    string sym = Symbol();

    long spread    = SymbolInfoInteger(sym, SYMBOL_SPREAD);
    long digits    = SymbolInfoInteger(sym, SYMBOL_DIGITS);
    long stopLevel = SymbolInfoInteger(sym, SYMBOL_TRADE_STOPS_LEVEL);

    PrintFormat("Spread=%d  Digits=%d  StopLevel=%d",
                (int)spread, (int)digits, (int)stopLevel);
}
</code></pre>
<h2><span id="toc13">SymbolInfoString ― 文字列型の市場情報を取得</span></h2>
<p>通貨ペアの基軸通貨や決済通貨、説明文などの文字列情報を取得します。</p>
<table>
<thead>
<tr>
<th>プロパティID</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>SYMBOL_CURRENCY_BASE</td>
<td>基軸通貨（例：&#8221;USD&#8221;）</td>
</tr>
<tr>
<td>SYMBOL_CURRENCY_PROFIT</td>
<td>決済通貨（例：&#8221;JPY&#8221;）</td>
</tr>
<tr>
<td>SYMBOL_CURRENCY_MARGIN</td>
<td>証拠金通貨</td>
</tr>
<tr>
<td>SYMBOL_DESCRIPTION</td>
<td>シンボルの説明文</td>
</tr>
<tr>
<td>SYMBOL_PATH</td>
<td>シンボルツリー内のパス</td>
</tr>
</tbody>
</table>
<pre><code class="language-mql4">void OnStart()
{
    string sym = Symbol();

    string baseCurrency   = SymbolInfoString(sym, SYMBOL_CURRENCY_BASE);
    string profitCurrency = SymbolInfoString(sym, SYMBOL_CURRENCY_PROFIT);
    string description    = SymbolInfoString(sym, SYMBOL_DESCRIPTION);

    PrintFormat("基軸通貨=%s  決済通貨=%s", baseCurrency, profitCurrency);
    PrintFormat("説明: %s", description);
}
</code></pre>
<h2><span id="toc14">MarketInfo と SymbolInfo系の対応関係</span></h2>
<p>既存のコードをSymbolInfo系に書き換えたいときは、以下の対応表を参考にしてください。</p>
<table>
<thead>
<tr>
<th>MarketInfo (MODE定数)</th>
<th>SymbolInfo系 (プロパティID)</th>
<th>関数</th>
</tr>
</thead>
<tbody>
<tr>
<td>MODE_BID</td>
<td>SYMBOL_BID</td>
<td>SymbolInfoDouble</td>
</tr>
<tr>
<td>MODE_ASK</td>
<td>SYMBOL_ASK</td>
<td>SymbolInfoDouble</td>
</tr>
<tr>
<td>MODE_POINT</td>
<td>SYMBOL_POINT</td>
<td>SymbolInfoDouble</td>
</tr>
<tr>
<td>MODE_DIGITS</td>
<td>SYMBOL_DIGITS</td>
<td>SymbolInfoInteger</td>
</tr>
<tr>
<td>MODE_SPREAD</td>
<td>SYMBOL_SPREAD</td>
<td>SymbolInfoInteger</td>
</tr>
<tr>
<td>MODE_STOPLEVEL</td>
<td>SYMBOL_TRADE_STOPS_LEVEL</td>
<td>SymbolInfoInteger</td>
</tr>
<tr>
<td>MODE_TICKVALUE</td>
<td>SYMBOL_TRADE_TICK_VALUE</td>
<td>SymbolInfoDouble</td>
</tr>
<tr>
<td>MODE_MINLOT</td>
<td>SYMBOL_VOLUME_MIN</td>
<td>SymbolInfoDouble</td>
</tr>
<tr>
<td>MODE_LOTSTEP</td>
<td>SYMBOL_VOLUME_STEP</td>
<td>SymbolInfoDouble</td>
</tr>
<tr>
<td>MODE_MAXLOT</td>
<td>SYMBOL_VOLUME_MAX</td>
<td>SymbolInfoDouble</td>
</tr>
<tr>
<td>MODE_FREEZELEVEL</td>
<td>SYMBOL_TRADE_FREEZE_LEVEL</td>
<td>SymbolInfoInteger</td>
</tr>
</tbody>
</table>
<h2><span id="toc15">実践テクニック</span></h2>
<h3><span id="toc16">①スプレッドフィルター</span></h3>
<p>スプレッドが広がっているときにエントリーを避ける、シンプルなフィルターです。</p>
<pre><code class="language-mql4">// スプレッドが指定pips以上なら取引しない
bool IsSpreadOK(int maxSpreadPoints)
{
    long spread = SymbolInfoInteger(Symbol(), SYMBOL_SPREAD);
    if(spread > maxSpreadPoints)
    {
        PrintFormat("スプレッドが広すぎます: %d > %d", (int)spread, maxSpreadPoints);
        return false;
    }
    return true;
}
</code></pre>
<h3><span id="toc17">②ストップレベルを考慮したSL/TP設定</span></h3>
<p>ブローカーによってはストップレベルが設定されており、現在価格から一定以上離れていないとSL/TPを設定できません。また、<strong>ストップレベルが0を返す場合でも実際にはサーバー側で制限がかかるケース</strong>があるため、最低限のマージンを確保するのがポイントです。</p>
<pre><code class="language-mql4">double GetSafeStopDistance()
{
    long   stopLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL);
    double point     = SymbolInfoDouble(Symbol(), SYMBOL_POINT);

    // ストップレベルが0の場合でも最低10ポイントは確保
    if(stopLevel < 10)
        stopLevel = 10;

    return stopLevel * point;
}

// 使用例：Buy注文のSL/TPを安全に設定
double safeDistance = GetSafeStopDistance();
double sl = Ask - MathMax(desiredSL, safeDistance);
double tp = Ask + MathMax(desiredTP, safeDistance);
</code></pre>
<h3><span id="toc18">③リスクベースのロット計算</span></h3>
<p>口座残高の一定割合をリスクとして、適切なロット数を計算する関数です。</p>
<pre><code class="language-mql4">double CalcLotSize(double riskPercent, double slPoints)
{
    string sym = Symbol();

    double balance   = AccountBalance();
    double riskMoney = balance * riskPercent / 100.0;

    double tickValue = SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE);
    double tickSize  = SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_SIZE);
    double point     = SymbolInfoDouble(sym, SYMBOL_POINT);
    double minLot    = SymbolInfoDouble(sym, SYMBOL_VOLUME_MIN);
    double maxLot    = SymbolInfoDouble(sym, SYMBOL_VOLUME_MAX);
    double lotStep   = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);

    if(tickValue == 0 || tickSize == 0) return minLot;

    // 1ポイントあたりの価値
    double pointValue = tickValue * (point / tickSize);

    // ロット計算
    double lots = riskMoney / (slPoints * pointValue);

    // ロットステップに丸める
    lots = MathFloor(lots / lotStep) * lotStep;

    // 最小・最大ロットでクランプ
    lots = MathMax(lots, minLot);
    lots = MathMin(lots, maxLot);

    return NormalizeDouble(lots, 2);
}
</code></pre>
<h2><span id="toc19">ストラテジーテスターでの注意点</span></h2>
<p>ストラテジーテスター（バックテスト）では、市場情報の取得に制限があります。</p>
<ul>
<li><strong>他の通貨ペアの情報</strong>：テスト対象以外の通貨ペアのMarketInfoやSymbolInfoは、正しい値が返らないことがあります</li>
<li><strong>TickValueが0になる</strong>：テスト開始直後やクロス通貨ペアで、SYMBOL_TRADE_TICK_VALUEが0を返す場合があります</li>
<li><strong>対処法</strong>：TickValueが0の場合はデフォルト値を使う、またはOnTick()内で値が有効になるまで待つ処理を入れましょう</li>
</ul>
<pre><code class="language-mql4">// テスター対策：TickValueが0なら処理をスキップ
void OnTick()
{
    double tickValue = SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE);
    if(tickValue <= 0)
    {
        Print("TickValueが無効です。次のティックを待ちます。");
        return;
    }

    // 通常のEAロジック
    // ...
}
</code></pre>
<h2><span id="toc20">まとめ</span></h2>
<p>最後に、この記事のポイントを整理します。</p>
<ol>
<li><strong>MarketInfo関数</strong>はMQL4の基本関数で、MODE定数を使って様々な市場情報をdouble型で取得できる</li>
<li><strong>SymbolInfo系関数</strong>（Double/Integer/String）はデータ型に応じた3つの関数に分かれており、型安全に情報を取得できる</li>
<li><strong>MQL5への移行</strong>を見据えるなら、SymbolInfo系関数を使う習慣をつけるのがおすすめ</li>
<li><strong>ストップレベル</strong>は0を返す場合でも最低限のマージンを確保すると安全</li>
<li><strong>TickValue</strong>を使ったロット計算は実践的なEAに不可欠</li>
<li><strong>ストラテジーテスター</strong>では他通貨ペア情報やTickValueが正しく取得できない場合があるため、ガード処理を入れておくことが大切</li>
</ol>
<p>これらの関数を使いこなせるようになると、ブローカーの取引条件に応じた柔軟なEAが作れるようになります。ぜひ実際にコードを書いて、各関数の返り値を確認してみてください！</p>
<p>投稿 <a href="https://mql-programing.com/archives/13062/%e3%80%90mql4%e3%80%91%e5%b8%82%e5%a0%b4%e6%83%85%e5%a0%b1%e3%82%92%e5%8f%96%e5%be%97%e3%81%99%e3%82%8b%e9%96%a2%e6%95%b0%e3%82%92%e5%ae%8c%e5%85%a8%e8%a7%a3%e8%aa%ac%ef%bc%81marketinfo%e3%83%bbsymbol/">【MQL4】市場情報を取得する関数を完全解説！MarketInfo・SymbolInfoDouble・SymbolInfoInteger・SymbolInfoStringの使い方</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【MQL4】デバッグに必須！Print・Alert・Comment・GetLastError・ResetLastErrorの使い方を徹底解説</title>
		<link>https://mql-programing.com/archives/13055/%e3%80%90mql4%e3%80%91%e3%83%87%e3%83%90%e3%83%83%e3%82%b0%e3%81%ab%e5%bf%85%e9%a0%88%ef%bc%81print%e3%83%bbalert%e3%83%bbcomment%e3%83%bbgetlasterror%e3%83%bbresetlasterror%e3%81%ae%e4%bd%bf%e3%81%84/</link>
		
		<dc:creator><![CDATA[朝日奈りさ]]></dc:creator>
		<pubDate>Mon, 20 Apr 2026 01:00:00 +0000</pubDate>
				<category><![CDATA[【中級編】MQLプログラムの読み方・書き方]]></category>
		<category><![CDATA[GetLastError]]></category>
		<category><![CDATA[MQL4]]></category>
		<category><![CDATA[デバッグ]]></category>
		<category><![CDATA[EA開発]]></category>
		<category><![CDATA[Print関数]]></category>
		<guid isPermaLink="false">https://mql-programing.com/?p=13055</guid>

					<description><![CDATA[<p>MQL4でEA（自動売買）やインジケーターを開発するとき、「思った通りに動かない」「どこでエラーが出ているかわからない」という場面は必ず訪れます。そんなときに頼りになるのがデバッグ用の関数たちです。 この記事では、MQL [&#8230;]</p>
<p>投稿 <a href="https://mql-programing.com/archives/13055/%e3%80%90mql4%e3%80%91%e3%83%87%e3%83%90%e3%83%83%e3%82%b0%e3%81%ab%e5%bf%85%e9%a0%88%ef%bc%81print%e3%83%bbalert%e3%83%bbcomment%e3%83%bbgetlasterror%e3%83%bbresetlasterror%e3%81%ae%e4%bd%bf%e3%81%84/">【MQL4】デバッグに必須！Print・Alert・Comment・GetLastError・ResetLastErrorの使い方を徹底解説</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[<p>MQL4でEA（自動売買）やインジケーターを開発するとき、「思った通りに動かない」「どこでエラーが出ているかわからない」という場面は必ず訪れます。そんなときに頼りになるのが<strong>デバッグ用の関数</strong>たちです。</p>
<p>この記事では、MQL4開発で必須となる以下の5つ（＋α）の関数について、基本的な使い方から実践的な注意点まで徹底的に解説します。</p>
<ul>
<li><strong>Print()</strong> — ログへの出力</li>
<li><strong>Comment()</strong> — チャート上への表示</li>
<li><strong>Alert()</strong> — ポップアップ通知</li>
<li><strong>GetLastError()</strong> — エラーコードの取得</li>
<li><strong>ResetLastError()</strong> — エラーコードのリセット</li>
</ul>
<h2><span id="toc1">Print関数 — エキスパートログへの出力</span></h2>
<h3><span id="toc2">基本的な使い方</span></h3>
<p><strong>Print関数</strong>は、MetaTraderの「エキスパート」タブ（ログ）にメッセージを出力する、最も基本的なデバッグ関数です。開発中に変数の値を確認したり、処理の流れを追跡したりするのに欠かせません。</p>
<pre><code class="language-mql4">void OnTick()
{
    double currentPrice = Ask;
    int spread = MarketInfo(Symbol(), MODE_SPREAD);

    Print("現在のAsk価格: ", currentPrice);
    Print("スプレッド: ", spread, " ポイント");
    Print("通貨ペア: ", Symbol(), " 時間足: ", Period());
}
</code></pre>
<p>Print関数はカンマ区切りで複数の値を渡すことができ、<strong>文字列・整数・小数点数</strong>などさまざまなデータ型を自動的に文字列に変換して出力してくれます。</p>
<h3><span id="toc3">データ型ごとの表示仕様</span></h3>
<p>Print関数で各データ型を出力するときの仕様を覚えておきましょう。</p>
<pre><code class="language-mql4">void OnInit()
{
    // 整数型：そのまま数値で表示
    int intValue = 12345;
    Print("int型: ", intValue);           // → int型: 12345

    // double型：小数点以下の桁数は自動調整
    double dblValue = 1.23456789;
    Print("double型: ", dblValue);        // → double型: 1.23456789

    // bool型：trueまたはfalseで表示
    bool boolValue = true;
    Print("bool型: ", boolValue);         // → bool型: true

    // datetime型：日時形式で表示
    datetime dtValue = TimeCurrent();
    Print("datetime型: ", dtValue);       // → datetime型: 2024.01.15 12:30:00
}
</code></pre>
<h3><span id="toc4">出力先について</span></h3>
<p>Print関数の出力先は2か所あります。</p>
<ul>
<li><strong>エキスパートタブ</strong>：MetaTrader画面下部の「エキスパート」タブにリアルタイム表示</li>
<li><strong>ログファイル</strong>：MQL4/Logs フォルダ内にテキストファイルとしても記録される</li>
</ul>
<p>ログファイルに残るため、後から問題を調査するときにも役立ちます。ただし、<strong>OnTick内で大量にPrintを呼ぶとパフォーマンスに影響する</strong>場合があるので、本番稼働時には不要なPrintは削除またはコメントアウトしましょう。</p>
<h2><span id="toc5">Comment関数 — チャート画面への表示</span></h2>
<h3><span id="toc6">基本的な使い方</span></h3>
<p><strong>Comment関数</strong>は、チャートの<strong>左上</strong>にテキストを表示する関数です。リアルタイムで変数の値を視覚的に確認したいときに便利です。</p>
<pre><code class="language-mql4">void OnTick()
{
    double bid = Bid;
    double ask = Ask;
    int spread = (int)((ask - bid) / Point);

    Comment("Bid: ", bid, "\n",
            "Ask: ", ask, "\n",
            "Spread: ", spread, " points\n",
            "Time: ", TimeToStr(TimeCurrent(), TIME_SECONDS));
}
</code></pre>
<p>改行するには<strong>「\n」</strong>を使います。これにより、複数行にわたる情報をきれいに表示できます。</p>
<h3><span id="toc7">Comment関数の重要な注意点</span></h3>
<p>Comment関数には大きな特徴（欠点）があります。<strong>最後に呼び出したComment関数の内容で上書きされる</strong>という点です。</p>
<pre><code class="language-mql4">void OnTick()
{
    Comment("1行目のメッセージ");
    Comment("2行目のメッセージ");  // ← これだけが表示される！
}
</code></pre>
<p>上記の場合、チャートには「2行目のメッセージ」しか表示されません。複数の情報を表示したい場合は、<strong>1回のComment呼び出しにすべての情報をまとめる</strong>必要があります。</p>
<p>また、Comment関数の表示をクリア（消去）したい場合は、空文字を渡します。</p>
<pre><code class="language-mql4">Comment("");  // チャート左上の表示をクリア
</code></pre>
<h2><span id="toc8">Alert関数 — ポップアップ通知</span></h2>
<h3><span id="toc9">基本的な使い方</span></h3>
<p><strong>Alert関数</strong>は、ポップアップダイアログを表示して、音とともにユーザーに通知する関数です。重要なイベント（エントリーシグナル発生、エラー検知など）の通知に使います。</p>
<pre><code class="language-mql4">void OnTick()
{
    static datetime lastAlertTime = 0;
    datetime currentTime = TimeCurrent();

    // RSIが30以下になったらアラート（同じ足で1回だけ）
    double rsi = iRSI(Symbol(), 0, 14, PRICE_CLOSE, 0);

    if(rsi < 30.0 &#038;&#038; lastAlertTime != iTime(Symbol(), 0, 0))
    {
        Alert(Symbol(), " RSIが30以下です！ RSI=", NormalizeDouble(rsi, 2));
        lastAlertTime = iTime(Symbol(), 0, 0);
    }
}
</code></pre>
<h3><span id="toc10">Alert関数の注意点</span></h3>
<p>Alert関数には以下の注意点があります。</p>
<ul>
<li><strong>バックテストでは動作しない</strong>：ストラテジーテスターでのバックテスト時にはAlertは表示されません。バックテスト中のデバッグにはPrint関数を使いましょう。</li>
<li><strong>日本語の一部が文字化けする場合がある</strong>：環境によっては日本語表示が正しくされないことがあります。重要な情報は英数字で出力するのが安全です。</li>
<li><strong>連続呼び出しに注意</strong>：OnTick内で条件なしにAlertを呼ぶと、ティックごとにポップアップが出て操作不能になります。必ず条件制御を入れましょう。</li>
</ul>
<h2><span id="toc11">GetLastError関数 — エラーコードの取得</span></h2>
<h3><span id="toc12">基本的な使い方</span></h3>
<p><strong>GetLastError関数</strong>は、直前の操作で発生したエラーのコード（番号）を取得する関数です。注文送信やファイル操作などの後にエラーチェックを行う際に使います。</p>
<pre><code class="language-mql4">void OnTick()
{
    int ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "Test", 0, 0, clrBlue);

    if(ticket < 0)
    {
        int errorCode = GetLastError();
        Print("注文エラー！ エラーコード: ", errorCode);
    }
    else
    {
        Print("注文成功！ チケット番号: ", ticket);
    }
}
</code></pre>
<h3><span id="toc13">よく見るエラーコード一覧</span></h3>
<p>以下は、MQL4開発でよく遭遇するエラーコードの一覧です。</p>
<table>
<thead>
<tr>
<th>エラーコード</th>
<th>定数名</th>
<th>意味</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>ERR_NO_ERROR</td>
<td>エラーなし</td>
</tr>
<tr>
<td>1</td>
<td>ERR_NO_RESULT</td>
<td>エラーはないが結果が不明</td>
</tr>
<tr>
<td>2</td>
<td>ERR_COMMON_ERROR</td>
<td>一般的なエラー</td>
</tr>
<tr>
<td>6</td>
<td>ERR_NO_CONNECTION</td>
<td>サーバーとの接続がない</td>
</tr>
<tr>
<td>130</td>
<td>ERR_INVALID_STOPS</td>
<td>ストップが無効（SL/TPが近すぎる等）</td>
</tr>
<tr>
<td>131</td>
<td>ERR_INVALID_TRADE_VOLUME</td>
<td>取引量が無効</td>
</tr>
<tr>
<td>134</td>
<td>ERR_NOT_ENOUGH_MONEY</td>
<td>資金不足</td>
</tr>
<tr>
<td>138</td>
<td>ERR_REQUOTE</td>
<td>リクオート</td>
</tr>
<tr>
<td>146</td>
<td>ERR_TRADE_CONTEXT_BUSY</td>
<td>トレードコンテキストがビジー</td>
</tr>
<tr>
<td>4109</td>
<td>ERR_TRADE_NOT_ALLOWED</td>
<td>自動売買が許可されていない</td>
</tr>
</tbody>
</table>
<h3><span id="toc14">【超重要】GetLastErrorは2度呼ぶとリセットされる！</span></h3>
<p>GetLastError関数には<strong>非常に重要な仕様</strong>があります。<strong>一度呼び出すと、内部のエラーコードが0にリセットされてしまう</strong>のです。</p>
<pre><code class="language-mql4">// ★ ダメな例
int ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "", 0, 0, clrBlue);
if(ticket < 0)
{
    Print("エラーコード: ", GetLastError());   // ← 1回目：正しいエラーコードが取得できる
    Print("エラーコード: ", GetLastError());   // ← 2回目：0が返る！（リセット済み）
}
</code></pre>
<pre><code class="language-mql4">// ★ 正しい例：変数で受けてから使う
int ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "", 0, 0, clrBlue);
if(ticket < 0)
{
    int err = GetLastError();  // まず変数に格納！
    Print("エラーコード: ", err);
    Alert("注文失敗 エラー: ", err);  // 何度でも使える
}
</code></pre>
<p>これはMQL4開発でよくあるミスです。<strong>GetLastError()は必ず一度だけ呼び出して変数に保存</strong>してから使いましょう。</p>
<h2><span id="toc15">ResetLastError関数 — エラーコードのリセット</span></h2>
<p><strong>ResetLastError関数</strong>は、定義済み変数<strong>_LastError</strong>に格納されているエラーコードを<strong>0（エラーなし）にリセット</strong>するための関数です。</p>
<pre><code class="language-mql4">void OnTick()
{
    // エラーコードを事前にリセット
    ResetLastError();

    int ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "Test", 0, 0, clrBlue);

    if(ticket < 0)
    {
        int err = GetLastError();
        Print("注文エラー: ", err);
    }
}
</code></pre>
<h3><span id="toc16">なぜリセットが必要なのか？</span></h3>
<p>GetLastError()は「最後に発生したエラー」を返します。つまり、以前の処理で発生したエラーコードが残っている可能性があるのです。特定の処理のエラーだけを正確に検知したい場合は、<strong>処理の直前にResetLastError()を呼ぶのが定石</strong>です。</p>
<pre><code class="language-mql4">// 定石パターン：リセット → 処理 → エラーチェック
ResetLastError();           // ① リセット
bool result = OrderClose(ticket, lots, price, 3, clrRed);  // ② 処理実行
int err = GetLastError();   // ③ エラー取得（変数に格納）
if(err != 0)
{
    Print("決済エラー: ", err);
}
</code></pre>
<h2><span id="toc17">ErrorDescription関数 — エラーコードを文章に変換</span></h2>
<p>エラーコードの番号だけでは、何が起きたのかすぐにはわかりません。そこで便利なのが<strong>ErrorDescription関数</strong>です。この関数を使うと、エラーコードを人間が読める英語の文章に変換できます。</p>
<p>ただし、この関数はMQL4に標準で組み込まれているわけではなく、<strong>stdlib.mqh</strong>というライブラリファイルをインクルードする必要があります。</p>
<pre><code class="language-mql4">#include &lt;stdlib.mqh&gt;  // ErrorDescription関数を使うために必要

void OnTick()
{
    ResetLastError();

    int ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "Test", 0, 0, clrBlue);

    if(ticket < 0)
    {
        int err = GetLastError();
        Print("エラーコード: ", err, " 内容: ", ErrorDescription(err));
        // 例：エラーコード: 134 内容: not enough money
    }
}
</code></pre>
<p>エラーの原因がすぐにわかるため、デバッグの効率が格段に上がります。<strong>ぜひstdlib.mqhのインクルードを習慣にしましょう。</strong></p>
<h2><span id="toc18">実践例 — 5つの関数を組み合わせたデバッグ付きEA</span></h2>
<p>ここまで学んだ関数を組み合わせた、実践的なサンプルコードをご紹介します。</p>
<pre><code class="language-mql4">#include &lt;stdlib.mqh&gt;

input double LotSize = 0.1;
input int MagicNumber = 12345;

void OnTick()
{
    // 現在の状態をチャートに表示
    Comment("=== デバッグ情報 ===\n",
            "通貨ペア: ", Symbol(), "\n",
            "Bid: ", Bid, "  Ask: ", Ask, "\n",
            "スプレッド: ", MarketInfo(Symbol(), MODE_SPREAD), "\n",
            "保有ポジション: ", CountOrders(), "\n",
            "口座残高: ", AccountBalance(), "\n",
            "更新時刻: ", TimeToStr(TimeCurrent(), TIME_SECONDS));

    // 簡単な売買ロジック（例：移動平均のクロス）
    double maFast = iMA(Symbol(), 0, 10, 0, MODE_SMA, PRICE_CLOSE, 0);
    double maFastPrev = iMA(Symbol(), 0, 10, 0, MODE_SMA, PRICE_CLOSE, 1);
    double maSlow = iMA(Symbol(), 0, 25, 0, MODE_SMA, PRICE_CLOSE, 0);
    double maSlowPrev = iMA(Symbol(), 0, 25, 0, MODE_SMA, PRICE_CLOSE, 1);

    // ゴールデンクロスで買い
    if(maFastPrev <= maSlowPrev &#038;&#038; maFast > maSlow && CountOrders() == 0)
    {
        Print("ゴールデンクロス検出！ 買い注文を送信します。");
        Print("MA(10)=", maFast, " MA(25)=", maSlow);

        ResetLastError();  // エラーをリセット
        int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, 3, 0, 0,
                               "MA Cross Buy", MagicNumber, 0, clrBlue);

        int err = GetLastError();  // 変数に格納（1回だけ呼ぶ！）

        if(ticket >= 0)
        {
            Print("注文成功！ チケット: ", ticket);
        }
        else
        {
            Print("注文失敗！ エラーコード: ", err,
                  " 内容: ", ErrorDescription(err));
            Alert("注文失敗！ Error: ", err, " ", ErrorDescription(err));
        }
    }
}

// 保有ポジション数をカウントする関数
int CountOrders()
{
    int count = 0;
    for(int i = OrdersTotal() - 1; i >= 0; i--)
    {
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
                count++;
        }
    }
    return count;
}
</code></pre>
<p>このサンプルでは、以下のようにデバッグ関数を使い分けています。</p>
<ul>
<li><strong>Comment</strong>：リアルタイムの状態監視（チャート上に常時表示）</li>
<li><strong>Print</strong>：処理の流れやシグナル検出の記録（ログに残る）</li>
<li><strong>Alert</strong>：注文失敗などの重要イベントの即時通知</li>
<li><strong>ResetLastError → GetLastError</strong>：正確なエラーコード取得の定石パターン</li>
<li><strong>ErrorDescription</strong>：エラー内容の可読化</li>
</ul>
<h2><span id="toc19">まとめ — デバッグ関数の使い分け</span></h2>
<p>最後に、各関数の特徴と使い分けを表で整理します。</p>
<table>
<thead>
<tr>
<th>関数名</th>
<th>出力先</th>
<th>主な用途</th>
<th>注意点</th>
</tr>
</thead>
<tbody>
<tr>
<td>Print()</td>
<td>エキスパートログ</td>
<td>変数の値確認、処理フロー追跡</td>
<td>大量出力でパフォーマンス低下</td>
</tr>
<tr>
<td>Comment()</td>
<td>チャート左上</td>
<td>リアルタイムの状態監視</td>
<td>最後の呼び出しで上書きされる</td>
</tr>
<tr>
<td>Alert()</td>
<td>ポップアップ</td>
<td>重要イベントの即時通知</td>
<td>バックテスト非対応・日本語文字化けの可能性</td>
</tr>
<tr>
<td>GetLastError()</td>
<td>—</td>
<td>エラーコード取得</td>
<td><strong>2度呼ぶとリセットされる</strong>（変数で受ける）</td>
</tr>
<tr>
<td>ResetLastError()</td>
<td>—</td>
<td>エラーコードの初期化</td>
<td>処理前にリセットするのが定石</td>
</tr>
</tbody>
</table>
<p>デバッグ関数を上手に使いこなすことは、MQL4開発の効率を大きく左右します。特に<strong>「GetLastErrorは変数で一度受けてから使う」</strong>と<strong>「処理前にResetLastErrorでリセットする」</strong>の2つは、ぜひ今日から実践してください。</p>
<p>デバッグの精度が上がれば、EA開発のスピードも自然と上がっていきますよ！</p>
<p>投稿 <a href="https://mql-programing.com/archives/13055/%e3%80%90mql4%e3%80%91%e3%83%87%e3%83%90%e3%83%83%e3%82%b0%e3%81%ab%e5%bf%85%e9%a0%88%ef%bc%81print%e3%83%bbalert%e3%83%bbcomment%e3%83%bbgetlasterror%e3%83%bbresetlasterror%e3%81%ae%e4%bd%bf%e3%81%84/">【MQL4】デバッグに必須！Print・Alert・Comment・GetLastError・ResetLastErrorの使い方を徹底解説</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【MQL4】配列関数を完全マスター！ArraySize・ArrayResize・ArraySort・ArrayCopy・ArrayInitialize・ArraySetAsSeriesの使い方</title>
		<link>https://mql-programing.com/archives/13052/%e3%80%90mql4%e3%80%91%e9%85%8d%e5%88%97%e9%96%a2%e6%95%b0%e3%82%92%e5%ae%8c%e5%85%a8%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bc%ef%bc%81arraysize%e3%83%bbarrayresize%e3%83%bbarraysort%e3%83%bbarraycopy/</link>
		
		<dc:creator><![CDATA[朝日奈りさ]]></dc:creator>
		<pubDate>Sun, 19 Apr 2026 01:00:00 +0000</pubDate>
				<category><![CDATA[【中級編】MQLプログラムの読み方・書き方]]></category>
		<category><![CDATA[ArrayResize]]></category>
		<category><![CDATA[ArraySetAsSeries]]></category>
		<category><![CDATA[MQL4]]></category>
		<category><![CDATA[EA開発]]></category>
		<category><![CDATA[配列関数]]></category>
		<guid isPermaLink="false">https://mql-programing.com/?p=13052</guid>

					<description><![CDATA[<p>MQL4で自動売買（EA）やカスタムインジケーターを開発するとき、配列の操作は避けて通れません。価格データの格納、インジケーター値の計算、ソートによるランキング処理など、あらゆる場面で配列関数が活躍します。 この記事では [&#8230;]</p>
<p>投稿 <a href="https://mql-programing.com/archives/13052/%e3%80%90mql4%e3%80%91%e9%85%8d%e5%88%97%e9%96%a2%e6%95%b0%e3%82%92%e5%ae%8c%e5%85%a8%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bc%ef%bc%81arraysize%e3%83%bbarrayresize%e3%83%bbarraysort%e3%83%bbarraycopy/">【MQL4】配列関数を完全マスター！ArraySize・ArrayResize・ArraySort・ArrayCopy・ArrayInitialize・ArraySetAsSeriesの使い方</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[<p>MQL4で自動売買（EA）やカスタムインジケーターを開発するとき、<strong>配列の操作</strong>は避けて通れません。価格データの格納、インジケーター値の計算、ソートによるランキング処理など、あらゆる場面で配列関数が活躍します。</p>
<p>この記事では、MQL4で特に使用頻度の高い<strong>6つの配列関数</strong>を体系的に解説します。</p>
<ul>
<li><strong>ArraySize()</strong> – 要素数の取得</li>
<li><strong>ArrayResize()</strong> – サイズの動的変更</li>
<li><strong>ArrayInitialize()</strong> – 全要素の一括初期化</li>
<li><strong>ArrayCopy()</strong> – 配列のコピー</li>
<li><strong>ArraySort()</strong> – ソート（並び替え）</li>
<li><strong>ArraySetAsSeries()</strong> – 時系列インデックスへの変換</li>
</ul>
<p>それぞれの関数について、基本的な使い方・注意点・実践的なコードサンプルを交えながら丁寧に解説していきます。</p>
<h2><span id="toc1">ArraySize() – 配列の要素数を取得する</span></h2>
<p><code>ArraySize()</code>は、配列に含まれる<strong>全要素数</strong>を返す関数です。ループ処理で配列の全要素を走査するときに欠かせません。</p>
<h3><span id="toc2">基本構文</span></h3>
<pre><code class="language-mql5">int ArraySize(
   const void&amp; array[]   // 対象の配列
);
</code></pre>
<h3><span id="toc3">基本的な使い方</span></h3>
<pre><code class="language-mql5">void OnStart()
{
   double prices[5] = {100.0, 101.5, 102.3, 99.8, 100.7};

   int size = ArraySize(prices);
   Print("要素数: ", size);  // 出力: 要素数: 5

   // ループ処理での活用
   for(int i = 0; i &lt; ArraySize(prices); i++)
   {
      Print("prices[", i, "] = ", prices[i]);
   }
}
</code></pre>
<h3><span id="toc4">多次元配列での注意点</span></h3>
<p><code>ArraySize()</code>は多次元配列に対しては、<strong>全次元の要素数の積（全要素数）</strong>を返します。特定の次元の要素数だけを知りたい場合は<code>ArrayRange()</code>を使いましょう。</p>
<pre><code class="language-mql5">void OnStart()
{
   double matrix[3][4];  // 3行4列の二次元配列

   Print("ArraySize: ", ArraySize(matrix));       // 出力: 12（3×4）
   Print("第1次元: ", ArrayRange(matrix, 0));      // 出力: 3
   Print("第2次元: ", ArrayRange(matrix, 1));      // 出力: 4
}
</code></pre>
<h2><span id="toc5">ArrayResize() – 配列のサイズを動的に変更する</span></h2>
<p><code>ArrayResize()</code>は、<strong>動的配列</strong>のサイズを変更する関数です。EAの運用中にデータが増減する場面で大活躍します。</p>
<h3><span id="toc6">基本構文</span></h3>
<pre><code class="language-mql5">int ArrayResize(
   void&amp; array[],         // サイズ変更する配列
   int    new_size,        // 新しいサイズ
   int    reserve_size=0   // 予約サイズ（省略可）
);
</code></pre>
<p>戻り値は、成功した場合は新しいサイズ、失敗した場合は<strong>-1</strong>です。</p>
<h3><span id="toc7">基本的な使い方</span></h3>
<pre><code class="language-mql5">void OnStart()
{
   double data[];  // 動的配列（サイズ未指定）

   // サイズを5に設定
   ArrayResize(data, 5);
   Print("サイズ: ", ArraySize(data));  // 出力: 5

   // データを格納
   for(int i = 0; i &lt; 5; i++)
      data[i] = i * 1.5;

   // サイズを10に拡張（既存データは保持される）
   ArrayResize(data, 10);
   Print("拡張後サイズ: ", ArraySize(data));  // 出力: 10
   Print("data[2] = ", data[2]);  // 出力: 3.0（既存データは保持）
}
</code></pre>
<h3><span id="toc8">reserve_sizeでパフォーマンスを改善する</span></h3>
<p>ループ内で何度も<code>ArrayResize()</code>を呼ぶと、メモリの再割り当てが頻繁に発生しパフォーマンスが低下します。第3引数の<code>reserve_size</code>を指定することで、あらかじめメモリを多めに確保し、再割り当ての回数を減らせます。</p>
<pre><code class="language-mql5">void OnStart()
{
   double ticks[];
   int count = 0;

   // 悪い例：毎回メモリ再割り当てが発生
   // for(int i = 0; i &lt; 10000; i++)
   // {
   //    ArrayResize(ticks, ++count);
   //    ticks[count - 1] = Bid;
   // }

   // 良い例：reserve_sizeで事前にメモリを確保
   for(int i = 0; i &lt; 10000; i++)
   {
      ArrayResize(ticks, ++count, 10000);  // 最大10000要素分を予約
      ticks[count - 1] = Bid;
   }
}
</code></pre>
<p>大量のデータを扱うEAでは、この<code>reserve_size</code>の指定が処理速度に大きく影響します。ぜひ覚えておきましょう。</p>
<h2><span id="toc9">ArrayInitialize() – 全要素を一括で初期化する</span></h2>
<p><code>ArrayInitialize()</code>は、配列の<strong>全要素を指定した値で一括初期化</strong>する関数です。</p>
<h3><span id="toc10">基本構文</span></h3>
<pre><code class="language-mql5">int ArrayInitialize(
   double&amp; array[],   // 初期化する配列
   double  value       // セットする値
);
</code></pre>
<h3><span id="toc11">基本的な使い方</span></h3>
<pre><code class="language-mql5">void OnStart()
{
   double buffer[10];

   // 全要素を0.0で初期化
   ArrayInitialize(buffer, 0.0);

   for(int i = 0; i &lt; ArraySize(buffer); i++)
      Print("buffer[", i, "] = ", buffer[i]);  // すべて0.0
}
</code></pre>
<h3><span id="toc12">ArrayResizeとの組み合わせが重要</span></h3>
<p><code>ArrayResize()</code>でサイズを拡張した直後、新しく追加された要素の値は<strong>不定（ゴミ値）</strong>です。そのため、拡張後に<code>ArrayInitialize()</code>で初期化するのが安全なパターンです。</p>
<pre><code class="language-mql5">void OnStart()
{
   double data[];

   ArrayResize(data, 10);
   ArrayInitialize(data, 0.0);  // 拡張後は必ず初期化！

   Print("data[5] = ", data[5]);  // 安全に0.0が入っている
}
</code></pre>
<h2><span id="toc13">ArrayCopy() – 配列を別の配列にコピーする</span></h2>
<p><code>ArrayCopy()</code>は、配列の全体または一部を別の配列にコピーする関数です。</p>
<h3><span id="toc14">基本構文</span></h3>
<pre><code class="language-mql5">int ArrayCopy(
   void&amp; dst_array[],      // コピー先
   const void&amp; src_array[], // コピー元
   int   dst_start=0,       // コピー先の開始位置
   int   src_start=0,       // コピー元の開始位置
   int   count=WHOLE_ARRAY  // コピーする要素数
);
</code></pre>
<p>戻り値はコピーされた要素数です。</p>
<h3><span id="toc15">基本的な使い方</span></h3>
<pre><code class="language-mql5">void OnStart()
{
   double source[5] = {1.1, 2.2, 3.3, 4.4, 5.5};
   double dest[];

   // 全要素をコピー（destは自動でリサイズされる）
   ArrayCopy(dest, source);
   Print("dest[2] = ", dest[2]);  // 出力: 3.3

   // 部分コピー：sourceのインデックス1から3要素をdest2のインデックス0にコピー
   double dest2[3];
   ArrayCopy(dest2, source, 0, 1, 3);
   // dest2 = {2.2, 3.3, 4.4}
   for(int i = 0; i &lt; ArraySize(dest2); i++)
      Print("dest2[", i, "] = ", dest2[i]);
}
</code></pre>
<p>部分コピーを使いこなすと、直近N本のデータだけを抜き出す処理などが簡潔に書けます。</p>
<h2><span id="toc16">ArraySort() – 配列をソート（並び替え）する</span></h2>
<p><code>ArraySort()</code>は、配列の要素を<strong>昇順</strong>にソートする関数です。</p>
<h3><span id="toc17">基本構文</span></h3>
<pre><code class="language-mql5">bool ArraySort(
   void&amp; array[]   // ソートする配列
);
</code></pre>
<p>MQL4の<code>ArraySort()</code>は<strong>昇順のみ</strong>に対応しています。</p>
<h3><span id="toc18">基本的な使い方</span></h3>
<pre><code class="language-mql5">void OnStart()
{
   double values[5] = {3.5, 1.2, 4.8, 2.1, 3.9};

   // 昇順ソート
   ArraySort(values);

   for(int i = 0; i &lt; ArraySize(values); i++)
      Print("values[", i, "] = ", values[i]);
   // 出力: 1.2, 2.1, 3.5, 3.9, 4.8
}
</code></pre>
<h3><span id="toc19">降順にしたい場合</span></h3>
<p>MQL4の<code>ArraySort()</code>には降順オプションがないため、昇順ソート後に逆順で読むか、別の配列に逆順コピーする方法を使います。</p>
<pre><code class="language-mql5">void OnStart()
{
   double values[5] = {3.5, 1.2, 4.8, 2.1, 3.9};

   // まず昇順ソート
   ArraySort(values);

   // 逆順で読み取ることで降順として扱う
   int size = ArraySize(values);
   for(int i = size - 1; i &gt;= 0; i--)
      Print("降順 values[", (size - 1 - i), "] = ", values[i]);
   // 出力: 4.8, 3.9, 3.5, 2.1, 1.2
}
</code></pre>
<h3><span id="toc20">注意点：時系列配列はソートできない</span></h3>
<p><code>ArraySetAsSeries()</code>で時系列フラグが設定された配列は、<code>ArraySort()</code>でソートできません。ソートしたい場合は、まず通常の配列にコピーしてからソートしましょう。</p>
<h2><span id="toc21">ArraySetAsSeries() – 時系列インデックスに変換する</span></h2>
<p><code>ArraySetAsSeries()</code>は、配列のインデックスの方向を<strong>時系列方向</strong>に変更する関数です。MetaTraderのチャートデータは最新のバー（ローソク足）がインデックス0になっていますが、通常の配列は先頭がインデックス0です。この違いを吸収するのがこの関数です。</p>
<h3><span id="toc22">基本構文</span></h3>
<pre><code class="language-mql5">bool ArraySetAsSeries(
   const void&amp; array[],  // 対象の配列
   bool        flag       // true=時系列, false=通常
);
</code></pre>
<h3><span id="toc23">通常配列と時系列配列の違い</span></h3>
<pre><code class="language-mql5">// 通常の配列（左から右へインデックスが増加）
// index:  [0]  [1]  [2]  [3]  [4]
// データ:  古い ←――――――――――→ 新しい

// 時系列配列（右から左へインデックスが増加）
// index:  [4]  [3]  [2]  [1]  [0]
// データ:  古い ←――――――――――→ 新しい
</code></pre>
<h3><span id="toc24">基本的な使い方</span></h3>
<pre><code class="language-mql5">void OnStart()
{
   double closeArray[];

   // 直近10本の終値を取得
   ArraySetAsSeries(closeArray, true);  // 時系列方向に設定
   CopyClose(Symbol(), PERIOD_CURRENT, 0, 10, closeArray);

   // closeArray[0] = 最新バーの終値
   // closeArray[1] = 1つ前のバーの終値
   // closeArray[9] = 9つ前のバーの終値
   Print("最新の終値: ", closeArray[0]);
   Print("1つ前の終値: ", closeArray[1]);
}
</code></pre>
<h3><span id="toc25">インジケーター開発での活用</span></h3>
<p>カスタムインジケーターの<code>OnCalculate()</code>関数では、引数として渡される価格配列のインデックス方向が不定の場合があります。そのため、関数の冒頭で<code>ArraySetAsSeries()</code>を呼んでインデックス方向を統一するのが定番のパターンです。</p>
<pre><code class="language-mql5">int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &amp;time[],
                const double &amp;open[],
                const double &amp;high[],
                const double &amp;low[],
                const double &amp;close[],
                const long &amp;tick_volume[],
                const long &amp;volume[],
                const int &amp;spread[])
{
   // インデックス方向を時系列に統一
   ArraySetAsSeries(close, true);
   ArraySetAsSeries(high, true);
   ArraySetAsSeries(low, true);

   // これで close[0] が最新バーの終値になる
   // ... インジケーターの計算処理 ...

   return(rates_total);
}
</code></pre>
<h2><span id="toc26">実践テクニック：6つの関数を組み合わせて使う</span></h2>
<p>ここまで学んだ6つの関数を組み合わせた実践的なサンプルを見てみましょう。直近N本のバーから<strong>最高値トップ3</strong>を抽出する処理です。</p>
<pre><code class="language-mql5">void OnStart()
{
   int period = 20;  // 直近20本のバーを対象

   // 1. 高値データを格納する動的配列を準備
   double highPrices[];
   ArrayResize(highPrices, period);       // サイズを設定
   ArrayInitialize(highPrices, 0.0);      // 初期化

   // 2. 直近の高値データを取得
   double tempHigh[];
   ArraySetAsSeries(tempHigh, true);      // 時系列方向に設定
   CopyHigh(Symbol(), PERIOD_CURRENT, 0, period, tempHigh);

   // 3. 作業用配列にコピー
   ArrayCopy(highPrices, tempHigh, 0, 0, period);

   // 4. 昇順ソートしてトップ3を取得（末尾3要素が最大値）
   ArraySort(highPrices);

   int size = ArraySize(highPrices);
   Print("=== 直近", period, "本の高値トップ3 ===");
   for(int i = 0; i &lt; 3; i++)
   {
      Print("第", (i + 1), "位: ", highPrices[size - 1 - i]);
   }
}
</code></pre>
<p>このように、<code>ArrayResize</code>→<code>ArrayInitialize</code>→<code>ArraySetAsSeries</code>→<code>ArrayCopy</code>→<code>ArraySort</code>→<code>ArraySize</code>と、6つの関数を自然に組み合わせて使えるようになると、実践的なEA開発がスムーズに進みます。</p>
<h2><span id="toc27">配列関数 早見表</span></h2>
<table>
<thead>
<tr>
<th>関数名</th>
<th>機能</th>
<th>主な使用場面</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>ArraySize()</strong></td>
<td>要素数を取得</td>
<td>ループの上限値、配列が空かの判定</td>
</tr>
<tr>
<td><strong>ArrayResize()</strong></td>
<td>サイズを動的に変更</td>
<td>データ数が実行時に決まる場合</td>
</tr>
<tr>
<td><strong>ArrayInitialize()</strong></td>
<td>全要素を一括初期化</td>
<td>ArrayResize後のゴミ値対策</td>
</tr>
<tr>
<td><strong>ArrayCopy()</strong></td>
<td>配列の全体/部分コピー</td>
<td>データのバックアップ、部分抽出</td>
</tr>
<tr>
<td><strong>ArraySort()</strong></td>
<td>昇順ソート</td>
<td>ランキング処理、中央値の算出</td>
</tr>
<tr>
<td><strong>ArraySetAsSeries()</strong></td>
<td>インデックス方向を時系列に変換</td>
<td>インジケーター開発、価格データ操作</td>
</tr>
</tbody>
</table>
<h2><span id="toc28">まとめ</span></h2>
<p>今回はMQL4の主要な配列関数6つについて解説しました。ポイントを振り返りましょう。</p>
<ul>
<li><strong>ArraySize()</strong>はループ処理の必須パートナー。多次元配列では全要素数が返る点に注意</li>
<li><strong>ArrayResize()</strong>は第3引数の<code>reserve_size</code>を活用してパフォーマンスを改善</li>
<li><strong>ArrayInitialize()</strong>はArrayResize後のゴミ値を防ぐために必ずセットで使う</li>
<li><strong>ArrayCopy()</strong>は部分コピーが便利。引数の順番（コピー先が最初）を間違えないように</li>
<li><strong>ArraySort()</strong>はMQL4では昇順のみ。降順が必要なら逆順で読み取る</li>
<li><strong>ArraySetAsSeries()</strong>はインジケーター開発の定番。<code>close[0]</code>を最新バーにするために使う</li>
</ul>
<p>これら6つの関数を使いこなせれば、EA開発やインジケーター作成の幅が大きく広がります。まずは実際にスクリプトやEAの中で試してみて、配列操作に慣れていきましょう！</p>
<p>投稿 <a href="https://mql-programing.com/archives/13052/%e3%80%90mql4%e3%80%91%e9%85%8d%e5%88%97%e9%96%a2%e6%95%b0%e3%82%92%e5%ae%8c%e5%85%a8%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bc%ef%bc%81arraysize%e3%83%bbarrayresize%e3%83%bbarraysort%e3%83%bbarraycopy/">【MQL4】配列関数を完全マスター！ArraySize・ArrayResize・ArraySort・ArrayCopy・ArrayInitialize・ArraySetAsSeriesの使い方</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【MQL4】文字列関数を完全マスター！StringFormat・DoubleToString・IntegerToString・StringLen・StringSubstrの使い方</title>
		<link>https://mql-programing.com/archives/13049/%e3%80%90mql4%e3%80%91%e6%96%87%e5%ad%97%e5%88%97%e9%96%a2%e6%95%b0%e3%82%92%e5%ae%8c%e5%85%a8%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bc%ef%bc%81stringformat%e3%83%bbdoubletostring%e3%83%bbintegertostring/</link>
		
		<dc:creator><![CDATA[朝日奈りさ]]></dc:creator>
		<pubDate>Sat, 18 Apr 2026 01:00:00 +0000</pubDate>
				<category><![CDATA[【中級編】MQLプログラムの読み方・書き方]]></category>
		<category><![CDATA[MQL4]]></category>
		<category><![CDATA[EA開発]]></category>
		<category><![CDATA[文字列関数]]></category>
		<category><![CDATA[StringFormat]]></category>
		<category><![CDATA[DoubleToString]]></category>
		<guid isPermaLink="false">https://mql-programing.com/?p=13049</guid>

					<description><![CDATA[<p>EA開発をしていると、「ログに価格やチケット番号を表示したい」「コメント欄にきれいな書式で情報を出力したい」という場面が頻繁にあります。そんなとき活躍するのが文字列関数です。 MQL4には多くの文字列関数が用意されていま [&#8230;]</p>
<p>投稿 <a href="https://mql-programing.com/archives/13049/%e3%80%90mql4%e3%80%91%e6%96%87%e5%ad%97%e5%88%97%e9%96%a2%e6%95%b0%e3%82%92%e5%ae%8c%e5%85%a8%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bc%ef%bc%81stringformat%e3%83%bbdoubletostring%e3%83%bbintegertostring/">【MQL4】文字列関数を完全マスター！StringFormat・DoubleToString・IntegerToString・StringLen・StringSubstrの使い方</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[<p>EA開発をしていると、「ログに価格やチケット番号を表示したい」「コメント欄にきれいな書式で情報を出力したい」という場面が頻繁にあります。そんなとき活躍するのが<strong>文字列関数</strong>です。</p>
<p>MQL4には多くの文字列関数が用意されていますが、この記事では特に使用頻度の高い<strong>5つの関数</strong>に絞って解説します。</p>
<ul>
<li><strong>DoubleToString</strong> — 実数を文字列に変換</li>
<li><strong>IntegerToString</strong> — 整数を文字列に変換</li>
<li><strong>StringFormat</strong> — 書式を指定して文字列を生成</li>
<li><strong>StringLen</strong> — 文字列の長さを取得</li>
<li><strong>StringSubstr</strong> — 文字列の一部を切り出す</li>
</ul>
<p>すべてサンプルコード付きで、最後には5関数を組み合わせた実践例も紹介します。それでは順番に見ていきましょう！</p>
<h2><span id="toc1">DoubleToString — 実数を文字列に変換する</span></h2>
<p><code>DoubleToString</code>は、double型の数値を指定した小数桁数の文字列に変換する関数です。価格やロット数の表示に欠かせません。</p>
<h3><span id="toc2">基本的な使い方</span></h3>
<pre><code class="language-mql4">void OnStart()
{
    double price = 145.123456;

    // 小数点以下3桁で表示
    string s1 = DoubleToString(price, 3);
    Print("3桁: ", s1);  // 出力: 145.123

    // 小数点以下5桁で表示
    string s2 = DoubleToString(price, 5);
    Print("5桁: ", s2);  // 出力: 145.12346（四捨五入される）
}
</code></pre>
<h3><span id="toc3">実践テクニック：_Digits との組み合わせ</span></h3>
<p>通貨ペアによって小数桁数は異なります（USDJPYは3桁、EURUSDは5桁など）。<code>_Digits</code>を使えば、通貨ペアに応じた桁数で自動的に変換できます。</p>
<pre><code class="language-mql4">void OnTick()
{
    double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

    // 通貨ペアに合った桁数で文字列化
    string priceStr = DoubleToString(bid, _Digits);
    Print(_Symbol, " の現在価格: ", priceStr);
}
</code></pre>
<p>この書き方なら、どの通貨ペアのチャートにEAを適用しても正しい桁数で価格が表示されます。</p>
<h2><span id="toc4">IntegerToString — 整数を文字列に変換する</span></h2>
<p><code>IntegerToString</code>は、整数を文字列に変換する関数です。単純な変換だけでなく、<strong>ゼロ埋め（パディング）</strong>もできるのが特徴です。</p>
<h3><span id="toc5">基本的な使い方</span></h3>
<pre><code class="language-mql4">void OnStart()
{
    int ticket = 12345;

    // 単純な変換
    string s1 = IntegerToString(ticket);
    Print("チケット: ", s1);  // 出力: 12345
}
</code></pre>
<h3><span id="toc6">ゼロ埋め（パディング）の使い方</span></h3>
<p><code>IntegerToString</code>の第2引数で桁数、第3引数で埋める文字を指定できます。ログの整形やファイル名の連番に便利です。</p>
<pre><code class="language-mql4">void OnStart()
{
    int num = 42;

    // 6桁にゼロ埋め
    string s1 = IntegerToString(num, 6, '0');
    Print("ゼロ埋め: ", s1);  // 出力: 000042

    // 8桁にスペース埋め（デフォルト）
    string s2 = IntegerToString(num, 8);
    Print("スペース埋め: [", s2, "]");  // 出力: [      42]
}
</code></pre>
<h2><span id="toc7">StringFormat — 書式指定で文字列を組み立てる</span></h2>
<p><code>StringFormat</code>はC言語の<code>sprintf</code>に相当する関数で、<strong>最も万能な文字列生成関数</strong>です。複数の値をひとつの文字列にまとめたいときに大活躍します。</p>
<h3><span id="toc8">主な書式指定子</span></h3>
<table>
<thead>
<tr>
<th>指定子</th>
<th>意味</th>
<th>例</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>%s</code></td>
<td>文字列</td>
<td>&#8220;USDJPY&#8221;</td>
</tr>
<tr>
<td><code>%d</code></td>
<td>整数</td>
<td>12345</td>
</tr>
<tr>
<td><code>%f</code></td>
<td>実数（デフォルト6桁）</td>
<td>145.123000</td>
</tr>
<tr>
<td><code>%.Nf</code></td>
<td>実数（小数N桁）</td>
<td>145.12（N=2の場合）</td>
</tr>
<tr>
<td><code>%%</code></td>
<td>%そのもの</td>
<td>%</td>
</tr>
</tbody>
</table>
<h3><span id="toc9">サンプルコード</span></h3>
<pre><code class="language-mql4">void OnStart()
{
    string symbol = "USDJPY";
    double price  = 145.678;
    int    ticket  = 99001;
    double lots   = 0.1;

    // 書式を指定して一気に文字列生成
    string msg = StringFormat("%s | Ticket:%d | Price:%.3f | Lots:%.2f",
                              symbol, ticket, price, lots);
    Print(msg);
    // 出力: USDJPY | Ticket:99001 | Price:145.678 | Lots:0.10
}
</code></pre>
<p><code>StringFormat</code>を使えば、文字列の連結（<code>+</code>演算子）を多用するよりもコードがすっきりします。特に3つ以上の値を組み合わせるときはStringFormatがおすすめです。</p>
<h2><span id="toc10">StringLen — 文字列の長さを取得する</span></h2>
<p><code>StringLen</code>は文字列の文字数を返す関数です。入力値のバリデーションや空文字チェックに使います。</p>
<h3><span id="toc11">基本的な使い方</span></h3>
<pre><code class="language-mql4">void OnStart()
{
    string text = "Hello MQL4";
    int len = StringLen(text);
    Print("文字数: ", len);  // 出力: 10（スペースも1文字）

    // 空文字チェック
    string comment = "";
    if(StringLen(comment) == 0)
    {
        Print("コメントは空です");
    }
}
</code></pre>
<h3><span id="toc12">実践テクニック：入力パラメータのチェック</span></h3>
<pre><code class="language-mql4">input string MagicPrefix = "EA01";

int OnInit()
{
    // プレフィックスが長すぎないかチェック
    if(StringLen(MagicPrefix) > 10)
    {
        Print("エラー: MagicPrefixは10文字以内にしてください");
        return INIT_PARAMETERS_INCORRECT;
    }
    return INIT_SUCCEEDED;
}
</code></pre>
<h2><span id="toc13">StringSubstr — 文字列の一部を切り出す</span></h2>
<p><code>StringSubstr</code>は文字列から指定位置・指定長さの部分文字列を取り出す関数です。日時文字列の分解やファイル名の加工に活用できます。</p>
<h3><span id="toc14">基本的な使い方</span></h3>
<pre><code class="language-mql4">void OnStart()
{
    string text = "2024.01.15 09:30:00";

    // 日付部分を取得（先頭から10文字）
    string datePart = StringSubstr(text, 0, 10);
    Print("日付: ", datePart);  // 出力: 2024.01.15

    // 時刻部分を取得（11文字目から最後まで）
    string timePart = StringSubstr(text, 11);
    Print("時刻: ", timePart);  // 出力: 09:30:00

    // 年だけ取得（先頭から4文字）
    string year = StringSubstr(text, 0, 4);
    Print("年: ", year);  // 出力: 2024
}
</code></pre>
<p>第2引数が<strong>開始位置</strong>（0始まり）、第3引数が<strong>切り出す文字数</strong>です。第3引数を省略すると、開始位置から末尾までの全文字が返されます。</p>
<h3><span id="toc15">実践テクニック：末尾N文字を切り出す関数</span></h3>
<p>StringLenとStringSubstrを組み合わせると、末尾から指定文字数を取り出すユーティリティ関数が作れます。</p>
<pre><code class="language-mql4">// 末尾n文字を取得する関数
string StringRight(string text, int n)
{
    int len = StringLen(text);
    if(n >= len) return text;
    return StringSubstr(text, len - n, n);
}

void OnStart()
{
    string filename = "report_2024.csv";
    string ext = StringRight(filename, 4);
    Print("拡張子: ", ext);  // 出力: .csv
}
</code></pre>
<h2><span id="toc16">実践例：5つの関数を組み合わせた注文ログ出力</span></h2>
<p>最後に、ここまで学んだ5つの関数を全て使った実践的なサンプルを紹介します。注文情報をきれいに整形してログ出力する関数です。</p>
<pre><code class="language-mql4">// 注文情報を整形して出力する関数
void PrintOrderInfo(int ticket)
{
    if(!OrderSelect(ticket, SELECT_BY_TICKET))
    {
        Print("チケット ", IntegerToString(ticket), " が見つかりません");
        return;
    }

    string symbol   = OrderSymbol();
    int    type     = OrderType();
    double lots     = OrderLots();
    double openPrice = OrderOpenPrice();
    string comment  = OrderComment();

    // IntegerToString: チケット番号をゼロ埋め
    string ticketStr = IntegerToString(ticket, 8, '0');

    // DoubleToString: 価格を通貨ペアに合った桁数で変換
    int digits = (int)MarketInfo(symbol, MODE_DIGITS);
    string priceStr = DoubleToString(openPrice, digits);

    // StringLen: コメントが空なら代替テキストを設定
    if(StringLen(comment) == 0)
        comment = "(コメントなし)";

    // StringSubstr: コメントが長すぎる場合は20文字に切り詰め
    if(StringLen(comment) > 20)
        comment = StringSubstr(comment, 0, 20) + "...";

    // StringFormat: 全体を整形
    string typeStr = (type == OP_BUY) ? "BUY" : "SELL";
    string log = StringFormat("[%s] %s %s %.2fLots @ %s Comment:%s",
                              ticketStr, symbol, typeStr,
                              lots, priceStr, comment);
    Print(log);
    // 出力例: [00012345] USDJPY BUY 0.10Lots @ 145.678 Comment:MyEA_Entry
}
</code></pre>
<p>このように、文字列関数を組み合わせることで<strong>読みやすく情報量の多いログ</strong>が簡単に作れます。デバッグ効率が格段に上がるので、ぜひ活用してください。</p>
<h2><span id="toc17">まとめ</span></h2>
<p>今回紹介した5つの文字列関数のポイントを整理します。</p>
<table>
<thead>
<tr>
<th>関数名</th>
<th>用途</th>
<th>覚えておきたいポイント</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>DoubleToString</strong></td>
<td>実数→文字列</td>
<td><code>_Digits</code>と組み合わせて通貨ペア対応</td>
</tr>
<tr>
<td><strong>IntegerToString</strong></td>
<td>整数→文字列</td>
<td>第2・第3引数でゼロ埋め（パディング）可能</td>
</tr>
<tr>
<td><strong>StringFormat</strong></td>
<td>書式指定で文字列生成</td>
<td><code>%s</code><code>%d</code><code>%.Nf</code>を使い分ける</td>
</tr>
<tr>
<td><strong>StringLen</strong></td>
<td>文字列の長さ取得</td>
<td>空文字チェックやバリデーションに活用</td>
</tr>
<tr>
<td><strong>StringSubstr</strong></td>
<td>部分文字列の切り出し</td>
<td>開始位置は0始まり、第3引数省略で末尾まで</td>
</tr>
</tbody>
</table>
<p>これらの関数はEA開発のあらゆる場面で登場します。特に<strong>StringFormat</strong>は使いこなせると、Print文やComment表示が一気にスマートになります。まずはサンプルコードをコピーして動かしてみるところから始めてみてください！</p>
<p>投稿 <a href="https://mql-programing.com/archives/13049/%e3%80%90mql4%e3%80%91%e6%96%87%e5%ad%97%e5%88%97%e9%96%a2%e6%95%b0%e3%82%92%e5%ae%8c%e5%85%a8%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bc%ef%bc%81stringformat%e3%83%bbdoubletostring%e3%83%bbintegertostring/">【MQL4】文字列関数を完全マスター！StringFormat・DoubleToString・IntegerToString・StringLen・StringSubstrの使い方</a> は <a href="https://mql-programing.com">自動売買を作ろう！</a> に最初に表示されました。</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
