Newsgroup: it.comp.lang.visual-basic
Titolo: HELP vb per Excel- MACRO

Ciao a tutti,
sto scrivendo una macro per Excel
tale macro pesca dei valori da un foglio di excel, li rielabora utilizzando
una funzione (public function pdi) da me scritta, poi stampa il risultato in
una cella.
il listato della macro è:
Sub Simulazione()
'Raccoglie i dati dal foglio
Set rf = Worksheets("MC").Range("c7")
Set b = Worksheets("MC").Range("c8")
Set vol = Worksheets("MC").Range("c10")
Set s0 = Worksheets("MC").Range("c6")
Set ttm = Worksheets("MC").Range("c9")
Set strike = Worksheets("MC").Range("c4")
Set barriera = Worksheets("MC").Range("c5")
Set simtot = Worksheets("MC").Range("c1")
st = s0 + 40
output = pdi(st, strike, barriera, k, ttm - 1 / 365 * 5, rf, b, vol)
Cells(10, 10).Value = output
End Sub
Ovviamente ho un pò semplificato le cose, intendo che ho omesso alcune
subroutine e semplificato le funzioni ecc....comuqnue la sostanza del
programma è questa...
Quando lancio il debug mi viene evidenzato il primo argomento della funzione
pdi(e quindi presuppongo che l'errore si riverificherà anche per gli altri)
con una finestra che dice:
"Tipo non corrispondente per l'argomento byRef"
Che vuol dire? Se uso la funzione pdi in un foglio mi funziona
correttamente......
Come avrete capito sono un praticone, non ho studiato molto il vb...quindi
quando mi trovo di fronte agli errori di sintassi sono dolori...
Come faccio a fare si che quei valori perscati dal foglio di excel possano
essere rielaborati dalla funzione? ovviamente non posso legare la funzione
direttamente  alle celle (tipo pdi(c6;c8;c4;ecc...))
Grazie tante,
IaN

> IaNjOeY:

Prima di tutto dovresti farci vedere la dichiarazione della funzione pdi:
    Function pdi(
... e poi come continua?
E` possibile anche che tu non usi Option Explicit (vedi guida) che invece e`
molto importante.
--
Ciao.
Maurizio
--------
?SPQR(C)
 X
--------

 molto importante.
posto tutto allora:
'// The cumulative normal distribution function
Public Function CND(X As Double) As Double
    Dim L As Double, k As Double
    Const a1 = 0.31938153:  Const a2 = -0.356563782: Const a3 = 1.781477937:
    Const a4 = -1.821255978:  Const a5 = 1.330274429
    L = Abs(X)
    k = 1 / (1 + 0.2316419 * L)
    CND = 1 - 1 / Sqr(2 * Pi) * Exp(-L ^ 2 / 2) * (a1 * k + a2 * k ^ 2 + a3
* k ^ 3 + a4 * k ^ 4 + a5 * k ^ 5)
    If X < 0 Then
        CND = 1 - CND
    End If
End Function
Public Function invmoro(u As Double) As Double
'inverse Cumulative Normal Distibution secondo l'algoritmo di MORO
X = u - 0.5
If Abs(X) < 0.42 Then
'usiamo l'algoritmo di Beasly and Springer
a0 = 2.50662823884
a1 = -18.61500062529
a2 = 41.39119773534
a3 = -25.44106049637
b0 = -8.4735109309
b1 = 23.08336743743
b2 = -21.06224101826
b3 = 3.
13082909833
y = X * X
r = X * (((a3 * y + a2) * y + a1) * y + a0) / ((((b3 * y + b2) * y + b1) * y
+ b0) * y + 1)
invmoro = r
Else:
'per aumentare la precisione nelle code usiamo l'algoritmo di Moro
c0 = 0.337475482272615
c1 = 0.976169019091719
c2 = 0.160797971491821
c3 = 2.76438810333863E-02
c4 = 3.8405729373609E-03
c5 = 3.951896511919E-04
c6 = 3.21767881768E-05
c7 = 2.888167364E-07
c8 = 3.960315187E-07
r = u
If X > 0 Then r = 1 - u
r = Log(-Log(r))
r = c0 + r * (c1 + r * (c2 + r * (c3 + r * (c4 + r * (c5 + r * (c6 + r * (c7
+ r * c8)))))))
If X < 0 Then r = -r
invmoro = r
End If
End Function
Public Function plainvanilla(S As Double, X As Double, T As Double, r As
Double, b As Double, v As Double) As Double
'Calcola il valore di una put plain vanilla
    Dim d1 As Double, d2 As Double
    d1 = (Log(S / X) + (b + v ^ 2 / 2) * T) / (v * Sqr(T))
    d2 = d1 - v * Sqr(T)
    plainvanilla = X * Exp(-r * T) * CND(-d2) - S * Exp((b - r) * T) *
CND(-d1)
    End Function
Public Function pdi(S As Double, X As Double, h As Double, k As Double, T As
Double, _
            r As Double, b As Double, v As Double)
   'Prezza le opzioni put down and in tramite il modello di Rubinstein
Reiner
    Dim mu As Double
    Dim lambda As Double
    Dim X1 As Double, X2 As Double
    Dim y1 As Double, y2 As Double
    Dim Z As Double
    Dim eta As Integer    'Binary variable that can take the value of 1
or -1
    Dim phi As Integer    'Binary variable that can take the value of 1
or -1
    Dim f2 As Double    'Equal to formula "B" in the book
    Dim f3 As Double    'Equal to formula "C" in the book
    Dim f4 As Double    'Equal to formula "D" in the book
    Dim f5 As Double    'Equal to formula "E" in the book
   If S > h Then GoTo barrier Else GoTo vanilla
barrier:
    mu = (b - v ^ 2 / 2) / v ^ 2
    lambda = Sqr(mu ^ 2 + 2 * r / v ^ 2)
    X1 = Log(S / X) / (v * Sqr(T)) + (1 + mu) * v * Sqr(T)
    X2 = Log(S / h) / (v * Sqr(T)) + (1 + mu) * v * Sqr(T)
    y1 = Log(h ^ 2 / (S * X)) / (v * Sqr(T)) + (1 + mu) * v * Sqr(T)
    y2 = Log(h / S) / (v * Sqr(T)) + (1 + mu) * v * Sqr(T)
    Z = Log(h / S) / (v * Sqr(T)) + lambda * v * Sqr(T)
    eta = 1
    phi = -1
    f2 = phi * S * Exp((b - r) * T) * CND(phi * X2) - phi * X * Exp(-r * T)
* CND(phi * X2 - phi * v * Sqr(T))
    f3 = phi * S * Exp((b - r) * T) * (h / S) ^ (2 * (mu + 1)) * CND(eta *
y1) - phi * X * Exp(-r * T) * (h / S) ^ (2 * mu) * CND(eta * y1 - eta * v *
Sqr(T))
    f4 = phi * S * Exp((b - r) * T) * (h / S) ^ (2 * (mu + 1)) * CND(eta *
y2) - phi * X * Exp(-r * T) * (h / S) ^ (2 * mu) * CND(eta * y2 - eta * v *
Sqr(T))
    f5 = k * Exp(-r * T) * (CND(eta * X2 - eta * v * Sqr(T)) - (h / S) ^ (2
* mu) * CND(eta * y2 - eta * v * Sqr(T)))
    pdi = f2 - f3 + f4 + f5
GoTo fine
vanilla:
    Dim d1 As Double
    Dim d2 As Double
    d1 = (Log(S / X) + (r + v ^ 2 / 2) * T) / (v * Sqr(T))
    d2 = d1 - v * Sqr(T)
   pdi = X * Exp(-r * T) * CND(-d2) - S * CND(-d1)
   GoTo fine
fine:
End Function
Sub Simulazione()
'Raccoglie i dati dal foglio
Set rf = Worksheets("MC").Range("c7")
Set b = Worksheets("MC").Range("c8")
Set vol = Worksheets("MC").Range("c10")
Set s0 = Worksheets("MC").Range("c6")
Set ttm = Worksheets("MC").Range("c9")
Set strike = Worksheets("MC").Range("c4")
Set barriera = Worksheets("MC").Range("c5")
Set simtot = Worksheets("MC").Range("c1")
'Simula il sentiero
Dim checkbarriera
Dim sim
Dim day
Dim random As Double
sim = 0
Do
sim = sim + 1
st = s0
checkbarriera = 0 'la barriera non è stata toccata
day = 0
Do
day = day + 1
'creo un numero casuale normale (poi student)
Randomize
random = rnd
rndmst = invmoro(random)
'calcolo il valore del sottostante in quel giorno
st = st * Exp((rf - 0.5 * vol ^ 2) * 1 / 365 + vol * (1 / 365) ^ 0.5 *
rndmst)
'decide se bisogna controllare la barriera:
If checkbarriera = 0 Then
GoTo controllo
ElseIf checkbarriera = 1 Then
GoTo skip
End If
controllo:
'controllo se la barriera è stata toccata
If st < barriera Then
            checkbarriera = 1
ElseIf st > barriera Then
          checkbarriera = 0
'ricordarsi di aggiungere la condizione di brothersonratcliffe
End If
GoTo skip
skip:
'stampo i valori
Cells(2 * sim - 1, day + 6).Value = st
Cells(2 * sim, day + 6).Value = checkbarriera
Loop Until day = 5
Loop Until sim = simtot
'valuta l'opzione nel 5 giorno
'decide che modello usare
If barriera = 0 Then
GoTo barrier
ElseIf barriera = 1 Then
GoTo vanilla
End If
barrier:
output = pdi(sott, strike, barriera, k, ttm - 1 / 365 * 5, rf, b, vol)
GoTo fine
vanilla:
output = plainvanilla(st, strike, ttm - 1 / 365 * 5, rf, b, vol)
fine:
Cells(2 * sim - 1, day + 11).Value = output
End Sub
Se hai avuto la pazienza di leggere tutto!!
Grazie!
Ciao
IaNjOeY

 posto tutto allora:
Conclusione indebita. Ti chiedevo solo la *dichiarazione*.
Limito l'esame a quello che avevi richiesto nel post iniziale, ovvero la
chiamata alla funzione pdi:
    output = pdi(sott, strike, barriera, k, ttm - 1 / 365 * 5, rf, b, vol)
e la dichiarazione di tale funzione:
    Public Function pdi( _
      S As Double _
    , X As Double _
    , h As Double _
    , k As Double _
    , T As Double _
    , r As Double _
    , b As Double _
    , v As Double _
    )
Cominciamo. "sott" non sappiamo come l'hai dichiarato ma, visto che mi pare
accertato che non usi Option Explicit, ipotizziamo sia un Variant al quale
assegni il valore:
    ...
Azz!... Non esiste proprio! Senti lasciamo perdere, il tuo modo di scrivere
codice e` inqualificabile. Se hai voglia di venirne fuori in maniera pulita
sara` bene che tu prima ti impadronisca di un metodo rigoroso di scrittura.
Frequentare assiduamente il ng ti potra` essere di grande aiuto.






Ogni riga ne perdevo un po'. Arrivato in fondo l'ho esaurita. >:-)


>    , k As Double
Grazie, ciao
IaNjOeY

 > >    , k As Double
Ah!... Ecco... No, invece!... Ancora non ci siamo. Lascia in pace "S As
Double" che sembra andar bene cosi`. E` "sott" nella riga "output = ..." che
non va. Posto che sia vero che tu non usi "Option Explicit", la situazione
dovrebbe assumere piu` o meno i seguenti contorni:
1.
Dichiarazione esplicita:
    Dim sott As <...>
Uso nella chiamata a "pdi" della variabile dichiarata esplicitamente:
    output = pdi(sott, <...>)
2.
Dichiarazione implicita:
    sott = <...>
Uso nella chiamata a "pdi" della variabile dichiarata implicitamente:
    output = pdi(sott, <...>)
3.
Dichiarazione implicita contestuale all'uso nella chiamata a "pdi":
    output = pdi(sott, <...>)
Per quanto riguarda il modo in cui e` dichiarata la funzione "pdi":
A.
    Function pdi(S As Double, <...>)
che e` lo stesso che scrivere:
    Function pdi(ByRef S As Double, <...>)
B.
    Function pdi(ByVal S As Double, <...>)
Tu usi il "metodo" (3) e la dichiarazione (A) e insieme questi producono, in
fase di compilazione, l'errore:
    "Tipo non corrispondente per l'argomento ByRef"
E` questo l'errore che ottieni? Se non e` questo l'errore vuol dire che il
codice che hai postato non e` quello che ti da` il problema. Ed in questo
caso sorge spontanea la domanda: cosa aspetti a dirci come stanno le cose?
Invece di risentirti per i miei rimproveri, dacci una mano a darti una mano.
