|
// ª"˜¨¨¯¨¨˜"ª¤(¯`*•.¸(¯`*•.¸ Value Chart¸.•*´¯)¸.•*´¯)¤ª"˜¨¨¯¨¨˜"ª |
// |
// Release v9.0 [ITA] |
// No DLL (Tutto il codice incluso) |
// |
// |
// |
//Cos'è: |
// |
//E' un indicatore che fà apparire le candele del prezzo in una |
//finestra separata, normalizzate attorno alla media |
//(media di default SMA 20). |
// |
//A che serve: |
// |
//Serve ad individuare la dispersione del prezzo rispetto alla sua |
//media, a calcolare la densità di probabilità di tale dispersione, |
//e a vedere graficamente in che area di probabilità (o livello di |
//dispersione) si trova il prezzo in un determinato momento, in |
//relazione ad un determinato periodo passato (default ultime |
//1000 barre, ovvero circa 1 mese sul 5min). |
// |
//Come si usa: |
// |
//Si possono usare i livelli di dispersione come livelli di |
//ipercomprato/ipervenduto, e il livello di media come livello di |
//normale attività del prezzo. Questo può darci inidicazioni |
//operative: short da un livello di ipercomprato con tp la mediana, |
//long da un livello ipervenduto con tp la mediana. |
//Il persistere del prezzo in un'area di dispersione esterna ci fà |
//presagire un ritorno alla media, ovvero un persistere del prezzo |
//in area di elevata densità ci fà presagire un'uscita temporanea in|
//una zona esterna a densità minore. |
//Il prezzo tende sempre alla zona con densità maggiore. |
//Per ulteriori indicazioni si rimanda oltre al forum anche alla |
//lettura del libro |
//"Dynamic Trading Indicators, Stendahl, David & Helweg, Mark". |
// |
//Funzioni: |
// |
//L'indicatore è in grado di plottare il grafico normalizzato, di |
//calcolarne la distribuzione e di renderla graficamente in due |
//modi: |
//con curva gaussiana a pallini verdi e valori analitici alla |
//destra della finestra (si deve settare |
//ShowDistribution = TRUE e ampliare |
//molto la finestra per vederla bene), e con linee orizzontali |
//corrispondenti a livelli sensibili calcolati dinamicamente sulla |
//distribuzione stessa. |
//L'indicatore si autoaggiorna in ogni timeframe e cross su cui |
//viene attacato. |
// |
// |
//Com'è strutturato il programma: |
// |
//Il codice si divide essenzialmente in 3 parti: |
// |
//1)la prima parte serve a calcolare i valori di |
//apertura, chiusura, high e low delle candele, sottraendo il |
//valore |
//della mediana così da averle normalizzate e pronte ad essere |
//disegnate. Il disegno è il frutto di un paio di arrangiamenti |
//"artistici", ovvero per chi volesse approfondire si è usato |
//6 buffer di disegno: 4 buffer disegnano ad istogramma i |
//rettangolini del corpo delle candele e delle shadow, in due |
//colori |
//a seconda che l'apertura sia minore della chiusura e viceversa |
//come le normali candlestick. |
//In pratica per ognuno dei due colori un buffer disegna il corpo |
//della candela e uno le shadow. |
//Si ottiene la situazione come sotto perchè l'istogramma parte |
//a 0 |
//per entrambi i buffer e resta visibile solo la metà alta o bassa |
//della candela... |
//Vedere ad esempio lo schema sotto: |
// |
// _______ High |
// Buffer2-> | |
// | _______ Close |
// 0 |
// Buffer1 -> 0 |
//------------------------------------ 0 |
// Buffer1 -> 0 |
// 0 ______ Close |
// | |
// Buffer2-> | ______ Low |
// |
//Per risolvere la situazione si usa altri due buffer "nascosti" |
//che vanno a disegnare la parte coperta della candela, ovvero |
//la parte della candela vicino allo 0. |
//Così il risultato ottico finale è quelo di una candela |
//con le shadow, anche se in realtà sono 6 rettangoli incastrati! |
//Vedi disegnino ingradito sotto: |
// |
// |
// Buffer1 ->00000 00000 |
// 00000 00000 |
// 00000 00000 |
// []|[] | |
// Buffer2 ->|[] ====>>> | |
// []|[] | |
// Buffer5 ->[]x[] |
// []x[] |
// Buffer6 ->x[] |
//------------------------- 0 ---------------------0 |
// |
//Unico problema resta quando la candela è a cavallo dello 0, |
//situazione in cui servirebbero 10 buffer per poterla disegnare |
//con gli istogrammi... |
//La soluzione è shiftare il frafico in alto, lontano dallo 0. |
//io ho aggiunto 1 ai valori finali delle candele, così che la |
//mediana diventa il valore 1. |
//in tal modo è possibile disegnare le candele di due colori |
//diversi, con le relative shadow, con solo 6 buffer. |
// |
//2) La seconda parte del programma si occupa del calcolo della |
//distribuzione del prezzo in un dato periodo ovvero per un dato |
//numero di barre (default 1000). |
//Per calcolare la distribuzione si và prima a prendere il massimo |
//e il minimmo nella chart normalizzata nel periodo dato. |
//Questo gap viene diviso in 100 parti uguali e per ogni 100 parti |
//si calcola al valore di dispersione corrispondente quante barre |
//raggiungono tale valore. |
//tale calcolo della distribuzione è così come descritto nel libro |
//di Stendahl e helweg, e differisce un pò dal considerare le sole |
//chiusure o valori medi della candela. L'ho adottato perchè lo |
//ritengo più realistico. |
//per una descrizione più dettagliata vi rimando alla lettura del |
//libro stesso, alla spiegazione del disegno del Price Profile. |
//Il risultato del calcolo della distribuzione così ottenuto è |
//inserito in un array di 100 elementi e può esere visualizzato |
//con una campana di pallini verdi alla destra del grafico e |
//relativi valori analitici. |
//Si ottiene così il Price Profile come teorizzato da Stendahl ed |
//helweg nel periodo d'interesse. |
// |
//3) La terza parte del codice è quella relativa al calcolo |
//dei livelli dinamici da plottare sulla Value Chart. |
//la campana del Price Profile viene divisa in due array, |
//uno per la parte positiva e uno per la parte negativa. Gli array |
//che si ottengono sono bidimensionali e contengono su una riga il |
//valore di dispersione, sull'altra il corrispondente livello dalla |
//mediana. |
//Si fà una rapida scansione degli array sia positivo che negativo |
//e alle percentuali d'interesse si traccia i livelli sul grafico, |
//che di conseguenza si aggiornano sempre dinamicamente. |
// |
// |
// More Info: |
// |
//
Forex Trading - Comunità Forex e trading online |
// @Forum->Discussioni sul Forex->Trend Fade Trading Room |
// |
// Author : LyVyO |
// |
// Join our Trading Room: Skype -> TFTchat |
// |
// |
// Software released under |
// GNU LESSER GENERAL PUBLIC LICENSE |
// Version 3, 29 June 2007 |
// |
//
http://www.gnu.org/licenses/lgpl-3.0.txt |
// |
// |
//+-----------------------------------------------------------------+
#property indicator_separate_window
#property copyright "Livio Rondoni"
#property link "mailto:
[email protected]"
string windowName = "--- Value Chart by LyVyO°ArT ---";
//+-----------------------------------------------------------------+
// Settings esterni |
//+-----------------------------------------------------------------+
// Perido della mediana su cui viene normalizzato il prezzo.
//Consiglio di lasciare a 20 che è la mediana standard delle bande
//di bolinger e la più significativa.
extern int BBPeriod = 20;
//Arco di tempo considerato espresso in numero di barre su cui
//effettuare il calcolo della distribuzione.
//Sul 5min 1000 barre sono circa 1 mese di trading.
extern int BellPeriod = 1000;
//Setting per fa apparire o meno la campana del Price Profile
extern bool ShowDistribution = FALSE;
//Setting per la spaziatura tra le righe del Price Profile.
extern int Passo = 12;
//Setting per la dimensione del carattere dei valori del Price Profile
extern int Carattere = 10;
//Seting delle percentuali dei livelli dinamici da disegnare sul grafico
extern int Level_1 = 50;
extern int Level_2 = 75;
extern int Level_3 = 90;
extern int Level_4 = 96;
extern int Level_5 = 99;
// Settings dei colori delle candele
//Il setting "Desktop" è quello che definisce il colore dei layer nascosti
//deve essere lo stesso colore dello sfondo della chart utilizzata
extern color ColorBarUp = Lime;
extern color ColorBarDown = FireBrick;
extern color ColorLineUp = Lime;
extern color ColorLineDown = FireBrick;
extern color Desktop = Black;
//----------------------Fine Settings Esterni ------------------------
//+-----------------------------------------------------------------+
// proprietà dei buffer di disegno |
//+-----------------------------------------------------------------+
#property indicator_buffers 6
//Colore delle candele. leggere la descrizione sopra per capire come
//cambiare i valori. I buffer nascosti sono di default neri, se usate
//un background diverso adeguare il colore 3 e 6.
#property indicator_color1 Lime
#property indicator_color2 FireBrick
#property indicator_color3 Black
#property indicator_color4 Lime
#property indicator_color5 FireBrick
#property indicator_color6 Black
//larghezza delle candele. Anche Questa si può adattare se si una
//zoom particolari nel proprio template.
#property indicator_width1 4
#property indicator_width2 4
#property indicator_width3 4
#property indicator_width4 1
#property indicator_width5 1
#property indicator_width6 1
//----------------------Fine Definizione buffer ----------------------
//---- buffers
double ExtMapBuffer1[];//
double ExtMapBuffer2[];//
double ExtMapBuffer3[];//
double ExtMapBuffer4[];//
double ExtMapBuffer5[];//
double ExtMapBuffer6[];//
int ExtCountedBars=0;
//----
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//|------------------------------------------------------------------|
int init()
{
//+-----------------------------------------------------------------+
// definizione del disegno delle candele |
//+-----------------------------------------------------------------+
IndicatorShortName(windowName);
SetIndexStyle(0,DRAW_HISTOGRAM, 0, 3, ColorBarUp);
SetIndexBuffer(0, ExtMapBuffer1);
SetIndexLabel(0,"Body Up");
SetIndexStyle(1,DRAW_HISTOGRAM, 0, 3, ColorBarDown);
SetIndexBuffer(1, ExtMapBuffer2);
SetIndexLabel(1,"Body Down");
SetIndexStyle(2,DRAW_HISTOGRAM, 0, 3, Desktop);
SetIndexBuffer(2, ExtMapBuffer3);
SetIndexLabel(2,"Hidden Body");
SetIndexStyle(3,DRAW_HISTOGRAM, 0, 1, ColorLineUp);
SetIndexBuffer(3, ExtMapBuffer4);
SetIndexLabel(3,"Shadow Up");
SetIndexStyle(4,DRAW_HISTOGRAM, 0, 1, ColorLineDown);
SetIndexBuffer(4, ExtMapBuffer5);
SetIndexLabel(4,"Shadow Down");
SetIndexStyle(5,DRAW_HISTOGRAM, 0, 1, Desktop);
SetIndexBuffer(5, ExtMapBuffer6);
SetIndexLabel(5,"Hidden Shadow");
//----
SetIndexDrawBegin(0,1);
SetIndexDrawBegin(1,1);
SetIndexDrawBegin(2,1);
SetIndexDrawBegin(3,1);
SetIndexDrawBegin(4,1);
SetIndexDrawBegin(5,1);
//---- indicator buffers mapping
SetIndexBuffer(0,ExtMapBuffer1);
SetIndexBuffer(1,ExtMapBuffer2);
SetIndexBuffer(2,ExtMapBuffer3);
SetIndexBuffer(3,ExtMapBuffer4);
SetIndexBuffer(4,ExtMapBuffer5);
SetIndexBuffer(5,ExtMapBuffer6);
//---- initialization done
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
ObjectsDeleteAll();
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
//+-----------------------------------------------------------------+
// Inizio 1°Parte del programma |
//+-----------------------------------------------------------------+
//La prima parte serve a calcolare i valori di
//apertura, chiusura, high e low delle candele, sottraendo il
//valore della mediana così da averle normalizzate e pronte
//ad essere disegnate.
//definizione variabili valori candele
double haOpen, haHigh, haLow, haClose;
//Calcolo delle barre presenti sul grafico
//su cui andremo a calcolare i valori delle canadele
if(Bars<=10) return(0);
ExtCountedBars=IndicatorCounted();
//---- check for possible errors
if (ExtCountedBars<0) return(-1);
//---- last counted bar will be recounted
if (ExtCountedBars>0) ExtCountedBars--;
//inizializzatore del puntatore alla candela da calcolare
int pos=Bars-ExtCountedBars-1;
//Inizio del ciclo di calcolo delle candele
//Per ogni candela nel grafico...
while(pos>=0)
{
//...si calcola il valore della media mobile
//per il valore BBPeriod selezionato
double MA = iMA(NULL,0,BBPeriod,0,MODE_SMA,PRICE_CLOSE,pos);
//...si calcola il valore della chiusura , apertura, high e low
//della candela sottraendo il valore della mediana,
//più lo shift in alto di 1 necessario per il disegno con 6 buffer
//come spiegato in alto
haOpen = Open[pos] - MA +1;
haClose = Close[pos] -MA +1;
haHigh = High[pos] -MA +1;
haLow = Low[pos] -MA +1;
//...si inizializzano gli array di buffer e si preparano ad accogliere
//i valori appena calcolati
ExtMapBuffer1[pos]=EMPTY_VALUE;
ExtMapBuffer2[pos]=EMPTY_VALUE;
ExtMapBuffer3[pos]=EMPTY_VALUE;
ExtMapBuffer4[pos]=EMPTY_VALUE;
ExtMapBuffer5[pos]=EMPTY_VALUE;
ExtMapBuffer6[pos]=EMPTY_VALUE;
//...si sistemano i valori negli array di buffer,
//facendo attenzione che se la cadela è positiva quindi apertura minore della chiusura
//il buffer "close" andrà plottato Lime, e quello "open" sarà il nostro buffer nascosto
//nero, come spiegato.
//Al contrario, se la candela è negativa sarà il buffer "open" che sarà più in alto e quindi
//visibile, e dovrà essere Rosso, mentre la chiusura sarà il livello a cui arriverà il buffer nero
//a nascondere l'istogramma rosso.
//fatto questo in ogni caso si sistema l'ultimo buffer nascosto "6" sempre al valore "low"
//per ogni candela.
//Spero di essere stato chiaro

if (haOpen<haClose)
{
ExtMapBuffer1[pos]=haClose;
ExtMapBuffer3[pos]=haOpen;
ExtMapBuffer4[pos]=haHigh;
}
else
{
ExtMapBuffer2[pos]=haOpen;
ExtMapBuffer3[pos]=haClose;
ExtMapBuffer5[pos]=haHigh;
}
ExtMapBuffer6[pos] = haLow;
//...una volta sistemati i valori negli arrai si decrementa il puntatore
//per cambiare candela verso una più recente e si ricomincia il ciclo.
pos--;
}
//i valori messi negli array con questo ciclo sono poi letti nei buffer
//e si aggiornano ad ogni tick, disegnando le candele normalizzate.
//------------------------ Fine 1°Parte --------------------------
//+-----------------------------------------------------------------+
// Inizio 2°Parte del programma |
//+-----------------------------------------------------------------+
//2) La seconda parte del programma si occupa del calcolo della
//distribuzione del prezzo in un dato periodo ovvero per un dato
//numero di barre (default 1000).
//Per calcolare la distribuzione si và prima a prendere il massimo
//e il minimmo nella chart normalizzata nel periodo dato.
//Questo gap viene diviso in 100 parti uguali e per ogni 100 parti
//si calcola al valore di dispersione corrispondente quante barre
//raggiungono tale valore.
//Il risultato del calcolo della distribuzione così ottenuto è
//inserito in un array di 100 elementi e può esere visualizzato
//con una campana di pallini verdi alla destra del grafico e
//relativi valori analitici.
//Per il calcolo degli estremi ho voluto ripetere la generazione di due array,
//uno per i valori "High" e uno per i valori "Low" delle candele
double High_Array[];
double Low_Array[];
//Gli array hanno stessa dimensione del periodo cosiderato per il
//calcolo della distribuzione definito con il parametro esterno "BellPeriod"
ArrayResize(High_Array,BellPeriod);
ArrayResize(Low_Array,BellPeriod);
//inseriamo per ogni candela del periodo considerato i valori High e Low
//nei rispettivi array, allo stesso modo che avevamo visto in precedenza
//per l'inserimento dei valori dei buffer, ovvero sottraendo il valore della mediana
//e inserendo o shift di 1
for(int i=0;i<=BellPeriod;i++)
{
double SMA = iMA(NULL,0,BBPeriod,0,MODE_SMA,PRICE_CLOSE,i);
High_Array
= High - SMA +1;
Low_Array= Low - SMA +1;
}
//Quindi andiamo a cercare il valore rispettivamente massimo e minimo dei due arrai
//e lo mettiamo nelle variabili "Max" e "Min" che saranno gli estremi raggiunti
//dal prezzo nel periodo considerato
int MaxPos = ArrayMaximum(High_Array);
double Max = High_Array[MaxPos];
int MinPos = ArrayMinimum(Low_Array);
double Min = Low_Array[MinPos];
//ora che abbiamo gli estremi andiamo a calcolare la campana (bell in inglese)
//di distribuzione con il procedimento accennato sopra.
//prima cosa creiamo un bell'array da 100 posizioni
//(101 in realtà perchè c'è anche lo 0 ma noi per comodità non lo considereremo)
//e lo inizializziamo a 0.
int Bell_Array[100];
ArrayInitialize(Bell_Array,0);
//fatto questo creiamo un secondo array sempre dimensione 100
//che andrà a raccogliere i dati della posizione rispetto alla mediana del prezzo,
//per tutti i punti della campana del Price Profile
double Position_Array[100];
ArrayInitialize(Position_Array,0);
//Ora che abbiamo i nostri array dobbiamo adare a riempirli coi dati che serviranno
//per costruire la campana.
//Quindi per ogni punto della curva che vogliamo creare dobbiamo avere due coordinate:
//il valore della densità di probabilità corrispondente (la coordinata x, messa in Bell_Array)
//e il valore della distanza di tale punto dalla mediana (la coordinata Y, messa in Position_Array )
//Per inserire tutti i valori andiamo a costruire il ciclo seguenteche recita così:
//Per ognuno dei 100 punti in cui decidiamo di dividere la distanza
//tra il max e il min individuati precedentemente nel periodo considerato...
for(int n=1;n<=100;n++)
{
//...la coordinata Y da inserire è il punto stesso considerato, ossia uguale al minimo più
//lo scostamento in alto di 1/100 * n, fino al max.
Position_Array[n] = Min + (( (Max-Min) / 100 ) * n);
//...e per ognuna delle coordinate Y trovate, per tutte le barre considerate nel periodo
//settato col parametro "BellPeriod" bisogna andare a vedere se tale coordinata è raggiunta dal prezzo,
//ovvero se tale livello è compreso tra il min e il max della candela considerata.
//lo facciamo con il ciclo FOR e ponendo la condizione IF come sotto:
for( i=0;i<=BellPeriod;i++)
{
if(Position_Array[n] <= High_Array && Position_Array[n] >= Low_Array)
{
//se il prezzo è compreso nella candela considerata, si incrementa di 1 il valore corrispondente
//della campana del Price profile.
Bell_Array[n]= Bell_Array[n]+1;
}
}
}
//Fatto questo abbiamo ottenuto i due array con le coordinate X e Y per costruire la curva
//del Price Profile, e possiao riutilizzarli per andare a studiare la distriuzione del prezzo.
//Riassumendo gli array sono:
//
//Bell_Array[] => contiene i valori, contati, della distribuzione del prezzo
// per ogni barra nel periodo considerato, in 100 intervalli tra il
// min e il max di periodo.
//
//Position_Array[] => contiene la distanza a partire dal min di periodo dei corrispondenti
// punti
//
//Esempio: se il livello 1,650 è stato raggiunto 100 volte nelle ultime 1000 barre,
// Bell_Array conterrà il valore 100, e Position_Array conterrà il valore 1,650.
//
//
//Ecco anche un disegnino per capire meglio:
//
// x |y
// x |
// x |
// x------------|< Position_Array
// | x |
// | x |
// _________|___x________|
// x ^ 0
// Bell_Array
//
//Per ultimo si disegna la campana...
//
//Per ora il disegno è un pò grezzo..prendetelo per come è, tanto a livello operativo non è molto utile...
//Il disegno è fatto con 50 punti per praticità anzichè 100, ma volendo si può fare anche on 1000 punti
//cambiando i parametri...
//il disegno al contrario della value chart ha una grandezza fissa per cui se volete
//vederlo bene dovrete adattare la finetra alla grandezza del grafico risultante.
//Il setting esterno Passo definisce il passo tra le righe.
//Il setting Carattere invece la grandezza dei caratteri.
//Il price profile può essere visualizzato o meno con il parametro "ShowDistribution"
int Win_ind = WindowFind(windowName);
if(ShowDistribution)
{
for(n=0;n<=50;n++)
{
ObjectCreate("DIST1"+n,OBJ_LABEL,Win_ind,0,0);
ObjectSetText("DIST1"+n,""+Bell_Array[100 - n*2]+" -- "+DoubleToStr(Position_Array[100 - n*2],5)+"",8,"",White);
ObjectSet("DIST1"+n,OBJPROP_CORNER, 1);
ObjectSet("DIST1"+n,OBJPROP_XDISTANCE,10);
ObjectSet("DIST1"+n,OBJPROP_YDISTANCE,50 + (Passo*n));
}
for(n=0;n<=50;n++)
{
ObjectCreate("DIST2"+n,OBJ_LABEL,Win_ind,0,0,0,0);
ObjectSetText("DIST2"+n,CharToStr(159),Carattere,"Wingdings",Lime);
ObjectSet("DIST2"+n, OBJPROP_CORNER, 1);
ObjectSet("DIST2"+n, OBJPROP_XDISTANCE, 100 + Bell_Array[100 - n*2] );
ObjectSet("DIST2"+n, OBJPROP_YDISTANCE, 50+(Passo*n) );
}
}
//Se il parametro "ShowDistribution" è settato a 0, si deve cancellare un'eventuale
//Price Profile disegnato in precedenza.
//Per faro si scansiona tutti gli oggetti presenti nella chart
//che abbiamo il prefisso "DIST" cioè tutti quelli disegnati nel ciclo sopra,
//e se si trovano si cancellano.
if(ShowDistribution == FALSE)
{
for(n=50;n>=0;n--)
{
ObjectDelete("DIST1"+n);
ObjectDelete("DIST2"+n);
}
string NameOfObject = "DIST";
for( i = ObjectsTotal() - 1; i >= 0; i--)
{
string label = ObjectName(i);
if(StringSubstr(label, 0, StringLen(NameOfObject)) != NameOfObject)
continue;
ObjectDelete(label);
}
}
//------------------------ Fine 2°Parte --------------------------
//+-----------------------------------------------------------------+
// Inizio 3°Parte del programma |
//+-----------------------------------------------------------------+
//3) La terza parte del codice è quella relativa al calcolo
//dei livelli dinamici da plottare sulla Value Chart.
//la campana del Price Profile viene divisa in due array,
//uno per la parte positiva e uno per la parte negativa. Gli array
//che si ottengono sono bidimensionali e contengono su una riga il
//valore di dispersione, sull'altra il corrispondente livello dalla
//mediana.
//Si fà una rapida scansione degli array sia positivo che negativo
//e alle percentuali d'interesse si traccia i livelli sul grafico,
//che di conseguenza si aggiornano sempre dinamicamente.
//Allora cominciamo con l'andare a vedere quanti valori
//abbiamo in zona positiva e quanti in zona negativa.
//Verrebbe da dire 50 e 50 ma non è sempre così, in trend la campana
//di distribuzone si allunga da una parte e si accorcia dall'altra
//e le code rchiedono più o meno punti per essere disegnate, per cui
//il centro stesso di oscillazione, la mediana, è dinamico.
//Quindi la quantità di punti in zona positiva e negativa cambia continuamente
//e già fornisce un'indicazione sull'attività del prezzo, e quindi
//deve essere aggiornato ad ogni barra.
//Lo facciamo con il ciclo sotto.
//questi sono i valori che indicano la quantità di punti in zona positiva e negativa,
//ovvero la dimensione dei due array che andremo a costruire.
int SizePos = 0;
int SizeNeg = 0;
//e questi sono i valori che saranno pari alla somma di tutti i valori
//della distribuzione positivi e negativi, e che useremo dopo Per
//calcolare le percentuali.
double SumPos =0;
double SumNeg =0;
//iniziamo il cclo per calcolare questi quattro valori:
//per tutti i livelli Y della campana, se il livello è positivo incrementa la
//dimensione dell'array positivo di 1 e somma il valore di distribuzione corrispondente
//stessa cosa per i valori dei livelli negativi.
for( n=1;n<=100;n++)
{
if(Position_Array[n] >= 1 )
{
SizePos = SizePos + 1;
SumPos = SumPos + Bell_Array[n];
}
if(Position_Array[n] < 1 )
{
SizeNeg = SizeNeg + 1;
SumNeg = SumNeg + Bell_Array[n];
}
}
//Ecco che abbiamo ottenuto i valori che desideravamo, adesso usiamoli
//per costruire gli array che stavamo cercando come detto sopra.
//Anzituttto prepariamo i due array bidimensionali,
//uno per la campana positiva e uno per la campana negativa.
//I due array sono una struttura dinamica che dovrà accogliere i valori delle coordinate
//dei vari punti della campana, come nello schema sotto:
//
//
// __1____2____________Sizepos___
// PosBell_Struct/ \
// 0 | +x1 +x2 ....... +x[SizePos] |
// ------------------------------|
// 1 | +y1 +y2 ....... +y[SizePos] |
// \______________________________/
//
// __1____2____________Sizeneg___
// NegBell_Struct/ \
// 0 | -x1 -x2 ....... -x[SizeNeg] |
// ------------------------------|
// 1 | -y1 -y2 ....... -y[SizeNeg] |
// \______________________________/
//
//
//I valori sono inseriti così come dal disegno sotto:
//
// +X1 ... +X[SizePos]
// ________________
// |
// x|+Y[SizePos]
// x |
// x |
// x |+Y3
// x |+Y2
// x |+Y1
// -------------------0
// x |-Y1
// x |-Y2
// x |-Y3
// x |
// x |
// x|-Y[SizeNeg]
// _______________|
// -X1 ... -X[SizeNeg]
//
//
//Ed eccoli qua, i due array di struttura:
double PosBell_Struct[2][100];
double NegBell_Struct[2][100];
//Andiamo a riempirli con i valori come descritto:
for(i=0;i<=SizePos;i++)
{
PosBell_Struct[0]=Bell_Array[SizeNeg+i];
PosBell_Struct[1]=Position_Array[SizeNeg+i];
}
for(i=0;i<=SizeNeg;i++)
{
NegBell_Struct[0]=Bell_Array[SizeNeg-i-1];
NegBell_Struct[1]=Position_Array[SizeNeg-i-1];
}
//Benissimo, adesso abbiamo le due strutture per la parte di campana positiva e negativa
//e possiamo iniziare ad usarle per il calcolo dei livelli dinamici.
//Ci interessa sapere ad un dato livello Y, la percentuale di prezzo che resta inclusa
//tra lo O e il livello stesso.
//Quindi andremo da un minimo di 0 a livello 0, e ad un massimo del 100% a livello Max e Min
//rispettivamente per la zona positiva e negativa.
//Quello che faremo sarà scansionare ogni livello dei due array, partendo dal livello 0,
//andando a calcolare per ogni livello la percentuale sottesa.
//Quando questa sarà ad un livello prestabilito, prenderemo tale coordinata Y e la useremo Per
//tracciare la linea del livello.
//Questo motivo, il dover effettuare le due scansioni in zona positiva e negativa dal centro al'esterno,
//è il motivo per il quale abbiamo costruito le due strutture come descritto, coi i valori
//in fila dal centro all'esterno.
//Si procede come sotto:
//Prima di tutto rimuoviamo i livelli tracciati precedentemente per rinnovarli...
ObjectsDeleteAll(Win_ind, OBJ_HLINE);
//...quindi iniziamo la scansione del lato positivo della campana,
//poi faremo la stessa cosa per quello negativo.
//Quindi dal centro (0) fino all'estremo (SizePos):...
for(i=0;i<=SizePos;i++)
{
//...calcoliamo la percentuale di prezzo sotteso a tale livello, sommando
//i valori X della struttura fino al valore attuale, quindi dividendo per la somma totale
//che avevamo trovato in precedenza e dividendo per 100...
double PercSum=0;
for(n=0;n<=i;n++) //NOTA: n và da 0 (centro campana) a i (valore attuale di scansione)
{
PercSum = PercSum + PosBell_Struct[0][n];
}
if(SumPos != 0) { double Perc = (PercSum / SumPos) *100; }
//...trovata la percentuale "Perc" il gioco è già fatto, adesso basta distinguere i vari casi
//e disegnare i vari livelli!
//Commento il seguente ciclo di disegno poi i sestanti sono tutti identici.
//------------------Ciclo di disegno livello 1--------------------------
if(Perc >= Level_1) //Se la percentuale è >= del livello 1
{
if(ObjectFind("50PercLevel") == -1) //Se la linea non è mai stata disegnata prima
{
ObjectCreate("50PercLevel",OBJ_HLINE,Win_ind,0,PosBell_Struct[1]); //crea oggetto alla coordinata corrente
ObjectSet("50PercLevel",OBJPROP_COLOR,ForestGreen); //Set colore
ObjectSet("50PercLevel",OBJPROP_STYLE,STYLE_DASH); //Set stile
}
double Y_50Pos = ObjectGet("50PercLevel",OBJPROP_PRICE1); //Copia il valore della coordinata Y corrispondente,
} //ci servirà poi per disegnare il numero di % del livello
//------------------Ciclo di disegno livello 2--------------------------
if(Perc >= Level_2)
{
if(ObjectFind("75PercLevel") == -1)
{
ObjectCreate("75PercLevel",OBJ_HLINE,Win_ind,0,PosBell_Struct[1]);
ObjectSet("75PercLevel",OBJPROP_COLOR,ForestGreen);
ObjectSet("75PercLevel",OBJPROP_STYLE,STYLE_DASH);
}
double Y_75Pos = ObjectGet("75PercLevel",OBJPROP_PRICE1);
}
//------------------Ciclo di disegno livello 3--------------------------
if(Perc >= Level_3)
{
if(ObjectFind("90PercLevel") == -1)
{
ObjectCreate("90PercLevel",OBJ_HLINE,Win_ind,0,PosBell_Struct[1]);
ObjectSet("90PercLevel",OBJPROP_COLOR,ForestGreen);
}
double Y_90Pos = ObjectGet("90PercLevel",OBJPROP_PRICE1);
}
//------------------Ciclo di disegno livello 4--------------------------
if(Perc >= Level_4)
{
if(ObjectFind("96PercLevel") == -1)
{
ObjectCreate("96PercLevel",OBJ_HLINE,Win_ind,0,PosBell_Struct[1]);
ObjectSet("96PercLevel",OBJPROP_COLOR,ForestGreen);
ObjectSet("96PercLevel",OBJPROP_WIDTH,2);
}
double Y_96Pos = ObjectGet("96PercLevel",OBJPROP_PRICE1);
}
//------------------Ciclo di disegno livello 5--------------------------
if(Perc >= Level_5)
{
if(ObjectFind("99PercLevel") == -1)
{
ObjectCreate("99PercLevel",OBJ_HLINE,Win_ind,0,PosBell_Struct[1]);
ObjectSet("99PercLevel",OBJPROP_COLOR,ForestGreen);
ObjectSet("99PercLevel",OBJPROP_WIDTH,3);
}
double Y_99Pos = ObjectGet("99PercLevel",OBJPROP_PRICE1);
}
//------------------Fine ciclo di disegno------------------------------
}
//Fine scansione campana positiva
//Inizio scansione campana negativa, allo stesso modo:
for(i=0;i<=SizeNeg;i++)
{
//calcolo percentuale...
PercSum=0;
for(n=0;n<=i;n++)
{
PercSum = PercSum + NegBell_Struct[0][n];
}
if(SumNeg != 0) { Perc = (PercSum / SumNeg) *100; }
//------------------Ciclo di disegno livello 1--------------------------
if(Perc >= Level_1)
{
if(ObjectFind("Minus50PercLevel") == -1)
{
ObjectCreate("Minus50PercLevel",OBJ_HLINE,Win_ind,0,NegBell_Struct[1]);
ObjectSet("Minus50PercLevel",OBJPROP_COLOR,FireBrick);
ObjectSet("Minus50PercLevel",OBJPROP_STYLE,STYLE_DASH);
}
double Y_50Neg = ObjectGet("Minus50PercLevel",OBJPROP_PRICE1);
}
//------------------Ciclo di disegno livello 2--------------------------
if(Perc >= Level_2)
{
if(ObjectFind("Minus75PercLevel") == -1)
{
ObjectCreate("Minus75PercLevel",OBJ_HLINE,Win_ind,0,NegBell_Struct[1]);
ObjectSet("Minus75PercLevel",OBJPROP_COLOR,FireBrick);
ObjectSet("Minus75PercLevel",OBJPROP_STYLE,STYLE_DASH);
}
double Y_75Neg = ObjectGet("Minus75PercLevel",OBJPROP_PRICE1);
}
//------------------Ciclo di disegno livello 3--------------------------
if(Perc >= Level_3)
{
if(ObjectFind("Minus90PercLevel") == -1)
{
ObjectCreate("Minus90PercLevel",OBJ_HLINE,Win_ind,0,NegBell_Struct[1]);
ObjectSet("Minus90PercLevel",OBJPROP_COLOR,FireBrick);
}
double Y_90Neg = ObjectGet("Minus90PercLevel",OBJPROP_PRICE1);
}
//------------------Ciclo di disegno livello 4--------------------------
if(Perc >= Level_4)
{
if(ObjectFind("Minus96PercLevel") == -1)
{
ObjectCreate("Minus96PercLevel",OBJ_HLINE,Win_ind,0,NegBell_Struct[1]);
ObjectSet("Minus96PercLevel",OBJPROP_COLOR,FireBrick);
ObjectSet("Minus96PercLevel",OBJPROP_WIDTH,2);
}
double Y_96Neg = ObjectGet("Minus96PercLevel",OBJPROP_PRICE1);
}
//------------------Ciclo di disegno livello 5--------------------------
if(Perc >= Level_5)
{
if(ObjectFind("Minus99PercLevel") == -1)
{
ObjectCreate("Minus99PercLevel",OBJ_HLINE,Win_ind,0,NegBell_Struct[1]);
ObjectSet("Minus99PercLevel",OBJPROP_COLOR,FireBrick);
ObjectSet("Minus99PercLevel",OBJPROP_WIDTH,3);
}
double Y_99Neg = ObjectGet("Minus99PercLevel",OBJPROP_PRICE1);
}
//------------------Fine ciclo di disegno------------------------------
}
//Fine scansione campana negativa
//Qualche altra riga di codice per il disegno dei livelli Max, Min e 0...
//Linea 0
ObjectCreate("0Line",OBJ_HLINE,Win_ind,0,1);
ObjectSet("0Line",OBJPROP_COLOR,White);
//Max
ObjectCreate("HighLine",OBJ_HLINE,Win_ind,0,Max);
ObjectSet("highLine",OBJPROP_COLOR,LimeGreen);
ObjectSet("highLine",OBJPROP_WIDTH,4);
//Min
ObjectCreate("LowLine",OBJ_HLINE,Win_ind,0,Min);
ObjectSet("LowLine",OBJPROP_COLOR,Red);
ObjectSet("LowLine",OBJPROP_WIDTH,4);
//E infine il disegno dei cartellini con il valore di percentuale relativa ai vari livelli...
//Si cancella prima i vecchi cartelini...
string TheObjectName = "SIGNAL";
for( i = ObjectsTotal() - 1; i >= 0; i--)
{
label = ObjectName(i);
if(StringSubstr(label, 0, StringLen(TheObjectName)) != TheObjectName)
continue;
ObjectDelete(label);
}
//Si inizia a scrivere quelli dello 0, del Max e del Min...
//--------------------------Disegno Cartellino 0 -----------------------
if(ObjectFind("SIGNAL0") != 0)
{
ObjectCreate("SIGNAL0", OBJ_TEXT, Win_ind, Time[0], 1);
ObjectSetText("SIGNAL0"," 0%",11,"Arial Black",White);
}
else
{
ObjectMove("SIGNAL0", Win_ind, Time[0], 1);
}
//--------------------------Disegno Cartellino Max -----------------------
if(ObjectFind("SIGNAL1") != 0)
{
ObjectCreate("SIGNAL1", OBJ_TEXT, Win_ind, Time[0], Max);
ObjectSetText("SIGNAL1"," +100%",11,"Arial Black",Lime);
}
else
{
ObjectMove("SIGNAL1", Win_ind, Time[0], Max);
}
//--------------------------Disegno Cartellino Min -----------------------
if(ObjectFind("SIGNAL2") != 0)
{
ObjectCreate("SIGNAL2", OBJ_TEXT, Win_ind, Time[0], Min);
ObjectSetText("SIGNAL2"," -100%",11,"Arial Black",Red);
}
else
{
ObjectMove("SIGNAL2", Win_ind, Time[0], Min);
}
//...e poi si disegna quelli dei livelli.
//------------------------ Disegno Cartellino livello 5 -----------------------
if(ObjectFind("SIGNAL3") != 0)
{
ObjectCreate("SIGNAL3", OBJ_TEXT, Win_ind, Time[0], Y_99Pos);
ObjectSetText("SIGNAL3"," +"+Level_5+"%",8,"Arial Black",Lime);
}
else
{
ObjectMove("SIGNAL3", Win_ind, Time[0], Y_99Pos);
}
//------------------------ Disegno Cartellino livello 4 -----------------------
if(ObjectFind("SIGNAL4") != 0)
{
ObjectCreate("SIGNAL4", OBJ_TEXT, Win_ind, Time[0], Y_96Pos);
ObjectSetText("SIGNAL4"," +"+Level_4+"%",8,"Arial Black",Lime);
}
else
{
ObjectMove("SIGNAL4", Win_ind, Time[0], Y_96Pos);
}
//------------------------ Disegno Cartellino livello 3 -----------------------
if(ObjectFind("SIGNAL5") != 0)
{
ObjectCreate("SIGNAL5", OBJ_TEXT, Win_ind, Time[0], Y_90Pos);
ObjectSetText("SIGNAL5"," +"+Level_3+"%",8,"Arial Black",Lime);
}
else
{
ObjectMove("SIGNAL5", Win_ind, Time[0], Min);
}
//------------------------ Disegno Cartellino livello 2 -----------------------
if(ObjectFind("SIGNAL6") != 0)
{
ObjectCreate("SIGNAL6", OBJ_TEXT, Win_ind, Time[0], Y_75Pos);
ObjectSetText("SIGNAL6"," +"+Level_2+"%",8,"Arial Black",Lime);
}
else
{
ObjectMove("SIGNAL6", Win_ind, Time[0], Y_90Pos);
}
//------------------------ Disegno Cartellino livello 1 -----------------------
if(ObjectFind("SIGNAL7") != 0)
{
ObjectCreate("SIGNAL7", OBJ_TEXT, Win_ind, Time[0], Y_50Pos);
ObjectSetText("SIGNAL7"," +"+Level_1+"%",8,"Arial Black",Lime);
}
else
{
ObjectMove("SIGNAL7", Win_ind, Time[0], Y_50Pos);
}
//------------------------ Disegno Cartellino livello 5 -----------------------
if(ObjectFind("SIGNAL8") != 0)
{
ObjectCreate("SIGNAL8", OBJ_TEXT, Win_ind, Time[0], Y_99Neg);
ObjectSetText("SIGNAL8"," -"+Level_5+"%",8,"Arial Black",Red);
}
else
{
ObjectMove("SIGNAL8", Win_ind, Time[0], Y_99Neg);
}
//------------------------ Disegno Cartellino livello 4 -----------------------
if(ObjectFind("SIGNAL9") != 0)
{
ObjectCreate("SIGNAL9", OBJ_TEXT, Win_ind, Time[0], Y_96Neg);
ObjectSetText("SIGNAL9"," -"+Level_4+"%",8,"Arial Black",Red);
}
else
{
ObjectMove("SIGNAL9", Win_ind, Time[0], Y_96Neg);
}
//------------------------ Disegno Cartellino livello 3 -----------------------
if(ObjectFind("SIGNAL10") != 0)
{
ObjectCreate("SIGNAL10", OBJ_TEXT, Win_ind, Time[0], Y_90Neg);
ObjectSetText("SIGNAL10"," -"+Level_3+"%",8,"Arial Black",Red);
}
else
{
ObjectMove("SIGNAL10", Win_ind, Time[0], Min);
}
//------------------------ Disegno Cartellino livello 2 -----------------------
if(ObjectFind("SIGNAL11") != 0)
{
ObjectCreate("SIGNAL11", OBJ_TEXT, Win_ind, Time[0], Y_75Neg);
ObjectSetText("SIGNAL11"," -"+Level_2+"%",8,"Arial Black",Red);
}
else
{
ObjectMove("SIGNAL11", Win_ind, Time[0], Y_90Neg);
}
//------------------------ Disegno Cartellino livello 1 -----------------------
if(ObjectFind("SIGNAL12") != 0)
{
ObjectCreate("SIGNAL12", OBJ_TEXT, Win_ind, Time[0], Y_50Neg);
ObjectSetText("SIGNAL12"," -"+Level_1+"%",8,"Arial Black",Red);
}
else
{
ObjectMove("SIGNAL12", Win_ind, Time[0], Y_50Neg);
}
WindowRedraw();
//+------------------------ FINE DISEGNO --------------------------------------+
return(0);
}
//+------------------------------------------------------------------+
// |
// FINE DEL PROGRAMMA |
// |
// BUON DIVERTIMENTO!
|
// |
//+------------------------------------------------------------------+
buongiorno a tutti, chiedo cortesemente se qualcuno è in grado di tradurre questa codifica per la meta in prorealtime, si tratta di una versione di value chart molto ne fatta, vi mostro l'immagine del risultato
grazie