MQL5Book/Experts/p6/CrazyCarryTrade.mq5

127 lines
4.1 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 16:09:41 +02:00
//+------------------------------------------------------------------+
//| CrazyCarryTrade.mq5 |
//| Copyright 2022, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2022, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property description "Keep open positions in predefined direction, collect swaps and withdraw them."
#include "..\..\Include\PRTF.mqh"
#include "..\..\Include\PositionFilter.mqh"
#include "..\..\Include\MqlTradeSync.mqh"
enum ENUM_ORDER_TYPE_MARKET
{
MARKET_BUY = ORDER_TYPE_BUY,
MARKET_SELL = ORDER_TYPE_SELL
};
input ENUM_ORDER_TYPE_MARKET Type;
input double Volume;
input double MinProfitPerLot = 1000;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(!MQLInfoInteger(MQL_TESTER))
{
Alert("This is a test EA! Run it in the tester only!");
return INIT_FAILED;
}
const double rate = SymbolInfoDouble(_Symbol,
Type == MARKET_BUY ? SYMBOL_SWAP_LONG : SYMBOL_SWAP_SHORT);
if(rate < 0)
{
Alert("Unprofitable symbol and direction specified!");
return INIT_FAILED;
}
PRTF(TesterWithdrawal(AccountInfoDouble(ACCOUNT_BALANCE) * 2));
/*
example:
not enough money for 20 000.00 withdrawal (free margin: 10 000.00)
TesterWithdrawal(AccountInfoDouble(ACCOUNT_BALANCE)*2)=false / MQL_ERROR::10019(10019)
*/
PRTF(TesterWithdrawal(100));
/*
example:
deal #2 balance -100.00 [withdrawal] done
TesterWithdrawal(100)=true / ok
*/
PRTF(TesterDeposit(100)); // restore
/*
example:
deal #3 balance 100.00 [deposit] done
TesterDeposit(100)=true / ok
*/
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Tick event handler |
//+------------------------------------------------------------------+
void OnTick()
{
const double volume = Volume == 0 ? SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN) : Volume;
ENUM_POSITION_PROPERTY_DOUBLE props[] = {POSITION_PROFIT, POSITION_SWAP};
double values[][2];
ulong tickets[];
PositionFilter pf;
pf.select(props, tickets, values, true);
if(ArraySize(tickets) > 0)
{
double loss = 0, swaps = 0;
for(int i = 0; i < ArraySize(tickets); ++i)
{
if(values[i][0] + values[i][1] * values[i][1] >= MinProfitPerLot * volume)
{
MqlTradeRequestSync request0;
if(request0.close(tickets[i]) && request0.completed())
{
swaps += values[i][1]; // sum up swaps of positions being closed
}
}
else
{
loss += values[i][0];
}
}
if(loss / ArraySize(tickets) <= -MinProfitPerLot * volume * sqrt(ArraySize(tickets)))
{
MqlTradeRequestSync request1;
(Type == MARKET_BUY ? request1.buy(volume) : request1.sell(volume));
}
if(swaps >= 0)
{
TesterWithdrawal(swaps); // withdraw collected swaps
}
}
else
{
MqlTradeRequestSync request1;
(Type == MARKET_BUY ? request1.buy(volume) : request1.sell(volume));
}
}
//+------------------------------------------------------------------+
//| Finalization handler |
//+------------------------------------------------------------------+
void OnDeinit(const int)
{
PrintFormat("Deposit: %.2f Withdrawals: %.2f",
TesterStatistics(STAT_INITIAL_DEPOSIT),
TesterStatistics(STAT_WITHDRAWAL));
/*
example:
final balance 10091.19 USD
Deposit: 10000.00 Withdrawals: 197.42
*/
}
//+------------------------------------------------------------------+