Benvenuto Ospite Cerca | Topic Attivi | Utenti | | Log In | Registra

Formula VBA Opzioni
guayas
Inviato: Friday, September 02, 2005 6:39:58 PM
Rank: Member

Iscritto dal : 12/20/2001
Posts: 0
Salve a tutti ! Ho scritto questa formula in VBA ( in modo molto elementare, forse ridondante, visto che sto muovendo davvero in primi passi in questo campo, sto leggendo Walkenbach ) che calcola il rapporto tra la somma delle variazioni positive e quelle negative del prezzo di un'azione rispetto al prezzo del giorno prima, e poi normalizza il rapporto tra 0 e 100 ( Per chi conosce l'analisi tecnica è l'RSI ) :

Function RSI(List)

Dim Cell As Variant
SumPos = 0
SumNeg = 0
For Each Cell In List
If Cell(1, 1).Value )= Cell(1, 1).Offset(-1, 0).Value Then
SumPos = SumPos + Cell(1, 1).Value - Cell(1, 1).Offset(-1, 0).Value
Else
If Cell(1, 1).Value ( Cell(1, 1).Offset(-1, 0).Value Then
SumNeg = SumNeg + (Cell(1, 1).Value - Cell(1, 1).Offset(-1, 0).Value)
End If
End If
Next Cell
If SumNeg = 0 Then
RSI = 100
Else
If SumNeg < 0 Then
RSI = 100 - (100 / (1 + (SumPos / (SumNeg * -1))))
End If
End If
End Function

Funziona, e ovviamente sul foglio di lavoro devo, per esempio, scrivere =RSI(A1:A14), ovvero l'intervallo A1:A14 sarebbe l'argomento "list" della funzione. Io invece vorrei che l'argomento fosse solo la lunghezza dell'intervallo dei dati e la colonna dove si trovano. cioè qualcosa come : =RSI(-1,14), ovvero la formula fosse calcolata sui dati presenti nella colonna a sinistra rispetto alla cella che contiene la formula, per 14 celle a partire dalla stessa riga della formula indietro. O ancora meglio =RSI(g1,g2) assumendo che i due valori -1 e 14 siano iscritti in queste due celle. Ho provato a togliere il range ( list ) dagli argomenti della funzione, e a definirlo all'interno della funzione, con offset, range, cells ( di cui alcuni parametri sono appunto gli argomenti della funzione, colonna e lunghezza )...ma non ne sono venuto a capo. Penso sia semplice, ma non ci arrivo, per la mia scarsa dimestichezza con VBA. Qualcuno può gentilmente aiutarmi ? Gliene sarei molto grato.
Sponsor
Inviato: Friday, September 02, 2005 6:39:58 PM

 
a10n11
Inviato: Saturday, September 03, 2005 10:54:24 AM

Rank: AiutAmico

Iscritto dal : 5/29/2003
Posts: 1,694
sicuro che la funzione che hai descritto funzioni?
If Cell(1, 1).Value )= Cell(1, 1).Offset(-1, 0).Value Then
questa riga in teoria non restituisce nulla in quanto usi la variabile Cell come Range a meno che non ti sia sfuggita una "s" finale .
Per risponderti mi sono andato a studiare questo strumento di analisi e se ho capito bene
la formula sarebbe in sintesi questa: 100-100/(1+numerorialzi/numeroribassi)
se così è qui ecco come dovrebbe essere modificata la funzione.
Public Function RSI(List)
Dim Cell As Variant
SumPos = 0
SumNeg = 0
For Each Cl In List
If Cl.Offset(0, 2) ) 0 Then
SumPos = SumPos + 1
End If
If Cl.Offset(0, 3) (> 0 Then
SumNeg = SumNeg + 1
End If
Next
If SumNeg = 0 Then
tRSI = 100
Else
RSI = 100 - 100 / (1 + SumPos / SumNeg)
End If
End Function

la tabella presa in esame ha in colonna A la data, in colonna B il valore, in colonna C i rialzi, in colonna D i ribassi
saluti
Andrea

guayas
Inviato: Sunday, September 04, 2005 4:27:55 PM
Rank: Member

Iscritto dal : 12/20/2001
Posts: 0
Grazie mille Andrea per aver risposto e per esserti interessato alla mia formula.
Però non capisco : la formula che ho postato l'ho copiata e incollata direttante dal mio file e funziona perfettamente( forse per puro caso ? ), senza dover peraltro ricorrere a colonne intermedie con i rialzi e i ribassi ( ho solo bisogno della colonna coi prezzi dell'azione ). Posso mandarti un allegato se vuoi. Inoltre per calcolare l'Rsi, non uso il rapporto tra il numero di rialzi e il numero di ribassi, ma tra la somma dei punti in rialzo e quella di ribasso. Comunque il mio problema è un'altro : io vorrei che l'argomento della funzione non sia l'intervallo di celle su cui viene calcolata ( List, nell'esempio ) ma vorrei definire List all'interno della formula, e usare come argomento della funzione la lunghezza dell'intervallo. Nella definizione di List, la lunghezza del range sarebbe indefinita e diventerebbe l'argomento dell'RSI. Ad esempio se voglio calcolare l'Rsi a 14 giorni scrivere sul foglio di lavoro =RSI(14) ( o ancora meglio =RSI (B1), in B1 scrivendo 14 ) e non RSI (A1:A14 ). Potrei farlo facilmente usando la funzione "scarto" : =RSI(scarto...), ma preferirei farlo direttamente in VBA. Spero di essere stato chiaro. Puoi aiutarmi in questo ? Ringrazio te e chiunque possa farlo.
a10n11
Inviato: Monday, September 05, 2005 10:16:18 AM

Rank: AiutAmico

Iscritto dal : 5/29/2003
Posts: 1,694
salve. avevo premesso che non conoscevo questo strumento di analisi. Leggendo in giro mi era sembrato che il metodo si applicasse tenendo conto della differenza tra i numeri di rialzo e quelli di ribasso e non del valore di essi.
In questo caso vedi se la funzione che ti descrivo sotto soddisfa le tue esigenze.

Public Function RSI(Riga As Integer, Col As Integer, Intervallo As Integer) As Double
Dim N As Integer, Inc As Double, Dec As Double, Oggi As Double, Prec As Double
' se i dati iniziano da riga 1 colonna 1 nella maschera funzione andranno indicati:
' Riga =1 - colonna =1 - Intervallo = 14 (oppure un riferimento di cella)
Inc = 0 'inizializza la variabile che totalizza gli incrementi
Dec = 0 ' inizializza la variabile che totalizza i decrementi
With ActiveSheet
For N = 1 To Intervallo
Oggi = .Cells(Riga + N, Col)
Prec = .Cells(Riga + N - 1, Col)
If Oggi - Prec > 0 Then
Inc = Inc + Oggi - Prec
Else
Dec = Dec + Prec - Oggi
End If
Next
End With
RSI = 100 - (100 / (1 + (Inc / dec)))
End Function

All'inizio della funzione ti ho descritto alcune note di chiarimento.
es. se i tuoi dati iniziano da cella A1 la formula sarà =RSI(1;1;14)
dove al posto di 14 potrai inserire un qualsiasi riferimento di cella.
saluti
Andrea

guayas
Inviato: Wednesday, September 07, 2005 10:31:24 PM
Rank: Member

Iscritto dal : 12/20/2001
Posts: 0
Grazie mille, Andrea, è proprio quello che volevo !!!! GRANDE !!!!! ciao
guayas
Inviato: Sunday, December 11, 2005 11:22:25 AM
Rank: Member

Iscritto dal : 12/20/2001
Posts: 0
Ciao, andrea. Mi avevi aiutato egregiamente con la formula dell'Rsi, ma c'è un problema.
Ho leggermente modificato la tua formula, perchè volevo che la riga di riferimento fosse sempre quella della cella attiva, cioè della cella in cui è iscritta la formula.
La nuova formula è la seguente :

Public Function RSI(Col As Integer, Intervallo As Integer)
Dim N, Inc, Dec, Oggi, Prec, Riga
Inc = 0
Dec = 0
With ActiveSheet
Riga = ActiveCell.Row
For N = 0 To Intervallo
Oggi = .Cells(Riga - N, Col)
Prec = .Cells(Riga - N - 1, Col)
If Oggi - Prec > 0 Then
Inc = Inc + Oggi - Prec
Else
Dec = Dec + Prec - Oggi
End If
Next
End With
RSI = 100 - (100 / (1 + (Inc / Dec)))
End Function

Se RSI(3;14) calcola l'RSI sulla colonna C per 14 righe al di sopra di quella in cui è la cella contenente la formula.
Tutto funziona bene. Però se io seleziono la cella in cui c'è l'RSI e faccio lo scroll per copiarla in tutte le celle della colonna, la formula è sempre calcolata come se la cella attiva fosse quella di partenza ( quindi il risultato è sempre uguale ), mentre se faccio un normale copia incolla, va tutto bene. Come faccio a superare questo inconveniente ? ( a me serve fare lo scroll : cosa devo scrivere ? )

Poi puoi spiegarmi gentilmente perchè se scrivo come segue, cioè usando Offset per identificare la riga, non funziona ?

Public Function RSI(Col As Integer, Intervallo As Integer)
Dim N, Inc, Dec, Oggi, Prec
Inc = 0
Dec = 0
With ActiveSheet
For N = 0 To Intervallo
Oggi = ActiveCell.Offset(0 - N, Col)
Prec = ActiceCell.Offset(0 - N - 1, Col)
If Oggi - Prec > 0 Then
Inc = Inc + Oggi - Prec
Else
Dec = Dec + Prec - Oggi
End If
Next
End With
RSI = 100 - (100 / (1 + (Inc / Dec)))
End Function

Dov'è l'errore ?
Ti ringrazio e saluto
Michele
a10n11
Inviato: Monday, December 12, 2005 12:06:20 PM

Rank: AiutAmico

Iscritto dal : 5/29/2003
Posts: 1,694
Facendo il semplice trascinamento della formula e non il copia/incolla la formula non viene ricalcolata, bisogna in quel caso preme F2+invio sulla cella per farla calcolare.

La tua formula:
Oggi = ActiveCell.Offset(0 - N, Col)
Prec = ActiceCell.Offset(0 - N - 1, Col)
se Col è = 1 l'offset sposta la cella attiva alla colonna successiva
quindi se l'intervallo è sulla colonna A con la formula che hai scritto ti sposti sulla colonna B. Ioltre (0-N) nel primo giro del ciclo For/next ti restituirà un riferimento circolare perchè l'offset sarà pari a zero quindi rimani puntato sulla cella attiva. vedi sotto come modificare:


Qui sotto, 3 ipotesi per come modificare le funzioni per assumere di default la cella attiva:

con questa macro funzione, indicando la colonna e l'intervallo, la riga di riferimento viene assunta dalla cella attiva il calcolo comincia dal primo valore dell'intervallo.

Public Function RSI(col As Integer, Intervallo As Integer) As Double
Dim N, Inc, Dec, Oggi, Prec, riga
Inc = 0
Dec = 0
With ActiveSheet
riga = ActiveCell.Offset(-1, 0).End(xlUp).Row
For N = 1 To Intervallo
Oggi = .Cells(riga + N, col)
Prec = .Cells(riga + N - 1, col)
If Oggi - Prec > 0 Then
Inc = Inc + Oggi - Prec
Else
Dec = Dec + Prec - Oggi
End If
Next
End With
RSI = 100 - (100 / (1 + (Inc / Dec)))
End Function

in alternativa a quella sopra, la riga e la colonna vengono prese di default dalla cella attiva e resta solo da indicare l'intervallo:

Public Function RSI2(Intervallo As Integer) As Double
Dim N, Inc, Dec, Oggi, Prec, riga, col
Inc = 0
Dec = 0
With ActiveSheet
riga = ActiveCell.Offset(-1, 0).End(xlUp).Row
colonna = ActiveCell.Column
For N = 1 To Intervallo
Oggi = .Cells(riga + N, colonna)
Prec = .Cells(riga + N - 1, colonna)
If Oggi - Prec > 0 Then
Inc = Inc + Oggi - Prec
Else
Dec = Dec + Prec - Oggi
End If
Next
End With
RSI2 = 100 - (100 / (1 + (Inc / Dec)))
End Function



Terza ipotesi, il calcolo inizia dall'ultimo valore dell'intervallo :

Public Function RSI3(col As Integer, Intervallo As Integer) As Double
Dim N, Inc, Dec, Oggi, Prec
Inc = 0
Dec = 0
With ActiveSheet
riga = ActiveCell.Offset(-1, 0).Row
For N = 0 To Intervallo
Oggi = .Cells(riga - N, col)
Prec = .Cells(riga - N - 1, col)
If Oggi - Prec > 0 Then
Inc = Inc + Oggi - Prec
Else
Dec = Dec + Prec - Oggi
End If
Next
End With
RSI3 = 100 - (100 / (1 + (Inc / Dec)))
End Function

resto dell'idea che una funzione non debba essere vincolata ad una cella
ma avere riferimenti variabili in modo da poterla utilizzare in qualsiasi punto del foglio.
saluti
Andrea






Edited by - a10n11 on 12/12/2005 14:52:13

guayas
Inviato: Tuesday, December 13, 2005 11:21:12 AM
Rank: Member

Iscritto dal : 12/20/2001
Posts: 0
Ciao, Andrea, graze per la risposta. Dunque, innanzitutto penso di non aver spiegato bene perchè mi serve che il calcolo della formula parta dalla stessa riga della cella attiva, e perchè riga-N. Dunque io ho i dati sulla colonna A ( poniamo da A1 a A100 ). Sulla colonna B la funzione RSI(1;14). Questa funzione deve calcolare la formula sui dati presenti sulla colonna A a partire dalla stessa riga, per 14 celle indietro ( quindi la formula in B14 sarà calcolata sui dati in A1:A14. In b15 su A2:A15, in B16 su A3:A7...e così via. Così ho sul grafico la linea dei dati e la linea dell'RSI. Detto ciò, la prima formula ( quella con Oggi = .Cells(riga-N, col) ) funziona bene. Invece se uso offset, mi da VALORE? . Però non capisco : perchè la mia scrittura dovrebbe darmi un riferimento circolare ? nel primo ciclo la riga sarà 0, ed è quello che voglio, ma la colonna è diversa, con RSI(-1;14) ). Perchè ovviamente so che se uso Offset scriverò RSI(-1;14); se uso .Cells, scriverò RSI(1;14). Quindi l'errore non è lì.
Il problema vero quindi per me è quello del trascinamento. Come hai visto a me l'RSI serve su ogni cella da B14 a B100 ( ma di partenza la funzione è scritta solo su B14, il trascinamento sarebbe una sorta di attivazione ). Perchè se trascino la formula da B14, la formula in B100, mi usa come cella attiva ancora la B14 ? Non c'è modo di aggirare l'ostacolo, sempre potendo usare il trascinamento ? Dovrei fare una serie di copia/incolla ? Sarebbe più lento del trascinamento, è proprio l'unica possibilità ?
Grazie per la tua disponibilità.
Michele
a10n11
Inviato: Tuesday, December 13, 2005 7:34:20 PM

Rank: AiutAmico

Iscritto dal : 5/29/2003
Posts: 1,694
salve.
Invece se uso offset, mi da VALORE...
questa è il codice corretto:
Oggi = ActiveCell.Offset(0 - N, -Col)
Prec = ActiveCell.Offset(0 - N - 1, -Col)

se non metti il simbolo meno (-Col) che significa sposta la colonna attiva di meno una posizione, viene interpretato esattamente all'opposto, il riferimento si sposta una colonna avanti (colonna C) che è vuota quindi il risultato è un errore.
se provi così funziona:

Public Function RSI(Col As Integer, Intervallo As Integer)
Dim N, Inc, Dec, Oggi, Prec
Inc = 0
Dec = 0
With ActiveSheet
For N = 0 To Intervallo
Oggi = ActiveCell.Offset(0 - N, -Col)
Prec = ActiveCell.Offset(0 - N - 1, -Col)
If Oggi - Prec > 0 Then
Inc = Inc + Oggi - Prec
Else
Dec = Dec + Prec - Oggi
End If
Next
End With
RSI = 100 - (100 / (1 + (Inc / Dec)))
End Function

l'aggiornamento della formula per trascinamento devi farla con F2+invio sulla cella o copiare singolarmente le celle. Infatti se si usasse l'applicazione
Application.volatile(True) che ricalcola in automatico non funziona in quanto ricalcola tutte le formule prendendo come base la cella attiva al momento.
saluti
Andrea

Edited by - a10n11 on 12/13/2005 19:35:17

Utenti presenti in questo topic
Guest


Salta al Forum
Aggiunta nuovi Topic disabilitata in questo forum.
Risposte disabilitate in questo forum.
Eliminazione tuoi Post disabilitata in questo forum.
Modifica dei tuoi post disabilitata in questo forum.
Creazione Sondaggi disabilitata in questo forum.
Voto ai sondaggi disabilitato in questo forum.

Main Forum RSS : RSS

Aiutamici Theme
Powered by Yet Another Forum.net versione 1.9.1.8 (NET v2.0) - 3/29/2008
Copyright © 2003-2008 Yet Another Forum.net. All rights reserved.