1828 lines
No EOL
143 KiB
MQL4
1828 lines
No EOL
143 KiB
MQL4
//+------------------------------------------------------------------+
|
|
//| MSM-07S.mq4 |
|
|
//| Copyright 2025, TNK/TNK_SYSTEM |
|
|
//| https://note.com/tnk_system |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2025, TNK/TNK_SYSTEM"
|
|
#property link "https://note.com/tnk_system"
|
|
#property version "3.0" // ロジック調整
|
|
#property icon "TNKIcon.ico" // アイコン取り込み
|
|
|
|
#property description "[通貨ペア] GBPJPY [時間足] M30 [スタイル] スイング [ポジション数] 1"
|
|
#property description "[両建て] 無し [トレール] 有り [週末持ち越し] 有り"
|
|
#property description "[TP/SL] 買390/720 売600/150 pips(変更不可)"
|
|
#property description "[年末年始] 新規エントリー無し・決済のみ実行(12/21~1/3)"
|
|
#property description "[口座] 日足5本(GMT冬+2/夏+3)専用 [バー数] 1000以上"
|
|
|
|
#property strict
|
|
#include <stdlib.mqh>
|
|
//#define ROSOKU_Check
|
|
//#define MQLDebug_OPCL
|
|
//#define MQLDebug_SLTP
|
|
//#include <MQL4to5.mqh>
|
|
|
|
//string limitDate = "2025.3.31 23:59";
|
|
//int validAccount1 = 81154073; // 口座縛り1
|
|
//int validAccount2 = 230087286; // 口座縛り2
|
|
//+------------------------------------------------------------------+
|
|
//|ユーザー入力用パラメーター |
|
|
//+------------------------------------------------------------------+
|
|
input int MagicNumber = 853434; // マジックナンバー(他EAと重複不可)
|
|
input double Lots = 0.11; // ロット(単利運用時)
|
|
input double MM_Risk = 1.0; // リスク%(複利選択項目の何%か)
|
|
enum MM_Select{
|
|
Fixed, // 0:単利/固定
|
|
FreeMargin, // 1:複利/余剰証拠金
|
|
Balance, // 2:複利/残高
|
|
};
|
|
input MM_Select MM_ON = Fixed; // 複利機能(0:固定/1:余剰証拠金/2:残高)
|
|
double MaxSpread_pips = 4.0; // 許容スプレッド(Pips)
|
|
input double AllowSpread = 10.0; // 許容スプレッドPips(0:自動)
|
|
input bool Recording = false; // トレード情報記録(スプレッド・スリッページ等)
|
|
input bool VisualHistory = false; // 取引履歴線・pipsをチャートに表示
|
|
|
|
//+------------------------------------------------------------------+
|
|
//|内部設定・グローバル関数 |
|
|
//+------------------------------------------------------------------+
|
|
//内部設定
|
|
int Maxposition = 1; // 最大ポジション
|
|
int Slippage = 100; // 許容スリッページ(Point)
|
|
int TakeProfit_pips = 1000; // 利確指値(Pips)
|
|
int StopLoss_pips = 250; // 【共通|決済】損切逆指値(Pips)
|
|
string _Comment = "MSM-07S_GBPJPY_M30"; // 通知用コメント
|
|
|
|
//バックテスト用モード切替
|
|
bool Development = false; // 開発モードON/OFF(OnTester欄にRF表示、インジケータ表示)
|
|
// bool Modify = true;
|
|
bool Buy_Entry = true; // 買いエントリー
|
|
bool Sell_Entry = true; // 売りエントリー
|
|
|
|
//バーカウント・桁合わせ
|
|
int xBars = 0, xxBars = 0;;
|
|
double xpoint;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//|便利機能系 |
|
|
//+------------------------------------------------------------------+
|
|
//チャートセット固定用
|
|
string SYMBOL1 = "GBPJPY"; // シンボル名(頭6文字)
|
|
ENUM_TIMEFRAMES Chart_TimeFrame = PERIOD_M30; // タイムフレーム
|
|
|
|
// EAの状態変化用
|
|
bool ChartWarning;
|
|
|
|
// マジックナンバー重複セットアラート
|
|
static bool check_duplicate = true;
|
|
static const string kEA_NAME = (string)MagicNumber;
|
|
|
|
// スプレッド計測用
|
|
double MeasureSpread, SpreadAve = 0;
|
|
|
|
// オートスプレッド用
|
|
double Adjustspread = 5.0; // 平均スプレッド加算用宣言
|
|
double AllowMaxSpread = 8.0; // 自動最大許容スプレッド
|
|
double Adjustspread_Margin = 2.0; // 自動スプレッド調整幅
|
|
|
|
// 証拠金チェック
|
|
int aCmd = 0;
|
|
|
|
// DPI換算
|
|
double DPIAdjust;
|
|
|
|
// バックテスト時間計測
|
|
uint StartingTimestampBT;
|
|
|
|
// 各計測用パラメータ
|
|
int err, fp;
|
|
string filename;
|
|
double OSpread, CSpread;
|
|
uint StartOrderTimestamp, OrderCloseTimestamp, StartingTimestamp;
|
|
double Order_Price, Close_Price;
|
|
uint OpenLatency, CloseLatency;
|
|
string Timeframe = (Period() == PERIOD_M1? "M1": Period() == PERIOD_M5? "M5": Period() == PERIOD_M15? "M15":
|
|
Period() == PERIOD_M30? "M30": Period() == PERIOD_H1? "H1": Period() == PERIOD_H4? "H4":
|
|
Period() == PERIOD_D1? "D1": Period() == PERIOD_W1? "W1": "MN1");
|
|
string Open_Type, Close_Type;
|
|
bool WritingTPSL = false;
|
|
datetime OrderCloseTime_bak = 0;
|
|
|
|
// チャートにトレード履歴表示用
|
|
double totalpips = 0, ProfitFactor = 0;
|
|
double plus_profit = 0, minus_profit = 0;
|
|
double minus_count = 0, plus_count = 0;
|
|
double RRR, WinPer;
|
|
double TradeCounts;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//|ロジック用パラメータ |
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|
|
//|共通 |
|
|
//+------------------------------------------------------------------+
|
|
int MA_period1 = 20; // 【共通|トリガー】短期MA期間
|
|
int MA_period2 = 50; // 【共通|トリガー】長期MA期間
|
|
double Gap_Pips = 10.0; // 【共通|フィルター】1本前ローソク足終値と現在価格の差pips
|
|
|
|
//+------------------------------------------------------------------+
|
|
//|買い |
|
|
//+------------------------------------------------------------------+
|
|
//オープン
|
|
int MAFilter_period_buy = 96; // 【買い|フィルター】MA期間
|
|
int SD_period_buy = 12; // 【買い|フィルター】SD期間
|
|
double SD_Line_buy = 0.17; // 【買い|フィルター】SDライン
|
|
int BB_period_buy = 19; // 【買い|フィルター】BB期間
|
|
double BB_Hensa_buy = 2.5; // 【買い|フィルター】BB偏差
|
|
double Kairi_Judge_percent1 = 2.5; // 【買い|フィルター】順張り:MA乖離%
|
|
double Kairi_Judge_percent2 = 0.7; // 【買い|フィルター】逆張り:MA乖離%
|
|
int MA_PERIOD_Middle = 390; // 【買い|フィルター】中期MA期間
|
|
int MA_PERIOD_Long = 720; // 【買い|フィルター】長期MA期間
|
|
int MA_Shift = 4; // 【買い|フィルター】MAシフト
|
|
int MOM_buy1 = 17; // 【買い|フィルター】モメンタム期間
|
|
|
|
//決済・トレール
|
|
ENUM_TIMEFRAMES SD_TF_buy = PERIOD_D1; // 【買い|TP】SDタイムフレーム
|
|
int SD_Period_buy = 7; // 【買い|TP】SD期間
|
|
double SDmulTP_buy = 9.3; // 【買い|TP】SD倍数
|
|
int TakeProfit_pips_buy = 320; // 【買い|TP】最大利確指値(Pips)
|
|
int StopLoss_pips_buy = 140; // 【買い|SL】損切逆指値(Pips)
|
|
int TrailStartPips_buy = 120; // 【買い|トレール】開始Pips
|
|
int BarCountSL_buy = 20; // 【買い|トレール】安値を探すローソク足本数
|
|
|
|
//+------------------------------------------------------------------+
|
|
//|売り |
|
|
//+------------------------------------------------------------------+
|
|
//オープン
|
|
int MAFilter_period_sell = 64; // 【売り|フィルター】MA期間
|
|
int SD_period_sell = 20; // 【売り|フィルター】SD期間
|
|
double SD_Line_sell = 0.37; // 【売り|フィルター】SDライン
|
|
int BB_period_sell = 24; // 【売り|フィルター】BB期間
|
|
double BB_Hensa_sell = 3.0; // 【売り|フィルター】BB偏差
|
|
ENUM_TIMEFRAMES ADX_TF_Sell1 = PERIOD_D1; // 【売り|フィルター】ADXタイムフレーム
|
|
int ADX_PERIOD_Sell1 = 12; // 【売り|フィルター】ADX期間
|
|
int ADX1_Sell_Value1 = 54; // 【売り|フィルター】ADX限界値
|
|
|
|
//決済・トレール
|
|
ENUM_TIMEFRAMES SD_TF_sell = PERIOD_D1; // 【売り|TP】SDタイムフレーム
|
|
int SD_Period_sell = 7; // 【売り|TP】SD期間
|
|
double SDmulTP_sell = 3.3; // 【売り|TP】SD倍数
|
|
int TakeProfit_pips_sell = 600; // 【売り|TP】最大利確指値(Pips)
|
|
int StopLoss_pips_sell = 150; // 【売り|SL】損切逆指値(Pips)
|
|
int TrailStartPips_sell = 110; // 【売り|トレール】開始Pips
|
|
int BarCountSL_sell = 14; // 【買い|トレール】安値を探すローソク足本数
|
|
int ADX_PERIOD_sell2 = 7; // 【売り|決済】ADX期間
|
|
int ADX_Value_sell2 = 29; // 【売り|決済】ADX限界値
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| tester function |
|
|
//+------------------------------------------------------------------+
|
|
double OnTester()
|
|
{
|
|
// OnTesterに表示【リカバリーファクター|勝率】
|
|
if (Development)
|
|
{
|
|
// リカバリーファクター
|
|
return(NormalizeDouble(TesterStatistics(STAT_PROFIT) / TesterStatistics(STAT_EQUITY_DD), 2));
|
|
// 勝率
|
|
// return(NormalizeDouble(100*TesterStatistics(STAT_PROFIT_TRADES) / TesterStatistics(STAT_TRADES), 2));
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
//+------------------------------------------------------------------+
|
|
// バックテスト時間計測
|
|
StartingTimestampBT = GetTickCount();
|
|
//+------------------------------------------------------------------+
|
|
// 使用期限・デモ制御
|
|
/*int demosv = StringFind(AccountServer(), "demo", 0); // サーバー名に"demo"で稼働
|
|
int Demosv = StringFind(AccountServer(), "Demo", 0); // サーバー名に"Demo"で稼働
|
|
int trialsv = StringFind(AccountServer(), "trial", 0); // サーバー名に"trial"で稼働
|
|
int practicesv = StringFind(AccountServer(), "practice", 0); // サーバー名に"practice"で稼働
|
|
|
|
if (TimeCurrent() > StrToTime(limitDate) && //期限切れ
|
|
(!IsDemo() && demosv == -1 && Demosv == -1 && trialsv == -1 && practicesv == -1)
|
|
)
|
|
{
|
|
Alert(WindowExpertName() + " has expired or is not a demo account." + "\n"
|
|
+ "使用期限が過ぎたか、デモ口座ではありません。");
|
|
return(INIT_FAILED);
|
|
}
|
|
if (!IsTesting())
|
|
{// コメントに使用期限を表示
|
|
Comment("使用期限は " + limitDate + " (サーバー時間) までです。以降はデモ口座のみで稼働可能です。");
|
|
}*/
|
|
//+------------------------------------------------------------------+
|
|
// 口座番号縛り
|
|
/*if (IsTesting() == false)
|
|
{
|
|
if (!(AccountNumber() == validAccount1))// || AccountNumber() == validAccount2))
|
|
{
|
|
Alert("Not allowed account!" +"\n"+ "許可されていない口座です。");
|
|
return(INIT_FAILED); // 初期化が失敗した事を返し、EAを終了させる
|
|
}
|
|
}*/
|
|
//+------------------------------------------------------------------+
|
|
// GMT0ブローカー禁止・サマータイム自動調整用宣言
|
|
string BrokerName0 = "Ava Trad"; // Ava "Ava Trade Ltd.";
|
|
string BrokerName1 = "Exness T"; // Exness "Exness Technologies Ltd";
|
|
/*string BrokerName2 = "HF Marke"; // HFM "HF Markets (SV) Ltd.";"HF Markets(SV)Ltd.";
|
|
string BrokerName3 = "Tradexfi"; // XM "Tradexfin Limited";
|
|
string BrokerName4 = "FinTrade"; // XM "FinTrade Limited";
|
|
string BrokerName5 = "NOTESCO "; // IronFX "NOTESCO Ltd";
|
|
*/
|
|
//+------------------------------------------------------------------+
|
|
// GMT0ブローカー稼働禁止
|
|
if(StringSubstr(AccountCompany(), 0, 8) == BrokerName0
|
|
|| StringSubstr(AccountCompany(), 0, 8) == BrokerName1
|
|
)
|
|
{
|
|
Alert(
|
|
WindowExpertName() + " cannot run on brokers at GMT0"
|
|
+ "\n"
|
|
+ "GMT0のブローカーは稼働できません"
|
|
);
|
|
return(INIT_FAILED);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
// サマータイム自動調整
|
|
/*if (StringSubstr(AccountCompany(), 0, 8) == BrokerName1)
|
|
{
|
|
Summertime = 0;
|
|
}
|
|
else if (StringSubstr(AccountCompany(), 0, 8) == BrokerName2
|
|
|| StringSubstr(AccountCompany(), 0, 8) == BrokerName3
|
|
|| StringSubstr(AccountCompany(), 0, 8) == BrokerName4
|
|
|| StringSubstr(AccountCompany(), 0, 8) == BrokerName5
|
|
)
|
|
{
|
|
Summertime = 2;
|
|
}
|
|
else
|
|
{
|
|
Summertime = 1;
|
|
}*/
|
|
//+------------------------------------------------------------------+
|
|
// 小数点以下の桁数に応じてPipsの値を調整する
|
|
xpoint = Point();
|
|
if (Digits() == 3 || Digits() == 5)
|
|
{
|
|
xpoint = xpoint * 10;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
// DPI換算
|
|
double USERdpi = TerminalInfoInteger(TERMINAL_SCREEN_DPI);
|
|
double DevPCdpi = 144;
|
|
DPIAdjust = USERdpi / DevPCdpi;
|
|
//+------------------------------------------------------------------+
|
|
// 最大SL算出(コメント・複利の計算で使用)
|
|
StopLoss_pips = MathMax(StopLoss_pips_buy, StopLoss_pips_sell);
|
|
//+------------------------------------------------------------------+
|
|
// 初期化スプレッド(バックテスト時または手動時、それ以外や自動)
|
|
if (IsTesting() || AllowSpread != 0) MaxSpread_pips = AllowSpread;
|
|
if (AllowSpread == 0) MaxSpread_pips = AllowMaxSpread;
|
|
//+------------------------------------------------------------------+
|
|
// チャート自動変更・シンボル・チャートコメント・状態表示
|
|
if (!IsTesting())
|
|
{
|
|
ChartSet(); // チャート自動変更
|
|
CenterSymbol(); // 中央のシンボル
|
|
ChartComment(); // チャートコメント
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
// トレード履歴をチャートに表示(ライン・pips)
|
|
if (VisualHistory)
|
|
{
|
|
history();
|
|
PosHis();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
// 開発モード(販売時はfalseに)
|
|
if (Development) HideTestIndicators(false);// 使用しているインジケータを表示する
|
|
else HideTestIndicators(true);// 使用しているインジケータを非表示にする
|
|
//+------------------------------------------------------------------+
|
|
// マジックナンバー重複セットアラート
|
|
if (check_duplicate)
|
|
{
|
|
double term_global_var;
|
|
if (GlobalVariableGet(kEA_NAME, term_global_var))
|
|
{
|
|
Alert(
|
|
WindowExpertName() + " may have duplicate magic numbers. If all is well, press OK to continue with the setup"
|
|
+ "\n"
|
|
+ "マジックナンバー重複の可能性があります。問題が無ければ、OKを押して設定を継続してください。"
|
|
);
|
|
}
|
|
|
|
const datetime mutex_time = GlobalVariableSet(kEA_NAME, 1.0);
|
|
if (mutex_time == 0)
|
|
{
|
|
const int errcode = GetLastError();
|
|
Print("GlobalVariableSet: ERRCODE[", errcode, "]:", ErrorDescription(errcode));
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
// ファイル出力初期化処理
|
|
if (Recording) FileInit();
|
|
//+------------------------------------------------------------------+
|
|
|
|
return(0);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
//+------------------------------------------------------------------+
|
|
// マジックナンバー重複用
|
|
if(check_duplicate)
|
|
{
|
|
if(!GlobalVariableDel(kEA_NAME))
|
|
{
|
|
const int errcode = GetLastError();
|
|
Print("GlobalVariableDel: ERRCODE[", errcode, "]:", ErrorDescription(errcode));
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
// オブジェクト削除関連
|
|
if(!IsTesting())
|
|
{
|
|
ObjectsDeleteAll();
|
|
ChartSetInteger(0,CHART_COLOR_CHART_UP,clrLime);
|
|
ChartSetInteger(0,CHART_COLOR_CHART_DOWN,clrLime);
|
|
ChartSetInteger(0,CHART_COLOR_CHART_LINE,clrLime);
|
|
Comment("");
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
// バックテスト時間計算・出力
|
|
if(IsTesting())
|
|
{
|
|
uint EndingTimestamp = GetTickCount(); //始動時間
|
|
uint BT_Time = EndingTimestamp - StartingTimestampBT;
|
|
uint msec_unit = BT_Time % 1000;
|
|
datetime temp_date = BT_Time / 1000;
|
|
|
|
Print("バックテスト時間= ",
|
|
TimeHour(temp_date), "hour ",
|
|
TimeMinute(temp_date), "min ",
|
|
TimeSeconds(temp_date), ".", msec_unit, "sec ",
|
|
" 元データ= ", BT_Time);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
// BT後にチャートにトレード線とpips表示
|
|
if (IsTesting() && VisualHistory) TradeLinePips();
|
|
//+------------------------------------------------------------------+
|
|
// BT後の解析防止
|
|
//if (IsTesting()) {ObjectsDeleteAll(0, "#");}
|
|
//+------------------------------------------------------------------+
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
//+------------------------------------------------------------------+
|
|
//始動時間
|
|
StartingTimestamp = GetTickCount();
|
|
//+------------------------------------------------------------------+
|
|
// 注文制御
|
|
if (Volume[0] <= 10)
|
|
{
|
|
PositionClose(); // クローズ
|
|
Trailing(); // トレーリング
|
|
PositionOpen(); // オープン
|
|
}
|
|
if (Volume[0] == 21) {SetTPSL();} // TP, SLの再設定
|
|
//+------------------------------------------------------------------+
|
|
// チャート自動変更・シンボル・チャートコメント・状態表示
|
|
if (!IsTesting())
|
|
{
|
|
CenterSymbol(); // センターにシンボル情報
|
|
ChartComment(); // チャートコメント
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
// スプレッド値取得
|
|
if (!IsTesting() && AllowSpread == 0)
|
|
{
|
|
MeasureSpread = MarketInfo(Symbol(),MODE_SPREAD) / 10;
|
|
MeasureSP();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
// チャートにトレード線とpips表示
|
|
if (!IsTesting() && VisualHistory) TradeLinePips();
|
|
//+------------------------------------------------------------------+
|
|
// 決済がTP/SLなら情報取得
|
|
if (Recording && !WritingTPSL) ClosedTradeTPSL();
|
|
//+------------------------------------------------------------------+
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| ポジションのクローズ |
|
|
//+------------------------------------------------------------------+
|
|
void PositionClose()
|
|
{
|
|
int i;
|
|
double profit;
|
|
bool res = false;
|
|
|
|
// 所有しているポジションをクローズする
|
|
for(i=OrdersTotal()-1; i>=0; i--)
|
|
{
|
|
//オーダー選択(エラーを生じた場合、ループから抜け出す)
|
|
if (OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) == false)
|
|
{
|
|
//Print("OrderSelect returned the error of ", GetLastError() );
|
|
break;
|
|
}
|
|
|
|
//オーダー確認(通貨ペアが一致しない場合は、for文の先頭に戻る)
|
|
if (OrderSymbol() != Symbol()) continue;
|
|
|
|
//マジックナンバー確認(マジックナンバーが一致しない場合は、for文の先頭に戻る)
|
|
if (OrderMagicNumber() != MagicNumber) continue;
|
|
|
|
//エントリーからのローソク足本数が1本未満なら、for文の先頭に戻る)
|
|
int OrderOpenCandleCount = iBarShift(NULL, 0, OrderOpenTime());
|
|
if (OrderOpenCandleCount == 0) continue;
|
|
|
|
int spread = (int)MarketInfo(NULL, MODE_SPREAD);
|
|
|
|
if (OrderType() == OP_BUY)
|
|
{
|
|
profit = NormalizeDouble(Bid - OrderOpenPrice(), Digits); // 買いポジションだった場合の、含み損益を計算する
|
|
|
|
// オーダーを成り行き決済する
|
|
if (
|
|
(Exit2(false, profit) == 2 && spread <= (int)MaxSpread_pips*10)
|
|
|| (Exit2(false, profit) == 2 && spread > (int)MaxSpread_pips*10 && profit > 0)
|
|
)
|
|
{
|
|
CSpread = MarketInfo(NULL, MODE_SPREAD); // スプレッド取得
|
|
OrderCloseTimestamp = GetTickCount();// レイテンシー取得
|
|
Close_Price = Bid; // 決済売り注文を入れる価格
|
|
|
|
res = OrderClose(OrderTicket(), OrderLots(), Bid, NULL, Green);
|
|
|
|
CloseLatency = GetTickCount() - OrderCloseTimestamp; // レイテンシー取得
|
|
}
|
|
}
|
|
|
|
if (OrderType() == OP_SELL)
|
|
{
|
|
profit = NormalizeDouble(OrderOpenPrice() - Ask, Digits); // 売りポジションだった場合の、含み損益を計算する
|
|
|
|
// オーダーを成り行き決済する
|
|
if (
|
|
(Exit1(true, profit) == 1 && spread <= (int)MaxSpread_pips*10)
|
|
|| (Exit1(true, profit) == 1 && spread > (int)MaxSpread_pips*10 && profit > 0)
|
|
)
|
|
{
|
|
CSpread = MarketInfo(NULL, MODE_SPREAD); //スプレッド取得
|
|
OrderCloseTimestamp = GetTickCount(); // レイテンシー取得
|
|
Close_Price = Ask; // 決済買い注文を入れる価格
|
|
|
|
res = OrderClose(OrderTicket(), OrderLots(), Ask, NULL, Green);
|
|
|
|
CloseLatency = GetTickCount() - OrderCloseTimestamp; // レイテンシー取得
|
|
}
|
|
}
|
|
|
|
} // 所有しているポジションをクローズする(ココマデ)
|
|
|
|
// ファイル書込
|
|
if (res && Recording)
|
|
{
|
|
for(int j=OrdersHistoryTotal()-1; j>=0; j--)
|
|
{
|
|
if (OrderSelect(j, SELECT_BY_POS, MODE_HISTORY)==false) // 履歴を選択
|
|
{
|
|
Print("Access to history failed with error (",GetLastError(),")");
|
|
break;
|
|
}
|
|
if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
|
|
{
|
|
CloseTradeInfo();
|
|
break; // 1ポジ分で書込終了の場合はfor文を抜ける
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| トレーリング |
|
|
//+------------------------------------------------------------------+
|
|
void Trailing()
|
|
{
|
|
int i;
|
|
double profit;
|
|
bool res;
|
|
double StopLevel = MarketInfo(Symbol(),MODE_STOPLEVEL) * (xpoint / 10);
|
|
|
|
//if (Modify) // トレイルON、OFF
|
|
{
|
|
// 所有しているポジションのストップをトレールする
|
|
for(i=OrdersTotal()-1; i>=0; i--)
|
|
{
|
|
//オーダー選択(エラーを生じた場合、ループから抜け出す)
|
|
if (OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) == false)
|
|
{
|
|
//Print("OrderSelect returned the error of ", GetLastError() );
|
|
break;
|
|
}
|
|
|
|
//オーダー確認(通貨ペアが一致しない場合は、for文の先頭に戻る)
|
|
if (OrderSymbol() != Symbol()) continue;
|
|
|
|
//マジックナンバー確認(マジックナンバーが一致しない場合は、for文の先頭に戻る)
|
|
if (OrderMagicNumber() != MagicNumber) continue;
|
|
|
|
if (OrderType() == OP_BUY && xBars != Bars)
|
|
{
|
|
profit = NormalizeDouble(Bid - OrderOpenPrice(), Digits+2); // 買いポジションだった場合の、含み損益を計算する
|
|
double TrailingStart_buy = TrailStartPips_buy * xpoint;
|
|
double LowSL = iLow(NULL, 0, (iLowest(NULL, 0, MODE_LOW, BarCountSL_buy, 1)));
|
|
double SL_step_buy = MathMax(LowSL, MathAbs(OrderOpenPrice() - StopLoss_pips_buy * xpoint));
|
|
|
|
TrailingStart_buy = NormalizeDouble(TrailingStart_buy, Digits+2);
|
|
SL_step_buy = NormalizeDouble(SL_step_buy, Digits+2);
|
|
|
|
if (profit > TrailingStart_buy
|
|
&& OrderStopLoss() < SL_step_buy
|
|
&& Bid - StopLevel >= SL_step_buy
|
|
)
|
|
{
|
|
res = OrderModify(OrderTicket(),
|
|
OrderOpenPrice(),
|
|
SL_step_buy,
|
|
OrderTakeProfit(),
|
|
0,
|
|
MediumSeaGreen);
|
|
}
|
|
if(res) xBars = Bars;
|
|
}
|
|
|
|
if (OrderType() == OP_SELL && xBars != Bars)
|
|
{
|
|
profit = NormalizeDouble(OrderOpenPrice() - Ask, Digits+2); // 売りポジションだった場合の、含み損益を計算する
|
|
double TrailingStart_sell = TrailStartPips_sell * xpoint;
|
|
double HighSL = iHigh(NULL, 0, (iHighest(NULL, 0, MODE_HIGH, BarCountSL_sell, 1)));
|
|
double SL_step_sell = MathMin(HighSL, MathAbs(OrderOpenPrice() + StopLoss_pips_sell * xpoint));
|
|
|
|
TrailingStart_sell = NormalizeDouble(TrailingStart_sell, Digits+2);
|
|
SL_step_sell = NormalizeDouble(SL_step_sell, Digits+2);
|
|
|
|
if (profit > TrailingStart_sell
|
|
&& OrderStopLoss() > SL_step_sell
|
|
&& Ask + StopLevel <= SL_step_sell
|
|
)
|
|
{
|
|
res = OrderModify(OrderTicket(),
|
|
OrderOpenPrice(),
|
|
SL_step_sell,
|
|
OrderTakeProfit(),
|
|
0,
|
|
MediumSeaGreen);
|
|
}
|
|
if(res) xBars = Bars;
|
|
}
|
|
} // 所有しているポジションのストップをトレールする(ココマデ)
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| ポジションのオープン |
|
|
//+------------------------------------------------------------------+
|
|
void PositionOpen()
|
|
{
|
|
int i;
|
|
int ticket = -2; // チケット初期値。-1は失敗時の番号のため、使われない-2で初期化
|
|
int CountBuy = 0,CountSell = 0;
|
|
bool res;
|
|
|
|
// ポジションの数をカウントする
|
|
for(i=OrdersTotal()-1; i>=0; i--)
|
|
{
|
|
//オーダー選択(エラーを生じた場合、ループから抜け出す)
|
|
if (OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) == false)
|
|
{
|
|
//Print("OrderSelect returned the error of ", GetLastError() );
|
|
break;
|
|
}
|
|
|
|
//オーダー確認(通貨ペアが一致しない場合は、for文の先頭に戻る)
|
|
if (OrderSymbol() != Symbol()) continue;
|
|
|
|
//マジックナンバー確認(マジックナンバーが一致しない場合は、for文の先頭に戻る)
|
|
if (OrderMagicNumber() != MagicNumber) continue;
|
|
|
|
if (OrderType() == OP_BUY)
|
|
{
|
|
CountBuy = CountBuy + 1;
|
|
}
|
|
|
|
if (OrderType() == OP_SELL)
|
|
{
|
|
CountSell = CountSell + 1;
|
|
}
|
|
|
|
aCmd = OrderType();
|
|
|
|
} // ポジションの数をカウントする(ココマデ)
|
|
|
|
// 証拠金不足・トレード許可チェック
|
|
if (EquityCheck())
|
|
{
|
|
double SD_TPSL_buy = iStdDev(NULL, SD_TF_buy, SD_Period_buy, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
double TP_buy = MathMin(SD_TPSL_buy * SDmulTP_buy, TakeProfit_pips_buy * xpoint);
|
|
double SD_TPSL_sell = iStdDev(NULL, SD_TF_sell, SD_Period_sell, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
double TP_sell = MathMin(SD_TPSL_sell * SDmulTP_sell, TakeProfit_pips_sell * xpoint);
|
|
|
|
// エントリー条件を確認し、成立していればエントリーを行う
|
|
if (Entry(true) == 1 // 買いエントリー
|
|
//&& CountSell == 0
|
|
&& CountBuy < Maxposition
|
|
&& Buy_Entry
|
|
&& xxBars != Bars
|
|
)
|
|
{
|
|
OSpread = MarketInfo(NULL, MODE_SPREAD);// スプレッド取得
|
|
StartOrderTimestamp = GetTickCount();// レイテンシー取得
|
|
Order_Price = Ask;// 買い注文を入れる価格
|
|
ticket = OrderSend(Symbol(),
|
|
OP_BUY,
|
|
CalculateLots(MM_Risk, StopLoss_pips),
|
|
Ask,
|
|
Slippage,
|
|
Ask - StopLoss_pips_buy * xpoint,
|
|
Ask + TP_buy,
|
|
_Comment,
|
|
MagicNumber,
|
|
0,
|
|
Blue);
|
|
|
|
// エントリーが失敗であれば、TPSLを分割して注文する
|
|
if (ticket == -1)
|
|
{
|
|
ticket = OrderSend(Symbol(),
|
|
OP_BUY,
|
|
CalculateLots(MM_Risk, StopLoss_pips),
|
|
Ask,
|
|
Slippage,
|
|
0,
|
|
0,
|
|
_Comment,
|
|
MagicNumber,
|
|
0,
|
|
Blue);
|
|
// エントリーに成功していれば、TP, SLをセットする
|
|
if (ticket != -1)
|
|
{
|
|
// チケットを使ってオーダーを選択(エラーを生じた場合、何もしない)
|
|
if( OrderSelect( ticket, SELECT_BY_TICKET ) == true )
|
|
{
|
|
res = OrderModify(OrderTicket(),
|
|
OrderOpenPrice(),
|
|
OrderOpenPrice() - StopLoss_pips_buy * xpoint,
|
|
OrderOpenPrice() + TP_buy,//TakeProfit_pips * xpoint,
|
|
0,
|
|
MediumSeaGreen);
|
|
|
|
}
|
|
}
|
|
}
|
|
OpenLatency = GetTickCount() - StartOrderTimestamp; // レイテンシー取得
|
|
Open_Type = "Buy"; // ticket未成立時の出力用
|
|
if (ticket != -1)
|
|
{
|
|
xxBars = Bars;
|
|
WritingTPSL = false; // TP/SL書込判定用
|
|
}
|
|
}
|
|
|
|
else if (Entry(false) == 2 // 売りエントリー
|
|
//&& CountBuy == 0
|
|
&& CountSell < Maxposition
|
|
&& Sell_Entry
|
|
&& xxBars != Bars
|
|
)
|
|
{
|
|
OSpread = MarketInfo(NULL, MODE_SPREAD);// スプレッド取得
|
|
StartOrderTimestamp = GetTickCount();// レイテンシー取得
|
|
Order_Price = Bid;// 売り注文を入れる価格
|
|
ticket = OrderSend(Symbol(),
|
|
OP_SELL,
|
|
CalculateLots(MM_Risk, StopLoss_pips),
|
|
Bid,
|
|
Slippage,
|
|
Bid + StopLoss_pips_sell * xpoint,
|
|
Bid - TP_sell,
|
|
_Comment,
|
|
MagicNumber,
|
|
0,
|
|
Red);
|
|
// エントリーが失敗であれば、TPSLを分割して注文する
|
|
if (ticket == -1)
|
|
{
|
|
ticket = OrderSend(Symbol(),
|
|
OP_SELL,
|
|
CalculateLots(MM_Risk, StopLoss_pips),
|
|
Bid,
|
|
Slippage,
|
|
0,
|
|
0,
|
|
_Comment,
|
|
MagicNumber,
|
|
0,
|
|
Red);
|
|
// エントリーに成功していれば、TP, SLをセットする
|
|
if (ticket != -1)
|
|
{
|
|
// チケットを使ってオーダーを選択(エラーを生じた場合、何もしない)
|
|
if( OrderSelect( ticket, SELECT_BY_TICKET ) == true )
|
|
{
|
|
res = OrderModify(OrderTicket(),
|
|
OrderOpenPrice(),
|
|
OrderOpenPrice() + StopLoss_pips_sell * xpoint,
|
|
OrderOpenPrice() - TP_sell,//TakeProfit_pips * xpoint,
|
|
0,
|
|
MediumSeaGreen);
|
|
}
|
|
}
|
|
}
|
|
OpenLatency = GetTickCount() - StartOrderTimestamp; // レイテンシー取得
|
|
Open_Type = "Sell"; // ticket未成立時の出力用
|
|
if (ticket != -1)
|
|
{
|
|
xxBars = Bars;
|
|
WritingTPSL = false; // TP/SL書込判定用
|
|
}
|
|
}
|
|
}
|
|
|
|
// ファイル書込
|
|
if (ticket != -2 && Recording)
|
|
{
|
|
if (!OrderSelect(ticket, SELECT_BY_TICKET)) OpenTradeInfo_false(); // チケット未成立時の書込
|
|
if (OrderSelect(ticket, SELECT_BY_TICKET)) OpenTradeInfo(); // チケット成立時の書込
|
|
}
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
bool EquityCheck()
|
|
{
|
|
// 証拠金不足・トレード許可チェック
|
|
double usedMoney = AccountEquity() - AccountFreeMarginCheck(Symbol(), aCmd, CalculateLots(MM_Risk, StopLoss_pips));
|
|
if (!(
|
|
(AccountStopoutMode() == 0 && usedMoney > 0.0 && (AccountEquity() / usedMoney) * 100 <= AccountStopoutLevel())
|
|
|| (AccountStopoutMode() == 0 && usedMoney > 0.0 && AccountFreeMarginCheck(Symbol(), aCmd, CalculateLots(MM_Risk, StopLoss_pips)) <= 0)
|
|
|| (AccountStopoutMode() == 1 && AccountFreeMarginCheck(Symbol(), aCmd, CalculateLots(MM_Risk, StopLoss_pips)) <= AccountStopoutLevel())
|
|
)
|
|
&& IsTradeAllowed()) // トレード許可判定
|
|
{
|
|
return(true);
|
|
}
|
|
else return(false);
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| TakeProfit, StopLoss |
|
|
//+------------------------------------------------------------------+
|
|
void SetTPSL()
|
|
{
|
|
int i;
|
|
bool res;
|
|
|
|
// ポジションにTP, SLをセットする
|
|
for(i=OrdersTotal()-1; i>=0; i--)
|
|
{
|
|
//オーダー選択(エラーを生じた場合、ループから抜け出す)
|
|
if (OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) == false)
|
|
{
|
|
//Print("OrderSelect returned the error of ", GetLastError() );
|
|
break;
|
|
}
|
|
|
|
//オーダー確認(通貨ペアが一致しない場合は、for文の先頭に戻る)
|
|
if (OrderSymbol() != Symbol()) continue;
|
|
|
|
//マジックナンバー確認(マジックナンバーが一致しない場合は、for文の先頭に戻る)
|
|
if (OrderMagicNumber() != MagicNumber) continue;
|
|
|
|
// 買いポジションの場合
|
|
if (OrderType() == OP_BUY)
|
|
{
|
|
// TP, SLがどちらも設定されていなければ、TP, SLを設定する
|
|
if (OrderStopLoss() == 0 && OrderTakeProfit() == 0)
|
|
{
|
|
double SD_TPSL_buy = iStdDev(NULL, SD_TF_buy, SD_Period_buy, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
double TP_buy = MathMin(SD_TPSL_buy * SDmulTP_buy, TakeProfit_pips_buy * xpoint);
|
|
|
|
res = OrderModify(OrderTicket(),
|
|
OrderOpenPrice(),
|
|
OrderOpenPrice() - StopLoss_pips_buy * xpoint,//SL_buy,
|
|
OrderOpenPrice() + TP_buy,//TakeProfit_pips * xpoint,
|
|
0,
|
|
MediumSeaGreen);
|
|
}
|
|
}
|
|
|
|
// 売りポジションの場合
|
|
if (OrderType() == OP_SELL)
|
|
{
|
|
// TP, SLがどちらも設定されていなければ、TP, SLを設定する
|
|
if (OrderStopLoss() == 0 && OrderTakeProfit() == 0)
|
|
{
|
|
double SD_TPSL_sell = iStdDev(NULL, SD_TF_sell, SD_Period_sell, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
double TP_sell = MathMin(SD_TPSL_sell * SDmulTP_sell, TakeProfit_pips_sell * xpoint);
|
|
|
|
res = OrderModify(OrderTicket(),
|
|
OrderOpenPrice(),
|
|
OrderOpenPrice() + StopLoss_pips_sell * xpoint,//SL_sell,
|
|
OrderOpenPrice() - TP_sell,//TakeProfit_pips * xpoint,
|
|
0,
|
|
MediumSeaGreen);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 複利機能 |
|
|
//+------------------------------------------------------------------+
|
|
// 複利機能のロット数を計算する
|
|
double CalculateLots(double risk, // 許容するリスク
|
|
int sl_pips) // ストップロス
|
|
{
|
|
// バックテスト時は、バックテスト用の複利機能を使用する
|
|
if (IsTesting())
|
|
return(CalculateLots_forTest(risk, sl_pips));
|
|
else
|
|
return(CalculateLots_forReal(risk, sl_pips));
|
|
}
|
|
|
|
// 複利機能のロット数を計算する(実トレード用)
|
|
double CalculateLots_forReal(double risk, // 許容するリスク
|
|
int sl_pips) // ストップロス
|
|
{
|
|
double freemargin; // アカウントの余剰証拠金
|
|
double balance; // アカウントの口座残高
|
|
double credit; // アカウントのクレジット
|
|
double tickvalue; // 1ロット1pip当たりの証拠金通貨相当額
|
|
double lotstep; // サーバのロット数の最小刻み制限
|
|
double maxlots; // サーバの最大ロット数制限
|
|
double minlots; // サーバの最小ロット数制限
|
|
double lotsize = Lots; // ロットサイズ
|
|
|
|
freemargin = AccountFreeMargin();
|
|
balance = AccountBalance();
|
|
credit = AccountCredit();
|
|
tickvalue = MarketInfo(NULL, MODE_TICKVALUE);
|
|
lotstep = MarketInfo(NULL, MODE_LOTSTEP);
|
|
maxlots = MarketInfo(NULL, MODE_MAXLOT);
|
|
minlots = MarketInfo(NULL, MODE_MINLOT);
|
|
|
|
// 複利機能を使わない場合、Lotsから修正されたlotsizeを返す
|
|
int step = (int)MathAbs(MathLog10(MarketInfo(Symbol(), MODE_LOTSTEP)));
|
|
lotsize = NormalizeDouble(Lots, (int)step); //ロットステップで四捨五入
|
|
lotsize = MathMax(minlots, MathMin(maxlots, lotsize)); //最小ロット以下なら最小ロットに、最大ロット以上なら最大ロットに修正
|
|
if (MM_ON == Fixed) return(lotsize);
|
|
|
|
// tickvalueはpipsではなくpointなので、小数点以下の桁数に応じて補正する
|
|
/*if (StringSubstr(Symbol(), 0, 6) == "XAUUSD" || StringSubstr(Symbol(), 0, 4) == "GOLD")
|
|
{
|
|
if (Digits() == 2)
|
|
tickvalue = tickvalue * 10;
|
|
else if (Digits() == 3)
|
|
tickvalue = tickvalue * 100;
|
|
}
|
|
else if (!(StringSubstr(Symbol(), 0, 6) == "XAUUSD" || StringSubstr(Symbol(), 0, 4) == "GOLD"))
|
|
{*/
|
|
if (Digits() == 3 || Digits() == 5)
|
|
tickvalue = tickvalue * 10;
|
|
//}
|
|
|
|
// 許容するリスクとSLの幅から、ロットサイズを計算する。
|
|
if (MM_ON == FreeMargin) // 余剰証拠金方式
|
|
{
|
|
lotsize = (freemargin * risk / 100.0) // 許容するリスク (余剰証拠金のrisk%)
|
|
/ (sl_pips * tickvalue); // 1ロットでSLにかかった時の金額
|
|
}
|
|
else if (MM_ON == Balance) // 残高方式
|
|
{
|
|
lotsize = ((balance + credit) * risk / 100.0) // 許容するリスク (余剰証拠金のrisk%)
|
|
/ (sl_pips * tickvalue); // 1ロットでSLにかかった時の金額
|
|
}
|
|
|
|
// サーバのロット数の刻みに合わせてロット数を修正
|
|
lotsize = MathFloor(lotsize / lotstep) * lotstep;
|
|
|
|
// サーバの最小ロット数・最大ロット数で補正をかける
|
|
lotsize = MathMax(lotsize, minlots);
|
|
lotsize = MathMin(lotsize, maxlots);
|
|
|
|
return(lotsize);
|
|
}
|
|
|
|
// 複利機能のロット数を計算する(バックテスト用)
|
|
double CalculateLots_forTest(double risk, // 許容するリスク
|
|
int sl_pips) // ストップロス
|
|
{
|
|
double freemargin; // アカウントの余剰証拠金
|
|
double balance; // アカウントの口座残高
|
|
double credit; // アカウントのクレジット
|
|
double tickvalue; // 1ロット1pip当たりの証拠金通貨相当額
|
|
double lotstep; // サーバのロット数の最小刻み制限
|
|
double maxlots; // サーバの最大ロット数制限
|
|
double minlots; // サーバの最小ロット数制限
|
|
double lotamount; // 1ロットの通貨数
|
|
double lotsize = Lots; // ロットサイズ
|
|
double conv; // 口座通貨種類による補正係数
|
|
|
|
freemargin = AccountFreeMargin();
|
|
balance = AccountBalance();
|
|
credit = AccountCredit();
|
|
tickvalue = MarketInfo(NULL, MODE_TICKVALUE);
|
|
lotstep = MarketInfo(NULL, MODE_LOTSTEP);
|
|
maxlots = MarketInfo(NULL, MODE_MAXLOT);
|
|
minlots = MarketInfo(NULL, MODE_MINLOT);
|
|
lotamount = MarketInfo(NULL, MODE_LOTSIZE);
|
|
|
|
// 複利機能を使わない場合、Lotsから修正されたlotsizeを返す
|
|
int step = (int)MathAbs(MathLog10(MarketInfo(Symbol(), MODE_LOTSTEP)));
|
|
lotsize = NormalizeDouble(Lots, step); //ロットステップで四捨五入
|
|
lotsize = MathMax(minlots, MathMin(maxlots, lotsize)); //最小ロット以下なら最小ロットに、最大ロット以上なら最大ロットに修正
|
|
if (MM_ON == Fixed) return(lotsize);
|
|
|
|
// 1万通貨*1pips = $1 = 100円と仮定し、1ロット1pipの変動が口座通貨でいくらに相当するか計算
|
|
// 1 lot = 10万通貨
|
|
// 口座通貨 = JPY : tickvalue = 1000円/(lot・pip)
|
|
// 口座通貨 = USD : tickvalue = $10/(lot・pip)
|
|
/*if (StringSubstr(Symbol(), 0, 6) == "XAUUSD" || StringSubstr(Symbol(), 0, 4) == "GOLD")
|
|
{
|
|
conv = 1000;
|
|
if (AccountCurrency() == "JPY")
|
|
conv = 100000;
|
|
tickvalue = lotamount / 10000 * conv;
|
|
}
|
|
else if (!(StringSubstr(Symbol(), 0, 6) == "XAUUSD" || StringSubstr(Symbol(), 0, 4) == "GOLD"))
|
|
{*/
|
|
conv = 1;
|
|
if (AccountCurrency() == "JPY")
|
|
conv = 100;
|
|
tickvalue = lotamount / 10000 * conv;
|
|
//}
|
|
|
|
// 許容するリスクとSLの幅から、ロットサイズを計算する。
|
|
if (MM_ON == FreeMargin) // 余剰証拠金方式
|
|
{
|
|
lotsize = (freemargin * risk / 100.0) // 許容するリスク (余剰証拠金のrisk%)
|
|
/ (sl_pips * tickvalue); // 1ロットでSLにかかった時の金額
|
|
}
|
|
else if (MM_ON == Balance) // 残高方式
|
|
{
|
|
lotsize = ((balance + credit) * risk / 100.0) // 許容するリスク (余剰証拠金のrisk%)
|
|
/ (sl_pips * tickvalue); // 1ロットでSLにかかった時の金額
|
|
}
|
|
|
|
// サーバのロット数の刻みに合わせてロット数を修正
|
|
lotsize = MathFloor(lotsize / lotstep) * lotstep;
|
|
|
|
// サーバの最小ロット数・最大ロット数で補正をかける
|
|
lotsize = MathMax(lotsize, minlots);
|
|
lotsize = MathMin(lotsize, maxlots);
|
|
|
|
return(lotsize);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| エントリー総括 |
|
|
//+------------------------------------------------------------------+
|
|
int Entry(bool isbuy)
|
|
{
|
|
if (Entry_Rule1(isbuy) == 1 && (Entry_Filter1(isbuy) == 1 || Entry_Filter1(isbuy) == 3)
|
|
&& (Entry_Filter2(isbuy) == 1 || Entry_Filter2(isbuy) == 3)
|
|
&& (Entry_Filter3(isbuy) == 1 || Entry_Filter3(isbuy) == 3)
|
|
&& (Entry_Filter4(isbuy) == 1 || Entry_Filter4(isbuy) == 3)
|
|
)
|
|
{
|
|
return(1);
|
|
}
|
|
else if (Entry_Rule1(isbuy) == 2 && (Entry_Filter1(isbuy) == 2 || Entry_Filter1(isbuy) == 3)
|
|
&& (Entry_Filter2(isbuy) == 2 || Entry_Filter2(isbuy) == 3)
|
|
&& (Entry_Filter3(isbuy) == 2 || Entry_Filter3(isbuy) == 3)
|
|
&& (Entry_Filter4(isbuy) == 2 || Entry_Filter4(isbuy) == 3)
|
|
)
|
|
{
|
|
return(2);
|
|
}
|
|
else
|
|
{
|
|
return(0);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 売りポジションの決済総括 |
|
|
//+------------------------------------------------------------------+
|
|
int Exit1(bool isbuy, double profit)
|
|
{
|
|
if (Exit_Rule1(isbuy, profit) == 3 && Exit_Rule2(isbuy, profit) == 3)
|
|
{
|
|
return(0);
|
|
}
|
|
else if (Exit_Rule1(isbuy, profit) == 1)
|
|
{
|
|
return(1);
|
|
}
|
|
else if (Exit_Rule2(isbuy, profit) == 1)
|
|
{
|
|
return(1);
|
|
}
|
|
else
|
|
{
|
|
return(0);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 買いポジションの決済総括 |
|
|
//+------------------------------------------------------------------+
|
|
int Exit2(bool isbuy, double profit)
|
|
{
|
|
if (Exit_Rule1(isbuy, profit) == 3 && Exit_Rule2(isbuy, profit) == 3)
|
|
{
|
|
return(0);
|
|
}
|
|
else if (Exit_Rule1(isbuy, profit) == 2)
|
|
{
|
|
return(2);
|
|
}
|
|
else if (Exit_Rule2(isbuy, profit) == 2)
|
|
{
|
|
return(2);
|
|
}
|
|
else
|
|
{
|
|
return(0);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| エントリールール1 |
|
|
//+------------------------------------------------------------------+
|
|
int Entry_Rule1(bool isbuy)
|
|
{
|
|
//エントリールール1
|
|
double MA_S1 = iMA(NULL, 0, MA_period1, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
double MA_S2 = iMA(NULL, 0, MA_period1, 0, MODE_SMA, PRICE_CLOSE, 2);
|
|
double MA_L1 = iMA(NULL, 0, MA_period2, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
double MA_L2 = iMA(NULL, 0, MA_period2, 0, MODE_SMA, PRICE_CLOSE, 2);
|
|
|
|
if (isbuy && MA_S2 < MA_L2 && MA_S1 >= MA_L1)
|
|
{
|
|
return(1);
|
|
}
|
|
|
|
if (!isbuy && MA_S2 > MA_L2 && MA_S1 <= MA_L1)
|
|
{
|
|
return(2);
|
|
}
|
|
|
|
else
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
//エントリールール1ココマデ
|
|
return(3);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| エントリーフィルター1 |
|
|
//+------------------------------------------------------------------+
|
|
int Entry_Filter1(bool isbuy)
|
|
{
|
|
//エントリーフィルター1
|
|
//スプレッドフィルター
|
|
double spread = MarketInfo(NULL, MODE_SPREAD);
|
|
|
|
if (Digits == 3 || Digits == 5)
|
|
spread /= 10.0;
|
|
if (spread > MaxSpread_pips)
|
|
return(0); // スプレッドが指定pips以上でトレード不許可
|
|
|
|
//ローソク足マージンフィルター
|
|
double Close0 = iClose(NULL, 0, 0);
|
|
double Close1 = iClose(NULL, 0, 1);
|
|
|
|
if (isbuy && Close0 - Close1 >= Gap_Pips * xpoint) return(0); // (現在価格-1本足終値)が、指定pips以上だったら買い禁止
|
|
if (!isbuy && Close1 - Close0 >= Gap_Pips * xpoint) return(0); // (1本足終値-現在価格)が、指定pips以上だったら売り禁止
|
|
|
|
//12/20~1/3まではエントリーしない
|
|
int NGMonth = Month();
|
|
int NGDay = Day();
|
|
if ((NGMonth == 12 && NGDay >= 21) || (NGMonth == 1 && NGDay <= 3))
|
|
{
|
|
return(0);
|
|
} // エントリー出来ない
|
|
|
|
//サーバー0時台はエントリーしない
|
|
if (TimeHour(TimeCurrent()) == 0) return(0);
|
|
|
|
//エントリーフィルター1ココマデ
|
|
return(3);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| エントリーフィルター2 |
|
|
//+------------------------------------------------------------------+
|
|
int Entry_Filter2(bool isbuy)
|
|
{
|
|
//エントリーフィルター2
|
|
// MAフィルター
|
|
double MA_1_buy = iMA(NULL, 0, MAFilter_period_buy, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
double MA_2_buy = iMA(NULL, 0, MAFilter_period_buy, 0, MODE_SMA, PRICE_CLOSE, 2);
|
|
double SD_buy1 = iStdDev(NULL, 0, SD_period_buy, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
double MA_1_sell = iMA(NULL, 0, MAFilter_period_sell, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
double MA_2_sell = iMA(NULL, 0, MAFilter_period_sell, 0, MODE_SMA, PRICE_CLOSE, 2);
|
|
double SD_sell1 = iStdDev(NULL, 0, SD_period_sell, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
|
|
if (isbuy && MA_2_buy >= MA_1_buy && SD_buy1 > SD_Line_buy)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
if (!isbuy &&
|
|
(MA_2_sell <= MA_1_sell
|
|
||
|
|
(MA_2_sell > MA_1_sell && SD_sell1 > SD_Line_sell)
|
|
)
|
|
)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
//エントリーフィルター2ココマデ
|
|
return(3);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| エントリーフィルター3 |
|
|
//+------------------------------------------------------------------+
|
|
int Entry_Filter3(bool isbuy)
|
|
{
|
|
//エントリーフィルター3
|
|
if (isbuy)
|
|
{
|
|
double BB_buy1 = iBands(NULL, 0, BB_period_buy, BB_Hensa_buy, 0, PRICE_CLOSE, MODE_UPPER, 1);
|
|
if (BB_buy1 < Close[1]) return(0);
|
|
|
|
double Momentum_buy1 = iMomentum(NULL, 0, MOM_buy1, PRICE_CLOSE, 1);
|
|
if (Momentum_buy1 < 100) return(0);
|
|
}
|
|
|
|
if (!isbuy)
|
|
{
|
|
double BB_sell1 = iBands(NULL, 0, BB_period_sell, BB_Hensa_sell, 0, PRICE_CLOSE, MODE_LOWER, 1);
|
|
if (BB_sell1 > Close[1]) return(0);
|
|
|
|
double ADX_Sell1 = iADX(NULL, ADX_TF_Sell1, ADX_PERIOD_Sell1, PRICE_CLOSE, MODE_MAIN, 1);
|
|
if (ADX_Sell1 > ADX1_Sell_Value1) return(0);
|
|
|
|
}
|
|
//エントリーフィルター3ココマデ
|
|
return(3);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| エントリーフィルター4 |
|
|
//+------------------------------------------------------------------+
|
|
int Entry_Filter4(bool isbuy)
|
|
{
|
|
//エントリーフィルター4
|
|
// アップトレンド+中期のMAが下に乖離で「買い」
|
|
if (isbuy)
|
|
{
|
|
if ((Trend_Judge() >= 2 && Kairi_Judge() <= Kairi_Judge_percent1)
|
|
|| Kairi_Judge() <= -Kairi_Judge_percent2)
|
|
{
|
|
return(1);
|
|
} // 買い
|
|
else
|
|
{
|
|
return(0);
|
|
}
|
|
}
|
|
//エントリーフィルター4ココマデ
|
|
return(3);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
int Trend_Judge()
|
|
{
|
|
double MA_Middle1 = iMA(NULL, 0, MA_PERIOD_Middle, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
double MA_Long1 = iMA(NULL, 0, MA_PERIOD_Long, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
double MA_Middle2 = iMA(NULL, 0, MA_PERIOD_Middle, 0, MODE_SMA, PRICE_CLOSE, MA_Shift);
|
|
double MA_Long2 = iMA(NULL, 0, MA_PERIOD_Long, 0, MODE_SMA, PRICE_CLOSE, MA_Shift);
|
|
int UP_Trend = 0; //アップトレンドを0~3段階評価
|
|
|
|
if (MA_Middle1 > MA_Long1)
|
|
{
|
|
UP_Trend = UP_Trend+1;
|
|
}
|
|
if (MA_Middle1-MA_Middle2 > 0)
|
|
{
|
|
UP_Trend = UP_Trend+1;
|
|
}
|
|
if (MA_Long1-MA_Long2 > 0)
|
|
{
|
|
UP_Trend = UP_Trend+1;
|
|
}
|
|
return(UP_Trend);
|
|
}
|
|
|
|
double Kairi_Judge()
|
|
{
|
|
// 長期移動平均線に対し短期移動平均線が、指定%以上、上に乖離したら「売り」、下に乖離したら「買い」。
|
|
double Close1 = iClose(NULL, 0, 1);
|
|
double MA_Long = iMA(NULL, 0, MA_PERIOD_Long, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
|
|
double Long_Kairi = (Close1 - MA_Long) / Close1 * 100;
|
|
|
|
return(Long_Kairi);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 決済ルール1 |
|
|
//+------------------------------------------------------------------+
|
|
int Exit_Rule1(bool isbuy, double profit)
|
|
{
|
|
// 決済ルール1
|
|
double MA_S1 = iMA(NULL, 0, MA_period1, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
double MA_S2 = iMA(NULL, 0, MA_period1, 0, MODE_SMA, PRICE_CLOSE, 2);
|
|
double MA_L1 = iMA(NULL, 0, MA_period2, 0, MODE_SMA, PRICE_CLOSE, 1);
|
|
double MA_L2 = iMA(NULL, 0, MA_period2, 0, MODE_SMA, PRICE_CLOSE, 2);
|
|
|
|
if (isbuy && MA_S2 < MA_L2 && MA_S1 >= MA_L1)
|
|
{
|
|
return(1);
|
|
} // 買い
|
|
|
|
if (!isbuy && MA_S2 > MA_L2 && MA_S1 <= MA_L1)
|
|
{
|
|
return(2);
|
|
} // 売り
|
|
|
|
else
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
// 決済ルール1ココマデ
|
|
return(3);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 決済ルール2 |
|
|
//+------------------------------------------------------------------+
|
|
int Exit_Rule2(bool isbuy, double profit)
|
|
{
|
|
// 決済ルール2
|
|
if (isbuy) // 売りを決済
|
|
{
|
|
double ADX_sell2 = iADX(NULL, 0, ADX_PERIOD_sell2, PRICE_CLOSE, MODE_MAIN, 1);
|
|
if (profit < 0 && ADX_sell2 < ADX_Value_sell2) return(1);
|
|
|
|
}
|
|
|
|
// 決済ルール2ココマデ
|
|
return(3);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| チャート自動セット |
|
|
//+------------------------------------------------------------------+
|
|
// チャートセット初期化
|
|
void ChartSet()
|
|
{
|
|
// 気配値強制表示&自動切替
|
|
int chartWidth = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS); // チャート幅の計算
|
|
int textWidth = (int)NormalizeDouble(200 * DPIAdjust, 0); // 固定値pxまたはテキストの幅の計算
|
|
double ShiftPer = textWidth * 100 / chartWidth;
|
|
|
|
if (!IsTesting())
|
|
{
|
|
if (StringSubstr(Symbol(), 0, 6) != SYMBOL1 || Period() != Chart_TimeFrame)
|
|
{
|
|
SymbolSelect(SYMBOL1 + StringSubstr(Symbol(), 6, StringLen(Symbol())), true);
|
|
ChartSetSymbolPeriod(0, SYMBOL1 + StringSubstr(Symbol(), 6, StringLen(Symbol())), Chart_TimeFrame);
|
|
}
|
|
// 現在のシンボルが4文字の場合。無しならコメントアウト
|
|
/*if (StringSubstr(Symbol(), 0, 4) != SYMBOL2 || Period() != Chart_TimeFrame)
|
|
{
|
|
SymbolSelect(SYMBOL2 + StringSubstr(Symbol(), StringSubstr(Symbol(), 0, 4) == SYMBOL2? 4 : 6, StringLen(Symbol())), true);
|
|
ChartSetSymbolPeriod(0, SYMBOL2 + StringSubstr(Symbol(), StringSubstr(Symbol(), 0, 4) == SYMBOL2? 4 : 6, StringLen(Symbol())), Chart_TimeFrame);
|
|
}*/
|
|
ChartSetInteger(0, CHART_COLOR_BACKGROUND, clrBlack);
|
|
ChartSetInteger(0, CHART_COLOR_FOREGROUND, clrWhite);
|
|
ChartSetInteger(0, CHART_COLOR_GRID, clrLightSlateGray);
|
|
ChartSetInteger(0, CHART_COLOR_CHART_UP, clrOlive);
|
|
ChartSetInteger(0, CHART_COLOR_CHART_DOWN, clrOlive);
|
|
ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, clrBlack);
|
|
ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, clrBeige);
|
|
ChartSetInteger(0, CHART_COLOR_CHART_LINE, clrOlive);
|
|
ChartSetInteger(0, CHART_COLOR_VOLUME, clrOlive);
|
|
ChartSetInteger(0, CHART_COLOR_ASK, clrRed);
|
|
ChartSetInteger(0, CHART_COLOR_STOP_LEVEL, clrRed);
|
|
ChartSetInteger(0, CHART_SHIFT, true);
|
|
ChartSetDouble(0, CHART_SHIFT_SIZE, ShiftPer);
|
|
ChartSetInteger(0, CHART_AUTOSCROLL, true);
|
|
//ChartSetInteger(0, CHART_SHOW_DATE_SCALE, true); // これを入れるとなぜか表示範囲が狭くなる
|
|
//ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, true); // これを入れるとなぜか表示範囲が狭くなる
|
|
ChartSetInteger(0, CHART_FOREGROUND, false);
|
|
ChartSetInteger(0, CHART_SHOW_GRID, false);
|
|
ChartSetInteger(0, CHART_SHOW_ONE_CLICK, false);
|
|
ChartSetInteger(0, CHART_SHOW_OHLC, false);
|
|
ChartSetInteger(0, CHART_SHOW_PERIOD_SEP, true);
|
|
ChartSetInteger(0, CHART_SHOW_ASK_LINE, true);
|
|
ChartSetInteger(0, CHART_SCALE, 3);
|
|
ChartSetInteger(0, CHART_MODE, CHART_CANDLES);
|
|
}
|
|
}
|
|
// 状態によるチャート配色変更
|
|
void ChartSet2()
|
|
{
|
|
color ChartWar1 = ChartWarning? clrDarkGray : clrWhite;
|
|
color ChartWar2 = ChartWarning? clrDimGray : clrOlive;
|
|
color ChartWar3 = ChartWarning? clrSilver : clrBeige;
|
|
|
|
if (!IsTesting())
|
|
{
|
|
ChartSetInteger(0, CHART_COLOR_BACKGROUND, clrBlack);
|
|
ChartSetInteger(0, CHART_COLOR_FOREGROUND, ChartWar1);
|
|
ChartSetInteger(0, CHART_COLOR_GRID, clrLightSlateGray);
|
|
ChartSetInteger(0, CHART_COLOR_CHART_UP, ChartWar2);
|
|
ChartSetInteger(0, CHART_COLOR_CHART_DOWN, ChartWar2);
|
|
ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, clrBlack);
|
|
ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, ChartWar3);
|
|
ChartSetInteger(0, CHART_COLOR_CHART_LINE, ChartWar2);
|
|
ChartSetInteger(0, CHART_COLOR_VOLUME, ChartWar2);
|
|
ChartSetInteger(0, CHART_COLOR_ASK, clrRed);
|
|
ChartSetInteger(0, CHART_COLOR_STOP_LEVEL, clrRed);
|
|
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|
|
//| チャートの中央にシンボルを描画する |
|
|
//+------------------------------------------------------------------+
|
|
void CenterSymbol()
|
|
{
|
|
string TEXT1 = StringSubstr(Symbol(), 0, 6);
|
|
string TEXT2 = (Period() == 1? "M1": Period() == PERIOD_M5? "M5": Period() == PERIOD_M15? "M15": Period() == PERIOD_M30? "M30":
|
|
Period() == PERIOD_H1? "H1": Period() == PERIOD_H4? "H4": Period() == PERIOD_D1? "D1": Period() == PERIOD_W1? "W1": "MN1")
|
|
+ "/" + DoubleToStr(MarketInfo(Symbol(),MODE_SPREAD) / 10, 1);
|
|
int FontSize = 36;
|
|
|
|
int chartWidth = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS);
|
|
int chartHeight = (int)ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS);
|
|
int textWidth = StringLen(TEXT1) * FontSize / 2; // テキストの幅の計算
|
|
int textHeight = FontSize; // テキストの高さ
|
|
|
|
// テキストの中心からの座標を計算
|
|
int x = (chartWidth - textWidth) / 2 + textWidth / 2;
|
|
int y = (chartHeight - textHeight) / 2 + textHeight / 2;
|
|
|
|
DrawTextInCenter("Symbol1", TEXT1, x, y - FontSize, FontSize, C'60, 60, 60');
|
|
DrawTextInCenter("Symbol2", TEXT2, x, y + FontSize, FontSize, C'60, 60, 60');
|
|
}
|
|
void DrawTextInCenter(string Symbolname, string label_text, int pos_x, int pos_y, int s, color clr= clrBlack)
|
|
{
|
|
ObjectCreate(Symbolname, OBJ_LABEL, 0, 0, 0);
|
|
ObjectSetString(0, Symbolname, OBJPROP_TEXT, label_text);
|
|
ObjectSetInteger(0, Symbolname, OBJPROP_FONTSIZE, s);
|
|
ObjectSetString(0, Symbolname, OBJPROP_FONT, "Segoe UI");
|
|
ObjectSetInteger(0, Symbolname, OBJPROP_XDISTANCE, pos_x);
|
|
ObjectSetInteger(0, Symbolname, OBJPROP_YDISTANCE, pos_y);
|
|
ObjectSetInteger(0, Symbolname, OBJPROP_COLOR, clr);
|
|
ObjectSetInteger(0, Symbolname, OBJPROP_BACK, true);
|
|
ObjectSetInteger(0, Symbolname, OBJPROP_SELECTABLE, false);
|
|
ObjectSetInteger(0, Symbolname, OBJPROP_ANCHOR, ANCHOR_CENTER);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|
|
//| チャートコメント表示 |
|
|
//+------------------------------------------------------------------+
|
|
void ChartComment()
|
|
{
|
|
if (!IsTradeAllowed() || !IsConnected())
|
|
{
|
|
ChartWarning = true;
|
|
ChartSet2();
|
|
}
|
|
else
|
|
{
|
|
ChartWarning = false;
|
|
ChartSet2();
|
|
}
|
|
|
|
color clrChartWar = ChartWarning? clrNONE : clrWhite;
|
|
|
|
string LotsComment;
|
|
if (MM_ON == Fixed) LotsComment = DoubleToStr(Lots,2);
|
|
else LotsComment = DoubleToStr(CalculateLots(MM_Risk, StopLoss_pips),2) +
|
|
" (" + DoubleToStr(MM_Risk,1) +"%)";
|
|
|
|
string Comment0 = (string)MagicNumber + " [Magic]";
|
|
string Comment1 = LotsComment + " [Lots]";
|
|
string Comment2 = (MM_ON == 0 ? "Fixed" : MM_ON == 1 ? "FreeMargin" : "Balance") + " [MM]";
|
|
string Comment3 = DoubleToStr(MaxSpread_pips,1) + "/" + DoubleToStr(SpreadAve,1) + " [Spread Lim/Ave]";
|
|
string Comment4 = (string)Recording + " [Recording]";
|
|
string Comment5 = DoubleToStr(MarketInfo(Symbol(),MODE_SWAPLONG), 2) + "/" +
|
|
DoubleToStr(MarketInfo(Symbol(),MODE_SWAPSHORT), 2) + " [Swap B/S]";
|
|
string Comment6 = DoubleToStr(TakeProfit_pips_buy, 0) + "/" + DoubleToStr(StopLoss_pips_buy, 0) + " " +
|
|
DoubleToStr(TakeProfit_pips_sell, 0) + "/" + DoubleToStr(StopLoss_pips_sell, 0) + " [TP/SL]";
|
|
|
|
int xpix1 = 14, xpix2 = 20;
|
|
CommentLabel("Comment0", Comment0, 4, 4+xpix2*1, 10, clrYellow);
|
|
CommentLabel("Comment1", Comment1, 4, 8+xpix2*2, 10, clrYellow);
|
|
CommentLabel("Comment2", Comment2, 4, xpix1+xpix2*3, 8, clrChartWar);
|
|
CommentLabel("Comment3", Comment3, 4, xpix1+xpix2*4, 8, clrChartWar);
|
|
CommentLabel("Comment4", Comment4, 4, xpix1+xpix2*5, 8, clrChartWar);
|
|
CommentLabel("Comment5", Comment5, 4, xpix1+xpix2*6, 8, clrChartWar);
|
|
CommentLabel("Comment6", Comment6, 4, xpix1+xpix2*7, 8, clrChartWar);
|
|
|
|
//+------------------------------------------------------------------+
|
|
// 履歴表示用
|
|
color clrVisualHistory = !VisualHistory? clrNONE : ChartWarning? clrNONE : clrWhite;
|
|
color clrVisualHistoryPP = !VisualHistory? clrNONE : ChartWarning? clrNONE : totalpips < 0? clrOrangeRed : clrWhite;
|
|
color clrVisualHistoryPF = !VisualHistory? clrNONE : ChartWarning? clrNONE : 0 < ProfitFactor && ProfitFactor < 1? clrOrangeRed : clrWhite;
|
|
|
|
string Comment8 = "------------------------------";
|
|
string Comment9 = DoubleToStr(TradeCounts, 0) + " [TradeCounts]";
|
|
string Comment10 = DoubleToStr(totalpips, 1) + " [Profit (pips)]";
|
|
string Comment11 = (plus_profit == 0 || minus_profit == 0? "--- [Profit factor]" :
|
|
DoubleToStr(ProfitFactor, 2) + " [Profit factor]");
|
|
string Comment12 = (plus_profit == 0 || minus_profit == 0? "---/--- [RRR/Win%]" :
|
|
DoubleToStr(RRR, 2) + "/" + DoubleToStr(WinPer, 1) + " [RRR/Win%]");
|
|
|
|
CommentLabel("Comment8", Comment8, 4, xpix1+xpix2*8, 8, clrVisualHistory);
|
|
CommentLabel("Comment9", Comment9, 4, xpix1+xpix2*9, 8, clrVisualHistory);
|
|
CommentLabel("Comment10", Comment10, 4, xpix1+xpix2*10, 8, clrVisualHistoryPP);
|
|
CommentLabel("Comment11", Comment11, 4, xpix1+xpix2*11, 8, clrVisualHistoryPF);
|
|
CommentLabel("Comment12", Comment12, 4, xpix1+xpix2*12, 8, clrVisualHistory);
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
void CommentLabel(string ComName, string ComText, int ComPos_x, int ComPos_y, int ComSize, color ComClr= clrBlack)
|
|
{
|
|
ComPos_x = (int)NormalizeDouble(ComPos_x * DPIAdjust, 0); // 別途DPI換算コードで調整
|
|
ComPos_y = (int)NormalizeDouble(ComPos_y * DPIAdjust, 0); // 別途DPI換算コードで調整
|
|
|
|
ObjectCreate(ComName, OBJ_LABEL, 0, 0, 0);
|
|
ObjectSetString (0, ComName, OBJPROP_TEXT, ComText);
|
|
ObjectSetInteger(0, ComName, OBJPROP_XDISTANCE, ComPos_x);
|
|
ObjectSetInteger(0, ComName, OBJPROP_YDISTANCE, ComPos_y);
|
|
ObjectSetInteger(0, ComName, OBJPROP_FONTSIZE, ComSize);
|
|
ObjectSetInteger(0, ComName, OBJPROP_COLOR, ComClr);
|
|
ObjectSetString (0, ComName, OBJPROP_FONT, "Segoe UI");
|
|
ObjectSetInteger(0, ComName, OBJPROP_BACK, true);
|
|
ObjectSetInteger(0, ComName, OBJPROP_SELECTABLE, false);
|
|
ObjectSetInteger(0, ComName, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
|
|
ObjectSetInteger(0, ComName, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|
|
//| チャートにトレード履歴表示 |
|
|
//+------------------------------------------------------------------+
|
|
void TradeLinePips()
|
|
{
|
|
int sf = 0, tof = 0;
|
|
datetime hf = 0;
|
|
|
|
if (sf != Seconds() && OrdersTotal() > 0)
|
|
{
|
|
PosHis();
|
|
sf = Seconds();
|
|
}
|
|
|
|
if ((hf != iTime((string)0, PERIOD_H1, 0) && Seconds() > 30) || tof != OrdersHistoryTotal())
|
|
{
|
|
history();
|
|
hf = iTime((string)0, PERIOD_H1, 0);
|
|
tof = OrdersHistoryTotal();
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
void PosHis()
|
|
{
|
|
int res;
|
|
double pips = 0;
|
|
|
|
for (int i = OrdersTotal() - 1; i >= 0; i--)
|
|
{
|
|
res = OrderSelect(i, SELECT_BY_POS);
|
|
if (res == false) continue;
|
|
if (OrderSymbol() != Symbol() || OrderType() > 1 || OrderMagicNumber() != MagicNumber)
|
|
continue;
|
|
pips += trend((string)OrderTicket(), OrderOpenTime(), OrderOpenPrice(), Time[0], OrderType() == 0 ? Bid : Ask, OrderType());
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
void history()
|
|
{
|
|
int res;
|
|
totalpips = 0;
|
|
plus_profit = 0;
|
|
minus_profit = 0;//, ProfitFactor = 0;
|
|
minus_count = 0;
|
|
plus_count = 0;
|
|
TradeCounts = 0;
|
|
|
|
// トレード履歴を検索
|
|
for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
|
|
{
|
|
res = OrderSelect(i, SELECT_BY_POS, MODE_HISTORY);
|
|
if (res == false) continue;
|
|
if (OrderSymbol() != Symbol() || OrderType() > 1 || OrderMagicNumber() != MagicNumber)
|
|
continue;
|
|
|
|
// プロフィットファクター・RRR・勝率計算
|
|
if (OrderProfit() < 0)
|
|
{
|
|
minus_profit -= OrderProfit();
|
|
minus_count += 1;
|
|
}
|
|
else if (OrderProfit() >= 0)
|
|
{
|
|
plus_profit += OrderProfit();
|
|
plus_count += 1;
|
|
}
|
|
if (minus_profit != 0 && plus_count != 0 && minus_count != 0)
|
|
{
|
|
ProfitFactor = plus_profit / minus_profit;
|
|
RRR = (plus_profit / plus_count) / (minus_profit / minus_count);
|
|
WinPer = (plus_count * 100) / (plus_count + minus_count);
|
|
}
|
|
TradeCounts = minus_count + plus_count;
|
|
|
|
// 合計pips計算
|
|
totalpips += trend((string)TradeCounts, OrderOpenTime(), OrderOpenPrice(), OrderCloseTime(), OrderClosePrice(), OrderType());
|
|
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
double trend(string obj_name, datetime Time1, double Close1, datetime Time2, double Close2, int type)
|
|
{
|
|
double tes = 0.0; // 外付け手数料(PIPS換算)
|
|
double pips = (double)DoubleToStr((type == 0 ? Close2 - Close1 : Close1 - Close2) / xpoint - tes, 1);
|
|
int Shift2 = iBarShift(NULL, 0, Time2);
|
|
datetime Timex = iTime(NULL, 0, Shift2 + 1);
|
|
|
|
// トレード線
|
|
ObjectDelete("TradeLine" + obj_name);
|
|
ObjectCreate(0, "TradeLine" + obj_name, OBJ_TREND, 0, Time1, Close1, Time2, Close2);
|
|
ObjectSetInteger(0, "TradeLine" + obj_name, OBJPROP_COLOR, type == 0 ? clrDodgerBlue : clrOrangeRed);
|
|
ObjectSetInteger(0, "TradeLine" + obj_name, OBJPROP_STYLE, 0);
|
|
ObjectSetInteger(0, "TradeLine" + obj_name, OBJPROP_WIDTH, 2);
|
|
ObjectSetInteger(0, "TradeLine" + obj_name, OBJPROP_SELECTABLE, false); // オブジェクトの選択可否設定
|
|
ObjectSetInteger(0, "TradeLine" + obj_name, OBJPROP_RAY_RIGHT, false); // 右に線を延長
|
|
|
|
// pips表示
|
|
ObjectDelete("TradePips" + obj_name);
|
|
ObjectCreate(0, "TradePips" + obj_name, OBJ_TEXT, 0, Timex, Close2);
|
|
ObjectSetInteger(0, "TradePips" + obj_name, OBJPROP_COLOR, pips < 0 ? clrOrangeRed : !IsTesting()? clrLime : clrYellow);//type == 0 ? BuyColor : SellColor);
|
|
ObjectSetInteger(0, "TradePips" + obj_name, OBJPROP_SELECTABLE, false); // オブジェクトの選択可否設定
|
|
ObjectSetInteger(0, "TradePips" + obj_name, OBJPROP_FONTSIZE, 12); // フォントサイズ
|
|
ObjectSetInteger(0, "TradePips" + obj_name, OBJPROP_ANCHOR, ANCHOR_RIGHT); // 描画位置
|
|
ObjectSetString(0, "TradePips" + obj_name, OBJPROP_TEXT, DoubleToStr(pips, 1)); // 表示するテキスト
|
|
ObjectSetString(0, "TradePips" + obj_name, OBJPROP_FONT, "Segoe UI Semibold"); // フォント
|
|
|
|
return(pips);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|
|
//| スプレッド計測・オートスプレッド |
|
|
//+------------------------------------------------------------------+
|
|
void MeasureSP()
|
|
{
|
|
double SpreadMin = 1000, SpreadMax = 0, SpreadSum = 0;
|
|
int TickCount = 0, lastBars = 0;
|
|
|
|
TickCount++;
|
|
SpreadSum += MeasureSpread;
|
|
SpreadMin = SpreadMin == 0 ? SpreadMin = MeasureSpread : SpreadMin;
|
|
if (TickCount > 0 && SpreadSum > 0) SpreadAve = SpreadSum / TickCount;
|
|
if (SpreadMax < MeasureSpread) SpreadMax = MeasureSpread;
|
|
if (SpreadMin > MeasureSpread) SpreadMin = MeasureSpread;
|
|
|
|
// 月足のバー更新時に累積値リセット
|
|
if (lastBars != iBars(NULL, PERIOD_MN1))
|
|
{
|
|
lastBars = iBars(NULL, PERIOD_MN1);
|
|
SpreadSum = 0;
|
|
TickCount = 0;
|
|
}
|
|
|
|
// オートスプレッド計算
|
|
Adjustspread = SpreadAve + Adjustspread_Margin; // 平均にマージン加算
|
|
MaxSpread_pips = MathMin(Adjustspread, AllowMaxSpread); // 内部設定の最大値とマージン加算を比較し小さい方を採用
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|
|
//| 実行スプレッド・スリッページ・実行スプレッド計測・ファイル作成 |
|
|
//+------------------------------------------------------------------+
|
|
// ファイル初期化
|
|
int FileInit()
|
|
{
|
|
filename = AccountCompany() + "_" + (string)AccountNumber() + "_TradeLog.csv";// ファイル名を決める
|
|
|
|
fp = FileOpen(filename, FILE_READ|FILE_WRITE|FILE_CSV, ',');// ファイルオープン(csv)
|
|
if(fp==INVALID_HANDLE)
|
|
{
|
|
err = GetLastError();
|
|
printf("Error occured: [%d] %s", err, ErrorDescription(err));
|
|
return(0.0);
|
|
}
|
|
FileWrite(fp, "注文番号", "注文時間", "時刻", "分", "取引種別", "注文価格", "約定価格",
|
|
"スプレッド(pips)", "スリッページ(pips)", "レイテンシー(ms)",
|
|
"損益(pips)", "数量", "通貨ペア", "時間足", "EA名",
|
|
"マジックナンバー", "開発1", "開発2");
|
|
// ファイルを閉じる
|
|
FileClose(fp);
|
|
|
|
return(0);
|
|
}
|
|
|
|
// トレード情報
|
|
void OpenTradeInfo_false()
|
|
{
|
|
Order_Price = (Open_Type == "Buy"? Ask : Bid); //NormalizeDouble(Order_Price , Digits); // 買い注文価格を正規化
|
|
double Open_Yakujyou_Price = GetLastError(); //NormalizeDouble(OrderOpenPrice(), Digits); // 実際約定した価格、正規化
|
|
double Open_Spread = OSpread / 10; // スプレッド、桁合わせ
|
|
double Open_Slippage = (double)Volume[0]; //NormalizeDouble(MathAbs(Order_Price - Open_Yakujyou_Price), Digits) / xpoint; // スリッページ、桁合わせ
|
|
uint Open_Runtime = StartOrderTimestamp - StartingTimestamp; // ランタイム時間
|
|
FileWriteingOpen_false(Open_Yakujyou_Price, Open_Spread, Open_Slippage, Open_Runtime); // 書き込み処理
|
|
}
|
|
void OpenTradeInfo()
|
|
{
|
|
Order_Price = NormalizeDouble(Order_Price , Digits); // 買い注文価格を正規化
|
|
double Open_Yakujyou_Price = NormalizeDouble(OrderOpenPrice(), Digits); // 実際約定した価格、正規化
|
|
double Open_Spread = OSpread / 10; // スプレッド、桁合わせ
|
|
double Open_Slippage = (OrderType() == OP_SELL? Open_Yakujyou_Price - Order_Price : Order_Price - Open_Yakujyou_Price) / xpoint;
|
|
Open_Slippage = NormalizeDouble(Open_Slippage, Digits); // スリッページ、桁合わせ
|
|
Open_Type = OrderType() == OP_BUY? "Buy" : "Sell";
|
|
uint Open_Runtime = StartOrderTimestamp - StartingTimestamp; // ランタイム時間
|
|
FileWriteingOpen(Open_Yakujyou_Price, Open_Spread, Open_Slippage, Open_Runtime); // 書き込み処理
|
|
}
|
|
void CloseTradeInfo()
|
|
{
|
|
Close_Price = NormalizeDouble(Close_Price, Digits); // 売り注文価格を正規化
|
|
double Close_Yakujou_Price = NormalizeDouble(OrderClosePrice(), Digits); // 実際約定した価格
|
|
double Close_Spread = CSpread / 10; // スプレッド、桁合わせ
|
|
double Close_Slippage = (OrderType() == OP_BUY? Close_Yakujou_Price - Close_Price : Close_Price - Close_Yakujou_Price) / xpoint;
|
|
Close_Slippage = NormalizeDouble(Close_Slippage, Digits); // スリッページ、桁合わせ
|
|
double profitpips = NormalizeDouble(OrderType() == OP_BUY? (OrderClosePrice() - OrderOpenPrice()) / xpoint :
|
|
(OrderOpenPrice() - OrderClosePrice()) / xpoint, 1);
|
|
Close_Type = "Close";
|
|
uint Close_Runtime = OrderCloseTimestamp - StartingTimestamp; // ランタイム時間
|
|
FileWriteingClose(Close_Yakujou_Price, Close_Spread, Close_Slippage, profitpips, Close_Runtime); // 書き込み処理
|
|
}
|
|
|
|
// ファイル書き込み
|
|
void FileWriteingOpen_false(double OYP, double OSp, double OSl, uint OR)
|
|
{
|
|
for(int i = 0; i < 3000; i++)
|
|
{
|
|
FileClose(fp); // ファイルが開きっぱなしで開けないエラーを防ぐ
|
|
fp = FileOpen(filename, FILE_READ|FILE_WRITE|FILE_CSV, ',');// ファイルオープン(csv)、失敗戻り値は-1
|
|
|
|
if (fp != INVALID_HANDLE)
|
|
{
|
|
FileSeek(fp, 0, SEEK_END);
|
|
FileWrite(fp, "false", TimeCurrent(), TimeHour(TimeCurrent()), TimeMinute(TimeCurrent()),
|
|
Open_Type, Order_Price, "Err=" + (string)OYP, OSp, "tick=" + (string)OSl, OpenLatency,
|
|
"---", CalculateLots(MM_Risk, StopLoss_pips), Symbol(), Timeframe, WindowExpertName(),
|
|
OrderMagicNumber(), i, OR);
|
|
FileClose(fp);
|
|
break;
|
|
}
|
|
}
|
|
if (fp == -1) Print("Error=", GetLastError(), " ファイルの書き込みに失敗しました");
|
|
}
|
|
void FileWriteingOpen(double OYP, double OSp, double OSl, uint OR)
|
|
{
|
|
for(int i = 0; i < 3000; i++)
|
|
{
|
|
FileClose(fp); // ファイルが開きっぱなしで開けないエラーを防ぐ
|
|
fp = FileOpen(filename, FILE_READ|FILE_WRITE|FILE_CSV, ',');// ファイルオープン(csv)、失敗戻り値は-1
|
|
|
|
if (fp != INVALID_HANDLE)
|
|
{
|
|
FileSeek(fp, 0, SEEK_END);
|
|
FileWrite(fp, OrderTicket(), OrderOpenTime(), TimeHour(OrderOpenTime()), TimeMinute(OrderOpenTime()),
|
|
Open_Type, Order_Price, OYP, OSp, OSl, OpenLatency,
|
|
"---", CalculateLots(MM_Risk, StopLoss_pips), Symbol(), Timeframe, WindowExpertName(),
|
|
OrderMagicNumber(), i, OR);
|
|
FileClose(fp);
|
|
break;
|
|
}
|
|
}
|
|
if (fp == -1) Print("Error=", GetLastError(), " ファイルの書き込みに失敗しました");
|
|
}
|
|
void FileWriteingClose(double CYP, double CSp, double CSl, double pro, uint CR)
|
|
{
|
|
for(int i = 0; i < 3000; i++)
|
|
{
|
|
FileClose(fp); // ファイルが開きっぱなしで開けないエラーを防ぐ
|
|
fp = FileOpen(filename, FILE_READ|FILE_WRITE|FILE_CSV, ',');// ファイルオープン(csv)、失敗戻り値は-1
|
|
|
|
if (fp != INVALID_HANDLE)
|
|
{
|
|
FileSeek(fp, 0, SEEK_END);
|
|
FileWrite(fp, OrderTicket(), OrderCloseTime(), TimeHour(OrderCloseTime()), TimeMinute(OrderCloseTime()),
|
|
Close_Type, Close_Price, CYP, CSp, CSl, CloseLatency,
|
|
pro, CalculateLots(MM_Risk, StopLoss_pips), Symbol(), Timeframe, WindowExpertName(),
|
|
OrderMagicNumber(), i, CR);
|
|
FileClose(fp);
|
|
break;
|
|
}
|
|
}
|
|
if (fp == -1) Print("Error=", GetLastError(), " ファイルの書き込みに失敗しました");
|
|
}
|
|
|
|
// TP/SL時の検出
|
|
void ClosedTradeTPSL()
|
|
{
|
|
for(int i=OrdersHistoryTotal()-1; i>=0; i--)
|
|
{
|
|
//オーダー選択(エラーを生じた場合、ループから抜け出す)
|
|
if (OrderSelect( i, SELECT_BY_POS, MODE_HISTORY ) == false)
|
|
{
|
|
//Print("OrderSelect returned the error of ", GetLastError() );
|
|
break;
|
|
}
|
|
//オーダー確認(通貨ペアが一致しない場合は、for文の先頭に戻る)
|
|
if (OrderSymbol() != Symbol()) continue;
|
|
|
|
//マジックナンバー確認(マジックナンバーが一致しない場合は、for文の先頭に戻る)
|
|
if (OrderMagicNumber() != MagicNumber) continue;
|
|
|
|
// 決済時間に更新がなければループ処理終了
|
|
if((OrderType() == OP_BUY || OrderType() == OP_SELL) && OrderCloseTime() == OrderCloseTime_bak) break;
|
|
|
|
if((OrderType() == OP_BUY || OrderType() == OP_SELL) && OrderCloseTime() > OrderCloseTime_bak && !WritingTPSL) // 決済時間が最新であれば
|
|
{
|
|
|
|
OrderCloseTime_bak = OrderCloseTime();
|
|
|
|
int length = StringLen(OrderComment());//StringLenは文字数を返す
|
|
if (length >= 4)
|
|
{
|
|
// TP/SL決済の確認
|
|
string tpsl = StringSubstr(OrderComment(), length-4, 4);
|
|
if (tpsl == "[tp]" || tpsl == "[sl]")
|
|
{
|
|
Close_Price = NormalizeDouble((tpsl == "[tp]"? OrderTakeProfit() : OrderStopLoss()), Digits); // 売り注文価格を正規化
|
|
double Close_Yakujou_Price = NormalizeDouble(OrderClosePrice(), Digits); // 実際約定した価格
|
|
double Close_Spread = MarketInfo(NULL,MODE_SPREAD) / 10; // スプレッド、桁合わせ
|
|
double Close_Slippage = (OrderType() == OP_BUY? Close_Yakujou_Price - Close_Price : Close_Price - Close_Yakujou_Price) / xpoint;
|
|
Close_Slippage = NormalizeDouble(Close_Slippage, Digits); // スリッページ、桁合わせ
|
|
CloseLatency = 0;
|
|
double profitpips = NormalizeDouble((OrderType() == OP_BUY? OrderClosePrice() - OrderOpenPrice() : OrderOpenPrice() - OrderClosePrice()) / xpoint, 1);
|
|
Close_Type = tpsl == "[tp]"? "TP" : "SL";
|
|
uint Close_Runtime = 0; // ランタイム時間
|
|
FileWriteingClose(Close_Yakujou_Price, Close_Spread, Close_Slippage, profitpips, Close_Runtime); // 書き込み処理
|
|
WritingTPSL = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+ |