トラリピEAを改造していろいろやってます。プログラムは素人にて容赦ねがいます。
//+------------------------------------------------------------------+
//| MTR20250105.mq4 |
//| Copyright 2025, bakueki-fx.com |
//| https://bakueki-fx.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, bakueki-fx.com"
#property link "https://bakueki-fx.com"
#property version "1.00"
#property strict
//--- input parameters
// バックテスト時は、timerInterval = 0 にしないと動かない。
// トレンドフォロー時、stopOrderSpreadPips は、 doOrderRangePips 未満にしないとエントリーしない。
// backTestMode = false では、処理が重くバックテストに時間がかかる。
input string eaName = "MTR20250105";
input int timerInterval = 10;
input int magicNumber = 1110000;
input double lots = 0.01;
input bool isBuyTrap=true;
input double maxOpenPrice = 160;
input int trapCount = 600;
input int trapIntervalPips = 10;
input int doOrderRangePips = 50;
input bool isTrendFollowOnly = false;
input int stopOrderSpreadPips = 10;
input int minProfitPips = 10;
input int trailingProfitPips = 5;
input int maxTakePosition=1000;
input int printInfomationLevel=0;
//input bool doPrintInformation = true;
input double lossCutBorderLine = 100;
input int intervalTrapOrder = 10;
input int intervalTrailingStop = 20;
input bool backTestMode = false;
//--- Global parameters
int waitTime = 5; // 待機時間
int slippage = 3; // スリッページ
color arrowColor[6] = { Green, Red, Green, Red, Green, Red }; // 矢印の色
int ticketArray[]; // チケット配列
int magicArray[]; // マジックナンバー配列
datetime lastExecutionTrapOrder = 0;
datetime lastExecutionTrailingStop = 0;
double pointPerPips; // 1pipsあたりのポイント
int slippagePips;
int digitMultiplier;
double buySum = 0; // Buyポジションの加重取得価格合計
double sellSum = 0; // Sellポジションの加重取得価格合計
double buyLotSum = 0; // Buyポジションのロット数合計
double sellLotSum = 0; // Sellポジションのロット数合計
double buyAverage = 0; // Buyポジションの平均取得価格
double sellAverage = 0; // Sellポジションの平均取得価格
double buyLossCutLine =0 ;
double sellLossCutLine =0 ;
int buyPositionCount = 0;
int sellPositionCount =0;
double buyLotProfit = 0; // Buyポジションの利益合計
double sellLotProfit = 0; // Sellポジションの利益合計
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
int mult = 1;
if(Digits == 3 || Digits == 5) {
mult = 10;
}
pointPerPips = Point * mult;
slippagePips = slippage * mult;
digitMultiplier = MathPow(10,Digits);
Print(" Digits= ",Digits," Point= ",Point," pointPerPips= ",pointPerPips," slippagePips= ",slippagePips," digitMultiplier= ",digitMultiplier," mult= ",mult );
//--- create timer
if (timerInterval > 0)
{
EventSetTimer(timerInterval); // 外部入力のタイマー間隔を設定
Print("Timer enabled with interval: ", timerInterval, " seconds.");
}
else
{
Print("Timer disabled. Using OnTick() instead.");
}
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- destroy timer
EventKillTimer();
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
if (timerInterval <= 0)
{
main(); // TimerIntervalが0以下の場合、OnTick()で動作
}
}
//+------------------------------------------------------------------+
//| Timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
//---
if (timerInterval > 0)
{
main(); // TimerIntervalが有効の場合、OnTimerで動作
}
}
//+------------------------------------------------------------------+
//| main関数 |
//+------------------------------------------------------------------+
void main()
{
//---
if (!backTestMode==true){
if(initOrderTicketInfo()==false)return;
doGetInfomation();
}
datetime nowO = TimeCurrent();
datetime nowT = TimeCurrent()+10;
if(nowO - lastExecutionTrapOrder >= intervalTrapOrder){
if(initOrderTicketInfo()==false)return;
if (printInfomationLevel>=2){
Print("トラップ発注を実行 時間= ",nowO);
}
// doGetInfomation();
doTrapRepeatIfDone();
lastExecutionTrapOrder =nowO;
}
if(nowT - lastExecutionTrailingStop >= intervalTrailingStop){
if(initOrderTicketInfo()==false)return;
if (printInfomationLevel>=2){
Print("トレーリングストップを実行 時間= ",nowT);
}
doTrailing();
lastExecutionTrailingStop =nowT;
}
}
//+------------------------------------------------------------------+
bool initOrderTicketInfo(){
// 対象通貨ペアの件数を取得
int orderCount=0;
for(int j=0; j < OrdersTotal(); j++) {
if(OrderSelect(j,SELECT_BY_POS,MODE_TRADES) == false) return(false);
if(OrderSymbol() == Symbol()) {
orderCount++;
}
}
// 配列を初期化
ArrayResize(ticketArray,orderCount);
ArrayResize(magicArray,orderCount);
ArrayInitialize(ticketArray, -1); // 初期化
ArrayInitialize(magicArray, -1); // 初期化
orderCount=0;
// 配列にセット
for(int j=0; j < OrdersTotal(); j++) {
if(OrderSelect(j,SELECT_BY_POS,MODE_TRADES) == false) return(false);
if(OrderSymbol() == Symbol()) {
ticketArray[orderCount] = OrderTicket();
magicArray[orderCount] = OrderMagicNumber();
orderCount++;
}
}
return(true);
}
//+------------------------------------------------------------------+
// 指定されたMAGIC注文があるかどうかをチェックする。なければ「-1」を返す
//
int getOrderTicket(int magic){
int orderCount = 0;
int ticket = -1;
for(int i=0; i < ArraySize(magicArray); i++) {
if(magic == magicArray[i]) {
ticket = ticketArray[i];
orderCount++;
}
}
if(orderCount > 1){
}
return(ticket);
}
//+------------------------------------------------------------------+
//
int doTrapRepeatIfDone() {
for(int i=0; i < trapCount; i++){
double openPrice = maxOpenPrice - trapIntervalPips * i * pointPerPips;
// 現値より大きく乖離した発注は出さない
double currentPrice;
if(isBuyTrap){
currentPrice = Ask;
} else {
currentPrice = Bid;
}
if( doOrderRangePips != 0 &&
(openPrice < currentPrice - doOrderRangePips * pointPerPips || openPrice > currentPrice + doOrderRangePips * pointPerPips) ){
continue;
}
int magic = magicNumber+i;
// 注文状態をチェックし、注文がなければリピートする
int ticket = getOrderTicket(magic);
if ( ticket <= 0) {
ticket = doRepeatIfDone(openPrice, magic);
}
}
return(0);
}
// 指定された条件でリピートIfDone注文を実行する
int doRepeatIfDone(double openPrice,int magic) {
// 注文形式を決定する
int tradeType = -1;
if( isTrendFollowOnly == true ) {
// トレンドフォローモードの場合、トレンドフォローを確認するため、
// ASK値が一旦、閾値以上の下値に達した後に建値まで戻ってきた場合にのみ
// リピートするようにする
// stopOrderSpreadPipsの値は、doOrderRangePipsより小さい値でないと発注しない!
if(isBuyTrap && openPrice >= Ask + stopOrderSpreadPips * pointPerPips ) {
tradeType = OP_BUYSTOP;
} else if(!isBuyTrap && openPrice < Bid - stopOrderSpreadPips * pointPerPips ) {
tradeType = OP_SELLSTOP;
}
} else {
if(isBuyTrap && openPrice <= Ask) {
// 買い注文で、建値 <= 現在価格(Ask) の場合は買い指値
tradeType = OP_BUYLIMIT;
} else if(isBuyTrap && openPrice > Ask) {
// 買い注文で、建値 > 現在価格(Ask) の場合は買い逆指値
tradeType = OP_BUYSTOP;
} else if(!isBuyTrap && openPrice >= Bid) {
// 売り注文で、建値 >= 現在価格(Bid) の場合は売り指値
tradeType = OP_SELLLIMIT;
} else if(!isBuyTrap && openPrice < Bid) {
// 売り注文で、建値 < 現在価格(Bid) の場合は売り逆指値
tradeType = OP_SELLSTOP;
}
}
// 注文形式が注文不要の場合はそのまま終了する
if(tradeType == -1) {
return(-1);
}
int ticket = doOrderSend(tradeType,openPrice,magic);
return(ticket);
}
//+------------------------------------------------------------------+
//
// 発注する
int doOrderSend(int type, double openPrice, int magic) {
// 0時23時は動作しない。
if(Hour()==23||Hour()==0||DayOfWeek()==6||DayOfWeek()==0){
return(-1);
}
doGetInfomation();
if (!backTestMode==true){
if( buyPositionCount >= maxTakePosition|| sellPositionCount >= maxTakePosition){
if (printInfomationLevel>=1){
Print("これ以上の発注はできません。 "," BuyPosition= ",buyPositionCount," SellPosition= ",sellPositionCount);
}
return(-1);
}
if(isBuyTrap==true){
if( buyLossCutLine >= lossCutBorderLine){
if (printInfomationLevel>=1||printInfomationLevel==-1){
Print("これ以上の発注はできません。 "," buyLossCutLine= ",buyLossCutLine," lossCutBorderLine= ",lossCutBorderLine," 余剰証拠金= ",AccountFreeMargin()," 買いLot数= ",buyLotSum," 買い平均価格= ",buyAverage);
}
return(-1);
}
}
else{
if( sellLossCutLine <= lossCutBorderLine){
if (printInfomationLevel>=1||printInfomationLevel==-1){
Print("これ以上の発注はできません。 "," sellLossCutLine= ",sellLossCutLine," lossCutBorderLine= ",lossCutBorderLine," 余剰証拠金= ",AccountFreeMargin()," 売りLot数= ",sellLotSum," 売り平均価格= ",sellAverage);
}
return(-1);
}
}
}
openPrice = NormalizeDouble(openPrice, Digits);
while(true) {
if(IsTradeAllowed() == true) {
RefreshRates();
int ticket = OrderSend(Symbol(), type, lots, openPrice, slippage, 0, 0, magic, magic, 0, arrowColor[type]);
if( ticket > 0) {
if (printInfomationLevel>=1){
Print("発注しました magic= ",magic ," ticket= ",ticket," openPrice= ",openPrice);
}
Sleep(waitTime*1000);
return(ticket);
}
if (printInfomationLevel>=1){
Print("発注エラー magic= ",magic ," ticket= ",ticket," エラーコード: ", GetLastError());
}
Sleep(waitTime*2000);
break;
}
}
return(-1);
}
//+------------------------------------------------------------------+
//
int doTrailing() {
for(int i=0; i < trapCount; i++){
int magic = magicNumber+i;
// 注文状態をチェックし、注文があれば 実行する。
int ticket = getOrderTicket(magic);
if (ticket > 0) {
doTrailingOrderModify(ticket);
}
}
return(0);
}
//+------------------------------------------------------------------+
//
int doTrailingOrderModify(int ticket){
// 0時23時は動作しない。
if(Hour()==23||Hour()==0||DayOfWeek()==6||DayOfWeek()==0){
return(-1);
}
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES) ==true)
{
if(OrderType() > 1) {
return(-1);
}
RefreshRates();
double orderDifference = (OrderType() == OP_BUY) ? (Bid - OrderOpenPrice()) : (OrderOpenPrice()-Ask);
orderDifference =orderDifference /pointPerPips;
if(orderDifference < minProfitPips )return(-1);
if (printInfomationLevel>=1){
Print("★ トレール利益を超えた Bid= ",Bid," OrderOpenPrice()= ",OrderOpenPrice()," doTrailingOrderModify ticket= ",ticket," orderDifferenc Point= ",orderDifference);
}
// 現在の逆指値価格を計算
double newStopLoss = (OrderType() == OP_BUY) ? Bid - trailingProfitPips * pointPerPips : Ask + trailingProfitPips * pointPerPips;
// 既存の逆指値を更新
if ((OrderType() == OP_BUY && (OrderStopLoss() < newStopLoss || OrderStopLoss() == 0)) ||
(OrderType() == OP_SELL && (OrderStopLoss() > newStopLoss || OrderStopLoss() == 0)))
{
if (!OrderModify(ticket, 0, NormalizeDouble(newStopLoss, Digits), 0, 0, clrYellow))
// if (!OrderModify(ticket, 0, newStopLoss, 0, 0, clrYellow))
{
if (printInfomationLevel>=1){
Print("OrderModify failed: ", GetLastError(), " OrderTicket: ", OrderTicket(),"OrderMagicNumber= ", OrderMagicNumber());
}
}
else
{
if (printInfomationLevel>=1){
Print("OrderModify succeeded for ticket: ", OrderTicket(), " New StopLoss: ", DoubleToString(newStopLoss, Digits));
}
}
}
}
return(ticket);
}
//+------------------------------------------------------------------+
//
int doGetInfomation(){
buySum = 0; // Buyポジションの加重取得価格合計
sellSum = 0; // Sellポジションの加重取得価格合計
buyLotSum = 0; // Buyポジションのロット数合計
sellLotSum = 0; // Sellポジションのロット数合計
buyAverage = 0; // Buyポジションの平均取得価格
sellAverage = 0; // Sellポジションの平均取得価格
buyLossCutLine =0 ;
sellLossCutLine =0 ;
buyPositionCount = 0;
sellPositionCount =0;
buyLotProfit = 0; // Buyポジションの利益合計
sellLotProfit = 0; // Sellポジションの利益合計
// ポジションのサーチ
for (int i = 0; i < OrdersTotal(); i++)
{
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) // すべての注文をチェック
{
// if (OrderSymbol() == symbol) // 現在の通貨ペアが一致する場合
for(int j=0; j < trapCount; j++){
int magic = magicNumber+j;
// 注文状態をチェック
int ticket = getOrderTicket(magic);
if (ticket == OrderTicket() )
{
double lotSize = OrderLots(); // ポジションのロット数を取得
double openPrice = OrderOpenPrice(); // ポジションの取得価格を取得
if (OrderType() == OP_BUY) // Buyポジションの場合
{
buySum += openPrice * lotSize; // ロット数で加重した取得価格を合計
buyLotSum += lotSize; // Buyポジションのロット数を合計
buyPositionCount++;
buyLotProfit += OrderProfit();
}
else if (OrderType() == OP_SELL) // Sellポジションの場合
{
sellSum += openPrice * lotSize; // ロット数で加重した取得価格を合計
sellLotSum += lotSize; // Sellポジションのロット数を合計
sellPositionCount++;
sellLotProfit += OrderProfit();
}
}
}
}
}
// Buyポジションの平均取得価格を計算
buyAverage = buyLotSum > 0 ? buySum / buyLotSum : 0;
// Sellポジションの平均取得価格を計算
sellAverage = sellLotSum > 0 ? sellSum / sellLotSum : 0;
buyLossCutLine = buyLotSum > 0
? Bid - (AccountFreeMargin() / (buyLotSum * 100))/digitMultiplier
: 0;
sellLossCutLine = sellLotSum > 0
? Bid + (AccountFreeMargin() / (sellLotSum * 100))/digitMultiplier
: 0;
buyAverage = NormalizeDouble(buyAverage,Digits);
sellAverage = NormalizeDouble(sellAverage,Digits);
buyLotSum=NormalizeDouble(buyLotSum,Digits);
sellLotSum=NormalizeDouble(sellLotSum,Digits);
buyLossCutLine= NormalizeDouble(buyLossCutLine,Digits);
sellLossCutLine=NormalizeDouble(sellLossCutLine,Digits);
buyLotProfit= NormalizeDouble(buyLotProfit,Digits);
sellLotProfit=NormalizeDouble(sellLotProfit,Digits);
if (printInfomationLevel>=2){
Print("Buy Average: ", buyAverage, ", Buy Lot Sum: ", buyLotSum);
Print("Sell Average: ", sellAverage, ", Sell Lot Sum: ", sellLotSum);
Print("buyPositionCount : ", buyPositionCount, ", sellPositionCount: ", sellPositionCount);
Print("Buy Loss Cut Line: ", buyLossCutLine, ", Sell Loss Cut Line: ", sellLossCutLine);
}
return(0);
}