Tutte le domande dei nuovi arrivati su MQL4 e MQL5, aiuto e discussione su algoritmi e codici - pagina 34
Ti stai perdendo delle opportunità di trading:
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Registrazione
Accedi
Accetti la politica del sito e le condizioni d’uso
Se non hai un account, registrati
Mostrami tutto il tuo indicatore - vediamo cosa c'è di sbagliato.
Grazie.
Ecco qui.
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 LawnGreen
#property indicator_color2 DeepPink
#property indicator_width1 1
#property indicator_width2 1
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
extern string Stochastic = "Configure Stochastic Settings";
extern int TimeFrame1=1;
extern int KPeriod = 5;
extern int DPeriod = 3;
extern int Slowing = 3;
extern int OverBought = 80;
extern int OverSold = 20;
extern int TimeFrame2=5;
extern int KPeriod1 = 5;
extern int DPeriod1 = 3;
extern int Slowing1 = 3;
extern int OverBought1 = 55;
extern int OverSold1 = 45;
extern string Alerts = "Configure Alerts";
extern bool PopUpAlert = true; //Popup Alert
extern bool EmailAlert = true; //Email Alert
extern bool PushAlert = true; //Push Notifications Alert
// UP and DOWN Buffers
double UP[];
double DOWN[];
// Distance of arrows from the high or low of a bar
int distance = 3;
double MyPoint;
datetime CTime;
int OnInit()
{
//--- indicator buffers mapping
//UP Arrow Buffer
SetIndexEmptyValue(0,0.0);
SetIndexStyle(0,DRAW_ARROW,0,EMPTY);
SetIndexArrow(0,233);
SetIndexBuffer(0,UP);
//DOWN Arrow Buffer
SetIndexEmptyValue(1,0.0);
SetIndexStyle(1,DRAW_ARROW,0,EMPTY);
SetIndexArrow(1,234);
SetIndexBuffer(1,DOWN);
//Auto Adjustment for broker digits
if (Digits()==5||Digits()==3){MyPoint=Point*10;} else{MyPoint=Point;}
CTime=Time[0];
//---
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
//--- delete an object from a chart
Comment("");
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
//---
Comment("");
int limit = rates_total;
int count=prev_calculated;
for(int i=limit-count; i>=1;i--)
{
//Getting Stochastic buffer values using the iCustom function
double Stoch1 = iStochastic(NULL,TimeFrame1,KPeriod,DPeriod,Slowing,MODE_SMA,0,MODE_MAIN,i);
double Stoch2 = iStochastic(NULL,TimeFrame1,KPeriod,DPeriod,Slowing,MODE_SMA,0,MODE_MAIN,i+1);
double Stoch50_1 = iStochastic(NULL,TimeFrame2,KPeriod1,DPeriod1,Slowing1,MODE_SMA,0,MODE_MAIN,i);
double Stoch50_2 = iStochastic(NULL,TimeFrame2,KPeriod1,DPeriod1,Slowing1,MODE_SMA,0,MODE_MAIN,i+1);
if(Stoch1>20 && Stoch2<20&&Stoch50_1>50&&Stoch50_1>Stoch50_2)
{
UP[i]=Low[i]-distance*MyPoint;
}
if(Stoch1<80 && Stoch2>80&&Stoch50_1<50&&Stoch50_1<Stoch50_2)
{
DOWN[i]=High[i]+distance*MyPoint;
}
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
Grazie.
Ecco qui
...
Solo per chiarire.
Voglio mettere la freccia in alto se la linea dell'indicatore ha attraversato il livello 20, nel periodo M1, e la linea dell'indicatore è diretta in alto, sopra il livello 50, nel periodo M5.
Vediamo come ottenere i valori dal timeframe superiore, essendo su quello inferiore:
//| iTwoStoch.mq4 |
//| Copyright 2016, Artem A. Trishkin, Skype artmedia70 |
//| https://login.mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Artem A. Trishkin, Skype artmedia70"
#property link "https://login.mql5.com/ru/users/artmedia70"
#property version "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2
//--- plot UP
#property indicator_label1 "UP"
#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrLawnGreen
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- plot DN
#property indicator_label2 "DN"
#property indicator_type2 DRAW_ARROW
#property indicator_color2 clrDeepPink
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- enums
enum enumYN
{
enYes=1, // Да
enNo=0, // Нет
};
//--- input parameters
extern string Stochastic1 = "Параметры стохастика 1";
input ENUM_TIMEFRAMES TimeFrame1 = PERIOD_M1; // Таймфрейм
input int KPeriod1 = 5; // Период %K
input int DPeriod1 = 3; // Период %D
input int Slowing1 = 3; // Замедление
input double OverBought1 = 80; // Уровень перекупленности
input double OverSold1 = 20; // Уровень перепроданности
extern string Stochastic2 = "Параметры стохастика 2";
input ENUM_TIMEFRAMES TimeFrame2 = PERIOD_M5; // Таймфрейм
input int KPeriod2 = 5; // Период %K
input int DPeriod2 = 3; // Период %D
input int Slowing2 = 3; // Замедление
input double OverBought2 = 55; // Уровень перекупленности
input double OverSold2 = 45; // Уровень перепроданности
extern string Alerts = "Configure Alerts";
input enumYN UsePopUpAlert = enYes; // Popup Alert
input enumYN UseEmailAlert = enYes; // Email Alert
input enumYN UsePushAlert = enYes; // Push Notifications Alert
//--- indicator buffers
double BufferUP[];
double BufferDN[];
//--- global variables
int kperiod1; // Период %K стох.1
int dperiod1; // Период %D стох.1
int slowing1; // Замедление стох.1
double overBought1; // Уровень перекупленности стох.1
double overSold1; // Уровень перепроданности стох.1
//---
int kperiod2; // Период %K стох.2
int dperiod2; // Период %D стох.2
int slowing2; // Замедление стох.2
double overBought2; // Уровень перекупленности стох.2
double overSold2; // Уровень перепроданности стох.2
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,BufferUP);
SetIndexBuffer(1,BufferDN);
//--- setting a code from the Wingdings charset as the property of PLOT_ARROW
SetIndexArrow(0,233);
SetIndexArrow(1,234);
//---
kperiod1=(KPeriod1<1?1:KPeriod1);
kperiod2=(KPeriod2<1?1:KPeriod2);
dperiod1=(DPeriod1<1?1:DPeriod1);
dperiod2=(DPeriod2<1?1:DPeriod2);
slowing1=(Slowing1<1?1:Slowing1);
slowing2=(Slowing2<1?1:Slowing2);
//---
overBought1=(OverBought1>100.0?100.0:OverBought1<0.1?0.1:OverBought1);
overSold1=(OverSold1<0?0:OverSold1>99.9?99.9:OverSold1);
if(overBought1<=overSold1) overBought1=overSold1+0.1;
if(overSold1>=overBought1) overSold1=overBought1-0.1;
//---
overBought2=(OverBought2>100.0?100.0:OverBought2<0.1?0.1:OverBought2);
overSold2=(OverSold2<0?0:OverSold2>99.9?99.9:OverSold2);
if(overBought2<=overSold2) overBought2=overSold2+0.1;
if(overSold2>=overBought2) overSold2=overBought2-0.1;
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
//---
if(rates_total<2) return(0);
int limit=rates_total-prev_calculated;
if(limit>1) {
limit=rates_total-2;
ArrayInitialize(BufferUP,EMPTY_VALUE);
ArrayInitialize(BufferDN,EMPTY_VALUE);
}
for(int i=limit; i>=0; i--) {
int bar_sto2_0=iBarShift(Symbol(),TimeFrame2,iTime(Symbol(),TimeFrame2,i));
int bar_sto2_1=iBarShift(Symbol(),TimeFrame2,iTime(Symbol(),TimeFrame2,i+1));
double sto1_0=iStochastic(Symbol(),TimeFrame1,kperiod1,dperiod1,slowing1,MODE_SMA,STO_LOWHIGH,MODE_MAIN,i);
double sto1_1=iStochastic(Symbol(),TimeFrame1,kperiod1,dperiod1,slowing1,MODE_SMA,STO_LOWHIGH,MODE_MAIN,i+1);
double sto2_0=iStochastic(Symbol(),TimeFrame2,kperiod2,dperiod2,slowing2,MODE_SMA,STO_LOWHIGH,MODE_MAIN,bar_sto2_0);
double sto2_1=iStochastic(Symbol(),TimeFrame2,kperiod2,dperiod2,slowing2,MODE_SMA,STO_LOWHIGH,MODE_MAIN,bar_sto2_1);
Comment(
"\n",
"Stoch ",EnumToString(TimeFrame1),
", бар ",(i+1)," > время: ",TimeToString(time[i+1],TIME_MINUTES),", значение: ",DoubleToString(sto1_1,Digits()),
"; бар ",i," > время: ",TimeToString(time[i],TIME_MINUTES),", значение: ",DoubleToString(sto1_0,Digits()),"\n",
//---
"Stoch ",EnumToString(TimeFrame2),
", бар ",bar_sto2_1," > время: ",TimeToString(iTime(Symbol(),TimeFrame2,bar_sto2_1),TIME_MINUTES),", значение: ",DoubleToString(sto2_1,Digits()),
"; бар ",bar_sto2_0," > время: ",TimeToString(iTime(Symbol(),TimeFrame2,bar_sto2_0),TIME_MINUTES),", значение: ",DoubleToString(sto2_0,Digits())
);
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
Poi, provate a fare la logica che volete al posto di Comment().
Vediamo...
Vediamo come ottenere valori da un timeframe superiore mentre si è su uno inferiore:
E poi provate a fare la logica che volete al posto di Comment().
Vedremo...
Grazie, ha funzionato )
Nell'Expert Advisor, quando chiamo l'indicatore, devo solo specificare il numero del timeframe desiderato, mentre l'indicatore "balla" con lo spostamento. Dove posso leggerne di più?
Grazie, ha funzionato )
Nell'EA, quando chiamo l'indicatore, devo solo specificare il numero del timeframe desiderato, e l'indicatore "balla" con lo spostamento. Dove posso leggerne di più?
Non l'ho letto da nessuna parte - non ne ho idea.
Immagina questo: vai in bicicletta attraverso i bar sulla M1. Si prendono i valori dell'indicatore dal numero della barra a cui si riferisce l'indice del ciclo i.
Nella tabella nell'intestazione in alto l'indice del ciclo M1, sotto c'è il valore del tempo della barra a cui si riferisce l'indice M1
In basso l'indice del ciclo M5, sopra c'è il valore del tempo della barra a cui si riferisce l'indice M5
Quando si passa il valore dell'indice del timeframe corrente, al quale inizia il ciclo, nella funzione iCustom(), si ottengono i valori dell'indicatore dal timeframe più vecchio secondo l'indice. Ma l'indice non si riferisce alla barra necessaria, come si può vedere nella tabella.
E questo dovrebbe essere fatto anche negli expert advisor, altrimenti - non stai prendendo i valori dalla barra prevista e pensi di averla corretta. Beh, l'hai preso bene, ma non dal bar sbagliato. Questo deve essere conosciuto e preso in considerazione.
Cioè, alla ricezione di dati multitemporali è necessario basarsi sul tempo, e ricalcolarlo in numero di barre al timeframe richiesto.
Artyom, per favore aiuta anche me, ho problemi con gli indicatori.
Ho bisogno di trovare queste costruzioni e metterci delle frecce. Le funzioni nell'Expert Advisor funzionano e sono semplici da collegare, beh, è comprensibile - hanno solo bisogno di valori attuali, ma come trasferirli all'indicatore, per disegnare la coincidenza sullo storico...?
Le frecce dovrebbero essere disegnate su una candela, non appena l'Alto[1] e il Basso[1] coincidono.
//| iTwo.mq4 |
//| Copyright 2016, Artem A. Trishkin, Skype artmedia70 |
//| https://login.mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Artem A. Trishkin, Skype artmedia70"
#property link "https://login.mql5.com/ru/users/artmedia70"
#property version "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2
//--- plot UP
#property indicator_label1 "UP"
#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrLawnGreen
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- plot DN
#property indicator_label2 "DN"
#property indicator_type2 DRAW_ARROW
#property indicator_color2 clrDeepPink
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- input parameters
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1;
input string dSymbol = "AUDUSD";
//--- indicator buffers
double BufferUP[];
double BufferDN[];
//--- global variables
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,BufferUP);
SetIndexBuffer(1,BufferDN);
//--- setting a code from the Wingdings charset as the property of PLOT_ARROW
SetIndexArrow(0,233);
SetIndexArrow(1,234);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
//---
if(rates_total<2) return(0);
int limit=rates_total-prev_calculated;
if(limit>1) {
limit=rates_total-2;
ArrayInitialize(BufferUP,EMPTY_VALUE);
ArrayInitialize(BufferDN,EMPTY_VALUE);
}
int NumFrUp = GetFractalBar(dSymbol,PERIOD_CURRENT,0,MODE_UPPER); // номер бара Up
int NumFrDn = GetFractalBar(dSymbol,PERIOD_CURRENT,0,MODE_LOWER); // номер бара Dn
Comment( "Bear: " , GetBearBull(dSymbol, TimeFrame, 3) == 1, // Подряд 3 бара вверх
"\nBull: ", GetBearBull(dSymbol, TimeFrame, 3) == 2, // Подряд 3 бара вниз
"\nNumFrUp: " , NumFrUp, // номер бара Up
"\nNumFrDn: ", NumFrDn, // номер бара Dn
"\nPriceFrUp: " ,iHigh(dSymbol,PERIOD_CURRENT,NumFrUp), // Цена верхнего фрактала
"\nPriceDn: ", iLow(dSymbol,PERIOD_CURRENT,NumFrDn) // Цена нижнего фрактала
);
for(int i=limit; i>=0; i--) {
//--
if(/* что сюда */0)
{
BufferUP[i]=Low[i]-50*_Point;
}
//--
if(/* что сюда */0)
{
BufferDN[i]=High[i]+50*_Point;
}
} // end for
//--- return value of prev_calculated for next call
return(rates_total);
}
//===============================================================================================
//---------------------- Возвращает номер бара фрактала по его номеру --------------------------+
//===============================================================================================
int GetFractalBar(string symb="0", int tf=0, int nf=0, int mode=MODE_UPPER) {
if(symb=="0") { symb=Symbol();}
double f=0;
int kf=0;
for(int i=3; i<iBars(symb, tf)-1; i++) {
if(mode==MODE_LOWER){
f=iFractals(symb, tf, MODE_LOWER, i);
if(f!=0) {
kf++;
if(kf>nf) { return(i);}
}}
if(mode==MODE_UPPER){
f=iFractals(symb, tf, MODE_UPPER, i);
if(f!=0) {
kf++;
if(kf>nf) { return(i);}
}}}
return(-1);
}
//===============================================================================================
//------------------------ Функция возвращает направление баров подряд -------------------------+
//===============================================================================================
int GetBearBull(string symb="0", int tf=0, int ne=5) {
if(symb=="0") { symb=Symbol();}
double open1=0,close1=0,open2=0,close2=0;
int b=1,s=1;
for(int i=1; i<ne; i++) {
open1=iOpen(symb,tf,i);
close1=iClose(symb,tf,i);
open2= iOpen(symb,tf,i+1);
close2= iClose(symb,tf,i+1);
if(open2<close2 && open1<close1 && open2<open1) { // бычьи
b++;
if(b==ne) { return(1);}
}
if(open2>close2 && open1>close1 && open2>open1) { // медвежьи
s++;
if(s==ne) { return(2);}
}
}
return(0);
}
//===============================================================================================
Poi cercherò di inserire altri modelli seguendo l'analogia, in modo da non disturbare l'Expert Advisor.
Grazie!
Artyom, per favore aiuta anche me, ho problemi con gli indicatori.
Ho bisogno di trovare queste costruzioni e metterci delle frecce. Le funzioni nell'Expert Advisor funzionano e sono semplici da collegare, beh, è comprensibile - hanno solo bisogno di valori attuali, ma come trasferirli all'indicatore, per disegnare la coincidenza sullo storico...?
Le frecce sono disegnate su una candela, quando si verifica la coincidenza di High[1] e Low[1].
...
Poi cercherò di inserire altri modelli seguendo l'analogia, in modo da non disturbare l'Expert Advisor.
Grazie!
Ci dovrebbe essere una logica diversa per i diversi modelli, perché non tutti sono uguali. E per uno stesso modello, la logica dovrebbe essere scritta in modo diverso da diversi programmatori.
E cosa esattamente, quale modello vuole determinare?
Cominciamo con questo.
Ci deve essere una logica diversa per i diversi modelli, perché non tutti i modelli sono uguali. E per lo stesso modello, programmatori diversi scriveranno una logica diversa.
E che cosa esattamente, quale modello vuole definire?
Cominciamo con questo.
Ho allegato una foto.
La condizione: il frattale "3" è superiore al frattale "2" e il frattale "1" è superiore al "2" -FrDn3 > FrDn2&& FrDn2< FrDn1 Guardiamo le candele, i frattali sono già formati e aspettiamo la conferma del pattern candlestick,
e se ci sono"3" in aumento in una fila - comprare (freccia) -GetBearBull(dSymbol,0,3)==1(1 - comprare)
È viceversa per la vendita.
È facile metterlo in un Expert Advisor, ma in un indicatore...
Ho allegato l'immagine.
Condizione necessaria: il frattale "3" è superiore al frattale "2" e il frattale "1" è superiore al "2" -FrDn3 > FrDn2&& FrDn2< FrDn1 Guardiamo la candela, i frattali si sono già formati e aspettiamo la conferma del pattern candlestick,
e se ci sono"3" crescenti di fila - comprare (freccia) -GetBearBull(dSymbol,0,3)==1(1 - comprare)
È viceversa per la vendita.
È facile metterlo in un Expert Advisor, ma in un indicatore...
Nell'indicatore è viceversa - se si inizia la ricerca nella profondità della storia, nell'indicatore - dal suo inizio. Cerca prima il frattale di sinistra, poi quello di mezzo, poi quello di destra.
Gestire le bandiere.
Nell'indicatore, la logica è opposta - se nell'EA si inizia a cercare in profondità nella storia, allora nell'indicatore si inizia dall'inizio della storia. Cerca prima il frattale di sinistra, poi quello di mezzo, poi quello di destra.
Gestire le bandiere.
Chiedo di mostrare la variante pronta, forse la vedrò una volta e le domande cadranno, ma ora ne ho mille e non posso decidere.
Cosa fare con tutto questo in un indicatore - non ne ho idea(
//---------------------- Возвращает номер бара фрактала по его номеру --------------------------+
//===============================================================================================
int GetFractalBar(string symb="0", int tf=0, int nf=0, int mode=MODE_UPPER) {
if(symb=="0") { symb=Symbol();}
double f=0;
int kf=0;
for(int i=3; i<iBars(symb, tf)-1; i++) {
if(mode==MODE_LOWER){
f=iFractals(symb, tf, MODE_LOWER, i);
if(f!=0) {
kf++;
if(kf>nf) { return(i);}
}}
if(mode==MODE_UPPER){
f=iFractals(symb, tf, MODE_UPPER, i);
if(f!=0) {
kf++;
if(kf>nf) { return(i);}
}}}
return(-1);
}
//===============================================================================================
//------------------------ Функция возвращает направление баров подряд -------------------------+
//===============================================================================================
int GetBearBull(string symb="0", int tf=0, int ne=5) {
if(symb=="0") { symb=Symbol();}
double open1=0,close1=0,open2=0,close2=0;
int b=1,s=1;
for(int i=1; i<ne; i++) {
open1=iOpen(symb,tf,i);
close1=iClose(symb,tf,i);
open2= iOpen(symb,tf,i+1);
close2= iClose(symb,tf,i+1);
if(open2<close2 && open1<close1 && open2<open1) { // бычьи
b++;
if(b==ne) { return(1);}
}
if(open2>close2 && open1>close1 && open2>open1) { // медвежьи
s++;
if(s==ne) { return(2);}
}
}
return(0);
}
//===============================================================================================
Se potessi, allora niente domande, capisco la logica, ma non posso implementarla nel codice, quindi chiedo di mostrarmi una variante pronta, la vedrò una volta e le domande spariranno in futuro, ma ora ce ne sono migliaia e non posso risolverle da solo.
Cosa fare con tutto questo in un indicatore - non ne ho idea(
//---------------------- Возвращает номер бара фрактала по его номеру --------------------------+
//===============================================================================================
int GetFractalBar(string symb="0", int tf=0, int nf=0, int mode=MODE_UPPER) {
if(symb=="0") { symb=Symbol();}
double f=0;
int kf=0;
for(int i=3; i<iBars(symb, tf)-1; i++) {
if(mode==MODE_LOWER){
f=iFractals(symb, tf, MODE_LOWER, i);
if(f!=0) {
kf++;
if(kf>nf) { return(i);}
}}
if(mode==MODE_UPPER){
f=iFractals(symb, tf, MODE_UPPER, i);
if(f!=0) {
kf++;
if(kf>nf) { return(i);}
}}}
return(-1);
}
//===============================================================================================
//------------------------ Функция возвращает направление баров подряд -------------------------+
//===============================================================================================
int GetBearBull(string symb="0", int tf=0, int ne=5) {
if(symb=="0") { symb=Symbol();}
double open1=0,close1=0,open2=0,close2=0;
int b=1,s=1;
for(int i=1; i<ne; i++) {
open1=iOpen(symb,tf,i);
close1=iClose(symb,tf,i);
open2= iOpen(symb,tf,i+1);
close2= iClose(symb,tf,i+1);
if(open2<close2 && open1<close1 && open2<open1) { // бычьи
b++;
if(b==ne) { return(1);}
}
if(open2>close2 && open1>close1 && open2>open1) { // медвежьи
s++;
if(s==ne) { return(2);}
}
}
return(0);
}
//===============================================================================================
Avete bisogno di una funzione che restituisca un numero di barra frattale per il suo numero?
Avete bisogno di una funzione che restituisca la presenza di un frattale sulla barra richiesta (indice del ciclo+3)