Appearance
question:questo è il codice originale senza frecce FUNZIOANATE //+------------------------------------------------------------------+ //| MTF Stochastic.mq4 | //| 2007, Christof Risch (iya) | //| Stochastic indicator from any timeframe. | //+------------------------------------------------------------------+ // Change Log: // 2.1 2012 07 24 Modified to display only the Signal line (smoothed sma) // cr: 2012 07 20 Added NextHigherAuto to automatically seletc the next higher time frame // Added HidePctD to suppress the Slow line, prn #property link "http://www.forexfactory.com/showthread.php?t=30109" #property indicator_separate_window #property indicator_buffers 4 #property indicator_color1 Green //C'255,255,255' // White // %K line #property indicator_color2 Red //Yellow // DimGray // %D line #property indicator_color3 Green // C'255,255,255' // White // %K line of the current candle #property indicator_color4 Red //Yellow // DimGray // %D line of the current candle #property indicator_level1 80 #property indicator_level2 20 #property indicator_level3 50 #property indicator_levelcolor DarkSlateGray #property indicator_maximum 100 #property indicator_minimum 0 //---- input parameters extern bool NextHigherAuto = true; extern bool HidePctK = false; extern bool HidePctD = false; extern int TimeFrame = 0, // {1=M1, 5=M5, 15=M15, ..., 1440=D1, 10080=W1, 43200=MN1} KPeriod = 11, DPeriod = 3, Slowing = 3, MAMethod = 0, // {0=SMA, 1=EMA, 2=SMMA, 3=LWMA} PriceField = 0; // {0=Hi/Low, 1=Close/Close} extern bool ShowClock = false; // display time to candle close countdown extern color ClockColor = Red; //---- indicator buffers double BufferK[], BufferD[], BufferK_Curr[], BufferD_Curr[]; //---- string IndicatorName = "", TimeLabelName = ""; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { if ( TimeFrame == 0 ) TimeFrame = Period(); if ( NextHigherAuto ) TimeFrame = GetHigherTimeFrame( TimeFrame ) ; //---- name for DataWindow and indicator subwindow label switch(TimeFrame) { case 1: IndicatorName="Period M1"; break; case 5: IndicatorName="Period M5"; break; case 15: IndicatorName="Period M15"; break; case 30: IndicatorName="Period M30"; break; case 60: IndicatorName="Period H1"; break; case 240: IndicatorName="Period H4"; break; case 1440: IndicatorName="Period D1"; break; case 10080: IndicatorName="Period W1"; break; case 43200: IndicatorName="Period MN1"; break; default: {TimeFrame = Period(); init(); return(0);} } IndicatorName = IndicatorName+" Stoch("+KPeriod+","+DPeriod+","+Slowing+")"; IndicatorShortName(IndicatorName); IndicatorDigits(1); string TimeFrameStr = TF2Str(TimeFrame); //---- indicator lines SetIndexBuffer(0,BufferK); SetIndexBuffer(1,BufferD); SetIndexBuffer(2,BufferK_Curr); SetIndexBuffer(3,BufferD_Curr); SetIndexStyle(0,DRAW_LINE,EMPTY,1); //SetIndexStyle(0,DRAW_NONE); SetIndexStyle(2,DRAW_LINE,EMPTY,1); //SetIndexStyle(2,DRAW_NONE); if ( ! HidePctK ) { SetIndexStyle(0,DRAW_LINE,EMPTY,1); SetIndexStyle(2,DRAW_LINE,EMPTY,1); SetIndexLabel(0,TimeFrameStr+" %K line"); SetIndexLabel(2,TimeFrameStr+" %K CurrBar"); } else { SetIndexStyle(0,DRAW_NONE); SetIndexStyle(2,DRAW_NONE); SetIndexLabel(0,NULL); SetIndexLabel(2,NULL); } if ( ! HidePctD ) { SetIndexStyle(1,DRAW_LINE,EMPTY,1); SetIndexStyle(3,DRAW_LINE,EMPTY,1); SetIndexLabel(1,TimeFrameStr+" %D Signal"); SetIndexLabel(3,TimeFrameStr+" %D CurrBar"); } else { SetIndexStyle(1,DRAW_NONE); SetIndexStyle(3,DRAW_NONE); SetIndexLabel(1,NULL); SetIndexLabel(3,NULL); } } //+------------------------------------------------------------------+ int deinit() { if(TimeLabelName!="") if(ObjectFind (TimeLabelName) != -1) ObjectDelete(TimeLabelName); } //+------------------------------------------------------------------+ //| MTF Stochastic | //+------------------------------------------------------------------+ int start() { //---- // counted bars from indicator time frame static int countedBars1 = 0; //---- // counted bars from display time frame if(Bars-1-IndicatorCounted() > 1 && countedBars1!=0) countedBars1 = 0; int bars1 = iBars(NULL,TimeFrame), start1 = bars1-1-countedBars1, limit1 = iBarShift(NULL,TimeFrame,Time[Bars-1]); if(countedBars1 != bars1-1) { countedBars1 = bars1-1; ArrayInitialize(BufferK_Curr,EMPTY_VALUE); ArrayInitialize(BufferD_Curr,EMPTY_VALUE); if(TimeLabelName!="") if(ObjectFind (TimeLabelName) != -1) ObjectDelete(TimeLabelName); } if(start1 > limit1 && limit1 != -1) start1 = limit1; //---- // 3... 2... 1... GO! for(int i = start1; i >= 0; i--) { int shift1 = i; if(TimeFrame < Period()) shift1 = iBarShift(NULL,TimeFrame,Time[i]); int time1 = iTime (NULL,TimeFrame,shift1), shift2 = iBarShift(NULL,0,time1); double stochK = iStochastic(NULL,TimeFrame,KPeriod,DPeriod,Slowing,MAMethod,PriceField,0,shift1), stochD = iStochastic(NULL,TimeFrame,KPeriod,DPeriod,Slowing,MAMethod,PriceField,1,shift1); //---- // old (closed) candles if(shift1>=1) { BufferK[shift2] = stochK; BufferD[shift2] = stochD; } //---- // current candle if((TimeFrame >=Period() && shift1<=1) || (TimeFrame < Period() &&(shift1==0||shift2==1))) { BufferK_Curr[shift2] = stochK; BufferD_Curr[shift2] = stochD; } //---- // linear interpolatior for the number of intermediate bars, between two higher timeframe candles. int n = 1; if(TimeFrame > Period()) { int shift2prev = iBarShift(NULL,0,iTime(NULL,TimeFrame,shift1+1)); if(shift2prev!=-1 && shift2prev!=shift2) n = shift2prev - shift2; } //---- // apply interpolation double factor = 1.0 / n; if(shift1>=1) if(BufferK[shift2+n]!=EMPTY_VALUE && BufferK[shift2]!=EMPTY_VALUE) { for(int k = 1; k < n; k++) { BufferK[shift2+k] = k*factor*BufferK[shift2+n] + (1.0-k*factor)*BufferK[shift2]; BufferD[shift2+k] = k*factor*BufferD[shift2+n] + (1.0-k*factor)*BufferD[shift2]; } } //---- // current candle if(shift1==0) if(BufferK_Curr[shift2+n]!=EMPTY_VALUE && BufferK_Curr[shift2]!=EMPTY_VALUE) { for(k = 1; k < n; k++) { BufferK_Curr[shift2+k] = k*factor*BufferK_Curr[shift2+n] + (1.0-k*factor)*BufferK_Curr[shift2]; BufferD_Curr[shift2+k] = k*factor*BufferD_Curr[shift2+n] + (1.0-k*factor)*BufferD_Curr[shift2]; } //---- // candle time countdown if(ShowClock) { int m,s; s = iTime(NULL,TimeFrame,0)+TimeFrame*60 - TimeCurrent(); m = (s-s%60)/60; s = s%60; string text; if(s<10) text = "0"+s; else text = ""+s; text = " "+m+":"+text; int window = WindowFind(IndicatorName); if(window==-1) window = WindowOnDropped() ; TimeLabelName = IndicatorName+" Time Counter "+window; if(ObjectFind (TimeLabelName) == -1) ObjectCreate(TimeLabelName, OBJ_TEXT, window, Time[shift2], BufferK_Curr[shift2]+3); else ObjectMove (TimeLabelName, 0, Time[shift2], BufferK_Curr[shift2]+3); ObjectSetText (TimeLabelName, text, 8, "Verdana", ClockColor); } } } return(0); } string TF2Str(int iPeriod) { switch(iPeriod) { case PERIOD_M1: return("M1"); case PERIOD_M5: return("M5"); case PERIOD_M15: return("M15"); case PERIOD_M30: return("M30"); case PERIOD_H1: return("H1"); case PERIOD_H4: return("H4"); case PERIOD_D1: return("D1"); case PERIOD_W1: return("W1"); case PERIOD_MN1: return("MN1"); default: return("M"+iPeriod); } return(0); } int GetHigherTimeFrame(int CurrentPeriod ) { if ( CurrentPeriod == 0 ) CurrentPeriod = Period(); if( CurrentPeriod == 1 ) { return(5); } else if( CurrentPeriod == 5 ) { return(15); } else if( CurrentPeriod == 15 ) { return(30); } else if( CurrentPeriod == 30 ) { return(60); } else if( CurrentPeriod == 60 ) { return(240); } else if( CurrentPeriod == 240 ) { return(1440); } else if( CurrentPeriod == 1440 ) { return(10080); } else if( CurrentPeriod == 10080 ) { return(43200); } else if( CurrentPeriod == 43200 ) { return(43200); } } // int GetHigherTimeFrame() perchè inserendo le frecce si rompe?
answer:Basandoci sul codice funzionante che hai fornito senza frecce, possiamo integrare il codice per le frecce facendo attenzione ad evitare rompere la logica esistente. Il codice delle frecce richiede di identificare incroci tra la linea %K e la linea %D dello stocastico, quindi il passo aggiuntivo sta nel rilevare detti incroci ed eseguire il disegno delle frecce nei punti appropriati. Ecco gli step che devi seguire per aggiungere il codice delle frecce nel modo corretto: 1. **Aggiungere due nuovi buffer per le frecce**: Aggiungi due nuovi buffer nella sezione dei buffer indicatori insieme a linee per inizializzare e configurare questi buffer nel metodo `init()`. ```mql4 double ArrowUpBuffer[]; double ArrowDownBuffer[]; ``` Nel metodo `init()`: ```mql4 SetIndexBuffer(4, ArrowUpBuffer); ArraySetAsSeries(ArrowUpBuffer, true); SetIndexBuffer(5, ArrowDownBuffer); ArraySetAsSeries(ArrowDownBuffer, true); SetIndexStyle(4, DRAW_ARROW); SetIndexStyle(5, DRAW_ARROW); SetIndexArrow(4, SYMBOL_ARROWUP); SetIndexArrow(5, SYMBOL_ARROWDOWN); ``` 2. **Inizializzare i buffer delle frecce**: All'inizio del metodo `start()`, inizializza i buffer delle frecce a `EMPTY_VALUE`. ```mql4 ArrayInitialize(ArrowUpBuffer, EMPTY_VALUE); ArrayInitialize(ArrowDownBuffer, EMPTY_VALUE); ``` 3. **Rilevare gli incroci e disegnare le frecce**: Aggiungi del codice nel `start()` per rilevare gli incroci dello stocastico e assegnare valori ai buffer delle frecce basandoti su questi incroci. ```mql4 for(int i = start1; i >= 1; i--) // Aggiungi il ciclo per le frecce a partire da 1, non 0, in modo da non guardare la barra corrente { // ... [Il codice esistente va qui] // Aggiungi il codice per disegnare le frecce solo per le barre precedenti alla barra corrente if(i > 1) { double prevStochK = iStochastic(NULL, TimeFrame, KPeriod, DPeriod, Slowing, MAMethod, PriceField, 0, shift1+1), prevStochD = iStochastic(NULL, TimeFrame, KPeriod, DPeriod, Slowing, MAMethod, PriceField, 1, shift1+1); if(BufferK[shift2] < BufferD[shift2] && prevStochK > prevStochD) // Incrocio verso l'alto { ArrowUpBuffer[shift2] = Low[shift2] - (4 * Point); } else if(BufferK[shift2] > BufferD[shift2] && prevStochK < prevStochD) // Incrocio verso il basso { ArrowDownBuffer[shift2] = High[shift2] + (4 * Point); } } // ... [Il codice esistente va qui] } ``` 4. **Aumenta il numero di buffer indicatori**: Aumentare il valore di `indicator_buffers` a 6 perché ora hai sei buffer. ```mql4 #property indicator_buffers 6 ``` 5. **Rimuovere la confusione tra i frame temporali**: Se stai introducendo frecce basate su un timeframe diverso da quello del grafico corrente, devi fare attenzione a come calcoli gli shift e le barre. Assicurati di aver compreso come i diversi timeframe si correlano tra loro e di aver codificato correttamente questa logica. Il codice originale ha un meccanismo di interpolazione delle barre; controlla attentamente l'utilizzo di `shift1`, `shift2`, `n` e il loro impatto sul posizionamento delle frecce. Implementando questi passaggi con attenzione, dovresti essere in grado di aggiungere la funzionalità delle frecce al tuo indicatore MTF Stochastic senza "rompere" il funzionamento originale. Ricorda di testare accuratamente l'indicatore in un ambiente di sviluppo per verificare che tutto funzioni come previsto.
question:puoi riscrivere tutto il codice, pezzo per pezzo in modo completo, usando più messaggi se necessario?
answer:Sicuramente! Ecco il codice riscritto per includere le frecce sugli incroci dello Stocastico, basandomi sul codice originale che mi hai fornito. Riporterò il codice per parti nelle successive risposte qui sotto. Utilizzerò questo spazio per indicare che inizierò dal metodo `init()` e che modificherò la dichiarazione della proprietà `indicator_buffers` per contemplare i due nuovi buffer delle frecce. Inoltre, aggiungerò le istruzioni per impostare i buffer per le frecce e i loro stili nel metodo `init()`. **Parte 1: Aggiornamenti al metodo `init()`** ```mql4 //+------------------------------------------------------------------+ //| ...[Precedente header con info e link] | //+------------------------------------------------------------------+ #property indicator_separate_window #property indicator_buffers 6 // Aumentato a 6 per includere i buffer delle frecce #property indicator_color1 Green #property indicator_color2 Red #property indicator_color3 Green #property indicator_color4 Red //... [Altri #property qui] ... //---- input parameters //... [Esterni variabili qui] ... //---- indicator buffers double BufferK[]; double BufferD[]; double BufferK_Curr[]; double BufferD_Curr[]; double ArrowUpBuffer[]; double ArrowDownBuffer[]; //... [Altri buffer e variabili qui] ... //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { //... [Precedente logica del metodo init qui] ... //---- setting index buffers with arrows for current candle SetIndexBuffer(4, ArrowUpBuffer); SetIndexArrow(4, SYMBOL_ARROWUP); // Seta SYMBOL_ARROWUP per mostrare la freccia verso l'alto SetIndexBuffer(5, ArrowDownBuffer); SetIndexArrow(5, SYMBOL_ARROWDOWN); // Seta SYMBOL_ARROWDOWN per mostrare la freccia verso il basso // Gli altri SetIndexStyle e SetIndexLabel andranno nell'area successiva } //+------------------------------------------------------------------+ //| ...[Precedente implementazione del metodo deinit] | //+------------------------------------------------------------------+ //... [Precedente implementazione del metodo start] ... //... [Precedenti funzioni helper] ... ``` Continuo nelle risposte seguenti con le modifiche al metodo `start()` e alle funzioni helper necessarie.
question:no non hai capito. in modo completo senza saltare nessun pezzo e senza usare segnaposto per altro codice. tutto il codice pezzo per pezzo completo
answer:Capisco, inizieremo dall'inizio e ricostruiremo il codice con le aggiunte necessarie per le frecce. Qui di seguito è presentato il codice aggiornato e completo in parti, considerato il limite di lunghezza dei messaggi. **Parte 1: Dichiarazioni iniziali e inizializzazione dei buffer** ```mql4 //+------------------------------------------------------------------+ //| MTF Stochastic.mq4 | //| Modificato per includere frecce | //+------------------------------------------------------------------+ #property link "http://www.forexfactory.com/showthread.php?t=30109" #property indicator_separate_window #property indicator_buffers 6 #property indicator_color1 Green // %K line #property indicator_color2 Red // %D line #property indicator_color3 Green // %K line of the current candle #property indicator_color4 Red // %D line of the current candle #property indicator_color5 Blue // Arrow Up #property indicator_color6 Red // Arrow Down #property indicator_level1 80 #property indicator_level2 20 #property indicator_level3 50 #property indicator_levelcolor DarkSlateGray #property indicator_maximum 100 #property indicator_minimum 0 //---- input parameters extern bool NextHigherAuto = true; extern bool HidePctK = false; extern bool HidePctD = false; extern int TimeFrame = 0; // {1=M1, 5=M5, 15=M15, ..., 1440=D1, 10080=W1, 43200=MN1} extern int KPeriod = 11; extern int DPeriod = 3; extern int Slowing = 3; extern int MAMethod = 0; // {0=SMA, 1=EMA, 2=SMMA, 3=LWMA} extern int PriceField = 0; // {0=Hi/Low, 1=Close/Close} extern bool ShowClock = false; // display time to candle close countdown extern color ClockColor = Red; //---- indicator buffers double BufferK[]; double BufferD[]; double BufferK_Curr[]; double BufferD_Curr[]; double ArrowUpBuffer[]; double ArrowDownBuffer[]; //---- indicator name and time label name for display string IndicatorName = ""; string TimeLabelName = ""; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { // Determine TimeFrame automatically if required if (TimeFrame == 0) TimeFrame = Period(); if (NextHigherAuto) TimeFrame = GetHigherTimeFrame(TimeFrame); // Name for DataWindow and indicator subwindow label IndicatorName = "MTF Stochastic (" + TimeFrameToStr(TimeFrame) + ")"; IndicatorShortName(IndicatorName); // Setting the indicator buffers for %K and %D lines, and their current values SetIndexBuffer(0, BufferK); SetIndexBuffer(1, BufferD); SetIndexBuffer(2, BufferK_Curr); SetIndexBuffer(3, BufferD_Curr); SetIndexBuffer(4, ArrowUpBuffer); SetIndexBuffer(5, ArrowDownBuffer); // Plotting styles for %K and %D lines, and their current values if (!HidePctK) { SetIndexStyle(0, DRAW_LINE, 0, 1, indicator_color1); SetIndexStyle(2, DRAW_LINE, 0, 1, indicator_color3); SetIndexLabel(0, "M1 %K Line"); SetIndexLabel(2, "M1 %K CurrBar"); } else { SetIndexStyle(0, DRAW_NONE); SetIndexStyle(2, DRAW_NONE); } if (!HidePctD) { SetIndexStyle(1, DRAW_LINE, 0, 1, indicator_color2); SetIndexStyle(3, DRAW_LINE, 0, 1, indicator_color4); SetIndexLabel(1, "M1 %D Signal"); SetIndexLabel(3, "M1 %D CurrBar"); } else { SetIndexStyle(1, DRAW_NONE); SetIndexStyle(3, DRAW_NONE); } // Adjusting plot drawing for the Arrows (Empty value initially to not display) SetIndexStyle(4, DRAW_ARROW, 0, 2, indicator_color5); SetIndexArrow(4, SYMBOL_ARROWUP); SetIndexEmptyValue(4, EMPTY_VALUE); SetIndexStyle(5, DRAW_ARROW, 0, 2, indicator_color6); SetIndexArrow(5, SYMBOL_ARROWDOWN); SetIndexEmptyValue(5, EMPTY_VALUE); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ int deinit() { // Add your deinitialization logic here, if any return(0); } ``` La prossima parte continua con il metodo `start()` dove avviene la logica di disegno delle frecce.
question:continua grazie
answer:Proseguiamo con il codice MQL4 per l'indicatore MT4 che aggiunge le frecce sugli incroci dello stocastico. Qui abbiamo la seconda parte che comprende il metodo `start()` e le funzioni ausiliarie. **Parte 2: Il metodo `start()` e le funzioni ausiliarie** ```mql4 //+------------------------------------------------------------------+ //| MTF Stochastic | //+------------------------------------------------------------------+ int start() { int i, counted_bars = IndicatorCounted(); if (counted_bars < 0) return(-1); // Usiamo Bars-1 per evitare errori out of range int look_back_bars = Bars - counted_bars - 1; int shift, prev_shift; double stochK, stochD, prevStochK, prevStochD; for (i = look_back_bars; i >= 0; i--) { // Calcola gli shift per il timeframe corrente if (TimeFrame >= Period()) { shift = i; prev_shift = shift + 1; } else { shift = iBarShift(NULL, TimeFrame, Time[i]); prev_shift = shift + 1; if (prev_shift >= iBars(NULL, TimeFrame)) prev_shift = shift; // Previene riferimenti invalidi } // Calcolo degli indici dello stocastico per il timeframe selezionato stochK = iStochastic(NULL, TimeFrame, KPeriod, DPeriod, Slowing, MAMethod, PriceField, MODE_MAIN, shift); stochD = iStochastic(NULL, TimeFrame, KPeriod, DPeriod, Slowing, MAMethod, PriceField, MODE_SIGNAL, shift); if (i != look_back_bars) { // Non calcolare per l'ultima barra (che è incompleta) prevStochK = iStochastic(NULL, TimeFrame, KPeriod, DPeriod, Slowing, MAMethod, PriceField, MODE_MAIN, prev_shift); prevStochD = iStochastic(NULL, TimeFrame, KPeriod, DPeriod, Slowing, MAMethod, PriceField, MODE_SIGNAL, prev_shift); // Verificare incroci dello stocastico e assegnare valori per le frecce if (prevStochK < prevStochD && stochK > stochD) { ArrowUpBuffer[i] = Low[i] - (4 * Point); ArrowDownBuffer[i] = EMPTY_VALUE; } else if (prevStochK > prevStochD && stochK < stochD) { ArrowDownBuffer[i] = High[i] + (4 * Point); ArrowUpBuffer[i] = EMPTY_VALUE; } else { ArrowUpBuffer[i] = EMPTY_VALUE; ArrowDownBuffer[i] = EMPTY_VALUE; } } // Assegnare i valori agli altri buffer BufferK[i] = stochK; BufferD[i] = stochD; if (shift == 0) { // Valori correnti solo per la barra attuale BufferK_Curr[i] = stochK; BufferD_Curr[i] = stochD; } else { BufferK_Curr[i] = EMPTY_VALUE; BufferD_Curr[i] = EMPTY_VALUE; } } return(0); } //+------------------------------------------------------------------+ //| Funzione ausiliaria per convertire il valore di TimeFrame in stringa | //+------------------------------------------------------------------+ string TimeFrameToStr(int period) { string period_str; switch (period) { case 1: period_str = "M1"; break; case 5: period_str = "M5"; break; case 15: period_str = "M15"; break; case 30: period_str = "M30"; break; case 60: period_str = "H1"; break; case 240: period_str = "H4"; break; case 1440: period_str = "D1"; break; case 10080: period_str = "W1"; break; case 43200: period_str = "MN1"; break; default: period_str = "Current"; break; } return period_str; } //+------------------------------------------------------------------+ //| Funzione ausiliaria per ottenere il TimeFrame superiore | //+------------------------------------------------------------------+ int GetHigherTimeFrame(int CurrentPeriod) { if (CurrentPeriod <= 1) return 5; if (CurrentPeriod <= 5) return 15; if (CurrentPeriod <= 15) return 30; if (CurrentPeriod <= 30) return 60; if (CurrentPeriod <= 60) return 240; if (CurrentPeriod <= 240) return 1440; if (CurrentPeriod <= 1440) return 10080; if (CurrentPeriod <= 10080) return 43200; return CurrentPeriod; // Nessun timeframe più alto } //+------------------------------------------------------------------+ ``` In questa parte del codice, la funzione `start()` calcola i valori dello stocastico e disegna le frecce basandosi sugli incroci tra la linea %K e la linea %D dello stocastico. Le frecce verranno posizionate sopra o sotto le barre a seconda della direzione dell'incrocio. Le funzioni `TimeFrameToStr()` e `GetHigherTimeFrame()` sono funzioni ausiliarie utilizzate nel resto del codice. Con questo, il corpo principale della tua funzione di indicatore dovrebbe essere impostato correttamente. Ricorda di eseguire test approfonditi sui dati storici prima di utilizzare questo indicatore in un ambiente di trading dal vivo per assicurarti che sia accurato e non abbia effetti collaterali indesiderati.