//+------------------------------------------------------------------+
//| Мегалот.mq4 |
//| 2015, Tatiana Zyrianova |
//| https://www.mql5.com/en/users/mqldiligent |
//+------------------------------------------------------------------+
#property copyright "2015, Tatiana Zyrianova"
#property link "https://www.mql5.com/en/users/mqldiligent"
#property version "1.00"
#property strict
#include <stdlib.mqh>
extern bool OneAccount = true; // Если работаете на одном счету, то true, если на двух - false
extern double StepLot = 0.01; // Шаг доливок при профите в виде лота
extern bool OpenBuy = false; // Открыть Бай
extern bool OpenSell = false; // Открыть Селл
extern double Risk = 50; // Риск в процентах от депозита
extern double PercentClose = 500; // Процент закрытия всех ордеров
extern int Slippage = 5; // Проскальзывание
extern int Magic = 49266773; // Магик
int modeSetOrders = 1; // Способ установки ордеров:
// 0 - по заданной цене
// 1 - скорректировать цены
// 2 - вход по текущим ценам
//+------------------------------------------------------------------+
int ticket1, ticket2, ticket3, ticket4;
double SL, TP, buylot, selllot;
bool mdf, cls;
static datetime PrevTime;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if (Digits == 3 || Digits == 5)
Slippage *= 10;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
if (StepLot < 0.01)
{
if (PrevTime != Time[0]) Alert("Параметр StepLot должен быть выше или равным 0.01!");
PrevTime = Time[0];
return;
}
buylot = NormalizeDouble(GetMarginLotForOpening(Risk, OP_BUY), 2);
selllot = NormalizeDouble(GetMarginLotForOpening(Risk, OP_SELL), 2);
double max_lot_for_1_order;
if (OneAccount) max_lot_for_1_order = NormalizeDouble((AccountFreeMargin()/MarketInfo(Symbol(),MODE_MARGINREQUIRED)-0.01)/2, 2);
else max_lot_for_1_order = NormalizeDouble(AccountFreeMargin()/MarketInfo(Symbol(),MODE_MARGINREQUIRED)-0.01, 2);
if (CountTrades() == 0)
{
if (OpenBuy == true && OpenSell == false)
{
buylot = NormalizeDouble(GetMarginLotForOpening(Risk, OP_BUY), 2);
if (buylot < max_lot_for_1_order) ticket1 = SetOrder(Symbol(), OP_BUY, buylot, Ask, Slippage, 0, 0, Magic);
else
{
if (PrevTime != Time[0]) Alert("Слишком большой риск для открытия позиции!");
PrevTime = Time[0];
return;
}
}
if (OpenBuy == false && OpenSell == true)
{
selllot = NormalizeDouble(GetMarginLotForOpening(Risk, OP_SELL), 2);
if (selllot < max_lot_for_1_order) ticket2 = SetOrder(Symbol(), OP_SELL, selllot, Bid, Slippage, 0, 0, Magic);
else
{
if (PrevTime != Time[0]) Alert("Слишком большой риск для открытия позиции!");
PrevTime = Time[0];
return;
}
}
if (OpenBuy == true && OpenSell == true)
{
if (PrevTime != Time[0]) Alert("Две сделки сразу открывать нельзя. Выберете или OpenBuy = true, или OpenSell = true");
PrevTime = Time[0];
return;
}
}
else if (CountTrades() > 0)
{
Print("Количество сделок бай = " + IntegerToString(CountTrades(OP_BUY)));
if (CountTrades(OP_BUY) > 0 && CountTrades(OP_SELL) == 0)
{
Print("Профит позиций на текущем символе = " + DoubleToStr(GetProfitOpenPosInCurrency(Symbol(), -1, Magic), 2));
if (GetProfitOpenPosInCurrency(Symbol(), -1, Magic) > 0)
{
buylot = NormalizeDouble(GetMarginLotForOpening(Risk, OP_BUY), 2);
Print("Бай лот с риском " + DoubleToString(Risk, 2) + "% от депозита = " + DoubleToStr(buylot, 2));
Print("Риск для доливки = " + DoubleToStr(GetMarginLotForTopUp(buylot, OP_BUY) + GetMarginLotForTopUpBalance(StepLot*CountTradesLot(StepLot), OP_BUY), 2) + ", Риск = " + DoubleToStr(Risk, 2) + ", Риск для " + DoubleToStr(StepLot, 2) + " лота = " + DoubleToStr(GetMarginLotForTopUpBalance(StepLot, OP_BUY), 2));
if (GetMarginLotForTopUp(buylot, OP_BUY) + GetMarginLotForTopUpBalance(StepLot*CountTradesLot(StepLot), OP_BUY) <= Risk - GetMarginLotForTopUpBalance(StepLot, OP_BUY))
{
if (StepLot <= max_lot_for_1_order) ticket3 = SetOrder(Symbol(), OP_BUY, StepLot, Ask, Slippage, 0, 0, Magic);
else
{
if (PrevTime != Time[0]) Alert("Слишком большой риск для открытия позиции!");
PrevTime = Time[0];
return;
}
}
}
}
Print("Количество сделок селл = " + IntegerToString(CountTrades(OP_SELL)));
if (CountTrades(OP_BUY) == 0 && CountTrades(OP_SELL) > 0)
{
Print("Профит позиций на текущем символе = " + DoubleToStr(GetProfitOpenPosInCurrency(Symbol(), -1, Magic), 2));
if (GetProfitOpenPosInCurrency(Symbol(), -1, Magic) > 0)
{
selllot = NormalizeDouble(GetMarginLotForOpening(Risk, OP_SELL), 2);
Print("Селл лот с риском " + DoubleToString(Risk, 2) + "% от депозита = " + DoubleToStr(selllot, 2));
Print("Риск для доливки = " + DoubleToStr(GetMarginLotForTopUp(selllot, OP_SELL) + GetMarginLotForTopUpBalance(StepLot*CountTradesLot(StepLot), OP_SELL), 2) + ", Риск = " + DoubleToStr(Risk, 2) + ", Риск для " + DoubleToStr(StepLot, 2) + " лота = " + DoubleToStr(GetMarginLotForTopUpBalance(StepLot, OP_SELL), 2));
if (GetMarginLotForTopUp(selllot, OP_SELL) + GetMarginLotForTopUpBalance(StepLot*CountTradesLot(StepLot), OP_SELL) <= Risk - GetMarginLotForTopUpBalance(StepLot, OP_SELL))
{
if (StepLot <= max_lot_for_1_order) ticket4 = SetOrder(Symbol(), OP_SELL, StepLot, Bid, Slippage, 0, 0, Magic);
else
{
if (PrevTime != Time[0]) Alert("Слишком большой риск для открытия позиции!");
PrevTime = Time[0];
return;
}
}
}
}
if (GetProfitOpenPosInCurrency(Symbol(), -1, Magic) >= AccountBalance()*(PercentClose/100))
{
Print("Профит позиций на текущем символе = " + DoubleToStr(GetProfitOpenPosInCurrency(Symbol(), -1, Magic), 2) + ", " + DoubleToStr(AccountBalance(), 2) + " * " + "(" + DoubleToStr(PercentClose, 2) + "/" + "100)");
CloseOrders();
}
}
}
//+------------------------------------------------------------------+
double GetMarginLotForTopUp(double lots,int type)
{
double risk = 0;
double margin = (risk/100)*AccountEquity();
string calc_currency="";
bool mode;
int leverage=(int)AccountInfoInteger(ACCOUNT_LEVERAGE);
//--- получим размер контракта
double lot_size=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE);
//--- получим валюту счета
string account_currency=AccountInfoString(ACCOUNT_CURRENCY);
//--- валюта, в которой берутся залоговые средства
string margin_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_MARGIN);
//--- валюта котировки
string profit_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_PROFIT);
double price = 0;
if (type == OP_BUY) price = Ask;
if (type == OP_SELL) price = Bid;
if(margin_currency==account_currency) risk = ((lots*lot_size)/(AccountEquity()*leverage))*100;
if(profit_currency==account_currency) risk = ((lots*(lot_size*price))/(AccountEquity()*leverage))*100;
if(margin_currency!=account_currency && profit_currency!=account_currency)
{
calc_currency=GetSymbolByCurrencies(margin_currency,account_currency);
mode=true;
//--- если полученное значение равно NULL, значит, такой символ не найден
if(calc_currency==NULL)
{
//--- попробуем наоборот
calc_currency=GetSymbolByCurrencies(account_currency,margin_currency);
mode=false;
if(calc_currency==NULL) Print("Откройте в терминале любой символ, в котором есть первая или вторая части теущего символа");
}
if(type == OP_BUY)
{
//--- обратная котировка
if(mode)
{
//--- считаем по цене покупки для обратной котировки
price=Ask;
risk = ((lots*(lot_size*price))/(AccountEquity()*leverage))*100;
}
//--- прямая котировка
else
{
//--- считаем по цене продажи для прямой котировки
price=Bid;
risk = ((lots*lot_size)/(AccountEquity()*leverage*price))*100;
}
}
//--- считаем для продажи
if(type == OP_SELL)
{
//--- обратная котировка
if(mode)
{
//--- считаем по цене продажи для обратной котировки
price=Bid;
risk = ((lots*(lot_size*price))/(AccountEquity()*leverage))*100;
}
//--- прямая котировка
else
{
//--- считаем по цене покупки для прямой котировки
price=Ask;
risk = ((lots*lot_size)/(AccountEquity()*leverage*price))*100;
}
}
}
return(NormalizeDouble(risk, 2));
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
double GetMarginLotForTopUpBalance(double lots,int type)
{
double risk = 0;
double margin = (risk/100)*AccountBalance();
string calc_currency="";
bool mode;
int leverage=(int)AccountInfoInteger(ACCOUNT_LEVERAGE);
//--- получим размер контракта
double lot_size=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE);
//--- получим валюту счета
string account_currency=AccountInfoString(ACCOUNT_CURRENCY);
//--- валюта, в которой берутся залоговые средства
string margin_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_MARGIN);
//--- валюта котировки
string profit_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_PROFIT);
double price = 0;
if (type == OP_BUY) price = Ask;
if (type == OP_SELL) price = Bid;
if(margin_currency==account_currency) risk = ((lots*lot_size)/(AccountBalance()*leverage))*100;
if(profit_currency==account_currency) risk = ((lots*(lot_size*price))/(AccountBalance()*leverage))*100;
if(margin_currency!=account_currency && profit_currency!=account_currency)
{
calc_currency=GetSymbolByCurrencies(margin_currency,account_currency);
mode=true;
//--- если полученное значение равно NULL, значит, такой символ не найден
if(calc_currency==NULL)
{
//--- попробуем наоборот
calc_currency=GetSymbolByCurrencies(account_currency,margin_currency);
mode=false;
if(calc_currency==NULL) Print("Откройте в терминале любой символ, в котором есть первая или вторая части теущего символа");
}
if(type == OP_BUY)
{
//--- обратная котировка
if(mode)
{
//--- считаем по цене покупки для обратной котировки
price=Ask;
risk = ((lots*(lot_size*price))/(AccountBalance()*leverage))*100;
}
//--- прямая котировка
else
{
//--- считаем по цене продажи для прямой котировки
price=Bid;
risk = ((lots*lot_size)/(AccountBalance()*leverage*price))*100;
}
}
//--- считаем для продажи
if(type == OP_SELL)
{
//--- обратная котировка
if(mode)
{
//--- считаем по цене продажи для обратной котировки
price=Bid;
risk = ((lots*(lot_size*price))/(AccountBalance()*leverage))*100;
}
//--- прямая котировка
else
{
//--- считаем по цене покупки для прямой котировки
price=Ask;
risk = ((lots*lot_size)/(AccountBalance()*leverage*price))*100;
}
}
}
return(NormalizeDouble(risk, 2));
}
//+------------------------------------------------------------------+
double GetMarginLotForOpening(double risk,int type)
{
double lots = 0;
double margin = (risk/100)*AccountBalance();
string calc_currency="";
bool mode;
int leverage=(int)AccountInfoInteger(ACCOUNT_LEVERAGE);
//--- получим размер контракта
double lot_size=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE);
//--- получим валюту счета
string account_currency=AccountInfoString(ACCOUNT_CURRENCY);
//--- валюта, в которой берутся залоговые средства
string margin_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_MARGIN);
//--- валюта котировки
string profit_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_PROFIT);
double price = 0;
if (type == OP_BUY) price = Ask;
if (type == OP_SELL) price = Bid;
if(margin_currency==account_currency) lots = (margin*leverage)/lot_size;
if(profit_currency==account_currency) lots = (margin*leverage)/(lot_size*price);
if(margin_currency!=account_currency && profit_currency!=account_currency)
{
calc_currency=GetSymbolByCurrencies(margin_currency,account_currency);
mode=true;
//--- если полученное значение равно NULL, значит, такой символ не найден
if(calc_currency==NULL)
{
//--- попробуем наоборот
calc_currency=GetSymbolByCurrencies(account_currency,margin_currency);
mode=false;
if(calc_currency==NULL) Print("Откройте в терминале любой символ, в котором есть первая или вторая части теущего символа");
}
if(type == OP_BUY)
{
//--- обратная котировка
if(mode)
{
//--- считаем по цене покупки для обратной котировки
price=Ask;
lots = (margin*leverage)/(lot_size*price);
}
//--- прямая котировка
else
{
//--- считаем по цене продажи для прямой котировки
price=Bid;
lots=(margin*price*leverage)/lot_size;
}
}
//--- считаем для продажи
if(type == OP_SELL)
{
//--- обратная котировка
if(mode)
{
//--- считаем по цене продажи для обратной котировки
price=Bid;
lots = (margin*leverage)/(lot_size*price);
}
//--- прямая котировка
else
{
//--- считаем по цене покупки для прямой котировки
price=Ask;
lots=(margin*price*leverage)/lot_size;
}
}
}
return(NormalizeDouble(lots, 2));
}
//+------------------------------------------------------------------+
//| Возвращает символ с заданными валютами залога и котировки |
//+------------------------------------------------------------------+
string GetSymbolByCurrencies(string margin_currency,string profit_currency)
{
//--- переберем в цикле все символы, которые представлены в окне "Обзор рынка"
for(int s=0;s<SymbolsTotal(true);s++)
{
//--- получим имя символа по номеру в списке "Обзор рынка"
string symbolname=SymbolName(s,true);
//--- получим валюту залога
string m_cur=SymbolInfoString(symbolname,SYMBOL_CURRENCY_MARGIN);
//--- получим валюту котировки (в чем измеряется прибыль при изменении цены)
string p_cur=SymbolInfoString(symbolname,SYMBOL_CURRENCY_PROFIT);
//--- если символ подошел по обеим заданным валютам, вернем имя символа
if(m_cur==margin_currency && p_cur==profit_currency) return(symbolname);
}
return(NULL);
}
//+------------------------------------------------------------------+
//| Суммарный профит по всем открытым позициям |
//+------------------------------------------------------------------+
double GetProfitOpenPosInCurrency(string sy="", int op=-1, int mn=-1) {
double p=0;
int i, k=OrdersTotal();
if (sy=="0") sy=Symbol();
for (i=0; i<k; i++) {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
if ((OrderSymbol()==sy || sy=="") && (op<0 || OrderType()==op)) {
if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
if (mn<0 || OrderMagicNumber()==mn) {
p+=OrderProfit();
}
}
}
}
}
return(NormalizeDouble(p, 2));
}
//+------------------------------------------------------------------+
//| Количество сделок |
//+------------------------------------------------------------------+
int CountTrades(int type = -1)
{
int count = 0;
for (int i = OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i,SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && (OrderType() == type || type == -1))
count++;
}
}
return(count);
}
//+------------------------------------------------------------------+
//| Количество сделок по лоту |
//+------------------------------------------------------------------+
int CountTradesLot(double lot)
{
int count = 0;
for (int i = OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i,SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderLots() == lot)
count++;
}
}
return(count);
}
//+------------------------------------------------------------------+
//| Закрывает все рыночные ордера |
//+------------------------------------------------------------------+
void CloseOrders()
{
for (int i=OrdersTotal()-1; i>=0; i--)
{
if (OrderSelect(i, SELECT_BY_POS))
{
if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
{
if (OrderType() == OP_BUY) cls = OrderClose(OrderTicket(), OrderLots(), Bid, Slippage);
if (OrderType() == OP_SELL) cls = OrderClose(OrderTicket(), OrderLots(), Ask, Slippage);
}
}
}
}
//+------------------------------------------------------------------------------+
//| Установка ордера с обработкой ошибок |
//+------------------------------------------------------------------------------+
int SetOrder(string sy, int op, double ll, double pp, int slippage,
double sl=0, double tp=0, int mn=0, string co="", datetime ex=0) {
color cl=IIFc(op==OP_BUYLIMIT || op==OP_BUYSTOP, clrBlue, clrRed);
datetime ot;
double pa, pb, mp, msl;
int err, it, ticket=0;
if (sy=="" || sy=="0") sy=Symbol();
msl=MarketInfo(sy, MODE_STOPLEVEL);
if (ex>0 && ex<TimeCurrent()) ex=0;
for (it=1; it<=50; it++) {
if (!IsTesting() && (!IsExpertEnabled() || IsStopped())) {
Print("SetOrder(): Остановка работы функции");
break;
}
while (!IsTradeAllowed()) Sleep(5000);
RefreshRates();
ot=TimeCurrent();
if (ll*MarketInfo(Symbol(),MODE_MARGINREQUIRED) <= AccountFreeMargin())
ticket=OrderSend(sy, op, ll, pp, slippage, sl, tp, co, mn, ex, cl);
if (ticket>0) {
Print("Ордер с тикетом " + IntegerToString(ticket) + " успешно выставлен!"); break;
} else {
err=GetLastError();
if (err==128 || err==142 || err==143) {
Sleep(1000*66);
if (ExistOrders(sy, op, mn, ot)) {
Print("Ордер с тикетом " + IntegerToString(ticket) + " успешно выставлен!"); break;
}
Print("Error(",err,") set order: ",ErrorDescription(err),", try ",it);
continue;
}
mp=MarketInfo(sy, MODE_POINT);
pa=MarketInfo(sy, MODE_ASK);
pb=MarketInfo(sy, MODE_BID);
if (pa==0 && pb==0) Print("SetOrder(): Проверьте в обзоре рынка наличие символа "+sy);
if (err != 0){
Print("Error(",err,") set order: ",ErrorDescription(err),", try ",it);
Print("Ask=",pa," Bid=",pb," sy=",sy," ll=",ll," op=",GetNameOP(op),
" pp=",pp," sl=",sl," tp=",tp," mn=",mn);}
// Неправильные стопы
if (err==130) {
// Корректировка ценовых уровней
if (modeSetOrders==1) {
Sleep(1000*5.3);
switch (op) {
case OP_BUYLIMIT:
if (pp>pa-msl*mp) pp=pa-msl*mp;
if (sl>pp-(msl+1)*mp) sl=pp-(msl+1)*mp;
if (tp>0 && tp<pp+(msl+1)*mp) tp=pp+(msl+1)*mp;
break;
case OP_BUYSTOP:
if (pp<pa+(msl+1)*mp) pp=pa+(msl+1)*mp;
if (sl>pp-(msl+1)*mp) sl=pp-(msl+1)*mp;
if (tp>0 && tp<pp+(msl+1)*mp) tp=pp+(msl+1)*mp;
break;
case OP_SELLLIMIT:
if (pp<pb+msl*mp) pp=pb+msl*mp;
if (sl>0 && sl<pp+(msl+1)*mp) sl=pp+(msl+1)*mp;
if (tp>pp-(msl+1)*mp) tp=pp-(msl+1)*mp;
break;
case OP_SELLSTOP:
if (pp>pb-msl*mp) pp=pb-msl*mp;
if (sl>0 && sl<pp+(msl+1)*mp) sl=pp+(msl+1)*mp;
if (tp>pp-(msl+1)*mp) tp=pp-(msl+1)*mp;
break;
}
Print("SetOrder(): Скорректированы ценовые уровни");
continue;
}
// Вход по текущим ценам
if (modeSetOrders==2) {
Print("SetOrder(): Вход по текущим ценам");
if (op==OP_BUYLIMIT || op==OP_BUYSTOP) OpenPosition(sy, OP_BUY, ll, slippage, sl, tp, mn, co);
if (op==OP_SELLLIMIT || op==OP_SELLSTOP) OpenPosition(sy, OP_SELL, ll, slippage, sl, tp, mn, co);
break;
}
}
// Блокировка работы советника
if (err==2 || err==64 || err==65 || err==133) break;
// Длительная пауза
if (err==4 || err==131 || err==132) {
Sleep(1000*300); break;
}
// Слишком частые запросы (8) или слишком много запросов (141)
if (err==8 || err==141) Sleep(1000*100);
if (err==139 || err==140 || err==148) break;
// Ожидание освобождения подсистемы торговли
if (err==146) while (IsTradeContextBusy()) Sleep(1000*11);
// Обнуление даты истечения
if (err==147) {
ex=0; continue;
}
if (err!=135 && err!=138) Sleep(1000*7.7);
}
}
return(ticket);
}
string GetNameOP(int op) {
switch (op) {
case OP_BUY : return("Бай");
case OP_SELL : return("Селл");
case OP_BUYLIMIT : return("БайЛимит");
case OP_SELLLIMIT: return("СелЛимит");
case OP_BUYSTOP : return("БайСтоп");
case OP_SELLSTOP : return("СеллСтоп");
default : return("Неизвестный тип");
}
}
bool ExistOrders(string sy="", int op=-1, int mn=-1, datetime ot=0) {
int i, k=OrdersTotal(), ty;
if (sy=="0") sy=Symbol();
for (i=0; i<k; i++) {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
ty=OrderType();
if (ty>1 && ty<6) {
if ((OrderSymbol()==sy || sy=="") && (op<0 || ty==op)) {
if (mn<0 || OrderMagicNumber()==mn) {
if (ot<=OrderOpenTime()) return(True);
}
}
}
}
}
return(False);
}
color IIFc(bool condition, color ifTrue, color ifFalse) {
if (condition) return(ifTrue); else return(ifFalse);
}
void OpenPosition(string sy, int op, double ll, int slippage, double sl=0, double tp=0, int mn=0, string comment=NULL) {
color clOpen;
double pp;
int err, ticket;
if (sy=="") sy=Symbol();
if (op==OP_BUY) {
pp=MarketInfo(sy, MODE_ASK); clOpen=clrBlue;
} else {
pp=MarketInfo(sy, MODE_BID); clOpen=clrRed;
}
if (ll*MarketInfo(Symbol(),MODE_MARGINREQUIRED) <= AccountFreeMargin())
ticket=OrderSend(sy, op, ll, pp, slippage, sl, tp, comment, mn, 0, clOpen);
if (ticket<0) {
err=GetLastError();
Print("Error(",err,") open ",GetNameOP(op),": ",ErrorDescription(err));
Print("Ask=",Ask," Bid=",Bid," sy=",sy," ll=",ll,
" pp=",pp," sl=",sl," tp=",tp," mn=",mn);
}
}