Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1540to1544
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

ByRef argument type mismatch

ByRef argument type mismatch
24.02.2017 11:56:17
Fabian
Hallo Zusammen,
ich habe folgende Macro geschrieben, wenn ich Sie aktivieren will kommt aber immer ein
"ByRef argument type mismatch" als Fehler. Ich komme einfach nicht drauf, an welchen Stellen es nicht passt.
Besten Dank und ein schönes Wochenende.
Fabian
Option Explicit
Sub IFD()
'Input parameters from worksheet
Dim iMax As Integer: iMax = Range("B3").Value
Dim jMax As Integer: jMax = Range("B2").Value
Dim maturity As Double: maturity = Range("B4").Value
Dim strike As Double: strike = Range("B5").Value
Dim riskFree As Double: riskFree = Range("B6").Value
Dim sigma As Double: sigma = Range("B7").Value
Dim dprice As Double: dprice = Range("B8").Value
Dim qcontract As Double: qcontract = Range("B10").Value
Dim knock As Double: knock = Range("B11").Value
Dim settle As Double: settle = Range("B12").Value
'Perform the matrix calculation
Dim Fvec() As Double: ReDim Fvec(0 To jMax)
Call CalAccumulatorPrices(knock, settle, qcontract, maturity, strike, riskFree, sigma, iMax,  _
jMax, dprice, Fvec())
'Put results back to worksheet
Dim i As Integer
For i = 0 To jMax: Range("C15").Offset(i, 0) = Fvec(i): Next i
End Sub

Sub CalAccumulatorPrices(knock As Double, settle As Double, qcontract As Double, maturity As  _
Double, strike As Double, riskFree As Double, sigma As Double, _
iMax As Integer, jMax As Integer, dprice As Double, ByRef Fvec() As Double)
Dim dtime As Double: dtime = maturity / iMax
Dim Lr As Integer
Dim i As Integer
Dim CIRsigma As Double: CIRsigma = sigma * (Lr * dprice) ^ 1 / 2
'Construct the matrix P and Q
Dim Pmatrix() As Double: ReDim Pmatrix(0 To jMax, 0 To jMax)
Dim Qmatrix() As Double: ReDim Qmatrix(0 To jMax, 0 To jMax)
Pmatrix(0, 0) = Exp(riskFree * dtime)
Pmatrix(jMax, jMax) = 1
Qmatrix(0, 0) = 0
Qmatrix(jMax, jMax) = 1
For Lr = 1 To jMax - 1
Pmatrix(Lr, Lr - 1) = 0.25 * ((Lr * riskFree * dtime) - (Lr ^ 2 * CIRsigma ^ 2 * dtime))
Pmatrix(Lr, Lr) = 1 + 0.5 * (riskFree * dtime) + (Lr ^ 2 * CIRsigma ^ 2 * dtime)
Pmatrix(Lr, Lr + 1) = -0.25 * ((Lr * riskFree * dtime) + (Lr ^ 2 * CIRsigma ^ 2 * dtime))
Next Lr
For Lr = 1 To jMax - 1
Qmatrix(Lr, Lr - 1) = -0.25 * ((Lr * riskFree * dtime) - (Lr ^ 2 * CIRsigma ^ 2 * dtime))
Qmatrix(Lr, Lr) = 1 - 0.5 * (riskFree * dtime) + (Lr ^ 2 * CIRsigma ^ 2 * dtime)
Qmatrix(Lr, Lr + 1) = 0.25 * ((Lr * riskFree * dtime) + (Lr ^ 2 * CIRsigma ^ 2 * dtime))
Next Lr
'Initialize the option vector according to the payoff condition
For Lr = 0 To jMax: Fvec(Lr) = Payoff(Lr * dprice, strike) * qcontract: Next Lr
'Perform the iteration
For i = 1 To iMax
Call SolveAxb(Pmatrix, Qmatrix, Fvec, Fvec, jMax + 1, 0, 0, 0)
Call Boundary(Fvec, jMax, dprice, knock, settle)
Next i
End Sub
'Put option payoff condition
Function Payoff(strike As Double, price As Double) As Double
Payoff = (price - strike)
End Function
'Accumulator settlement day and knock out feature
Sub Boundary(ByRef Fvec() As Double, i As Integer, knock As Double, jMax As Integer, settle As  _
Double, dprice As Double)
Dim Lr As Integer
Dim ReferenceV As Double: ReferenceV = iMax / settle
If (i Mod ReferenceV) = 0 Then
Lr = 0
Do While Lr = knock Then
Fvec(Lr) = 0
End If
Lr = Lr + 1
Loop
End If
End Sub

4
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: ByRef argument type mismatch
24.02.2017 12:29:26
Michael
Hi,
1. bist Du uns die SolveAxb schuldig geblieben,
2. führt die Konstruktion
Dim Lr As Integer
Dim i As Integer
Dim CIRsigma As Double: CIRsigma = sigma * (Lr * dprice) ^ 1 / 2

dazu, daß CIRsigma IMMER = 0 ist, weil LR 0 ist; abgesehen davon: wenn ^ 1 / 2 = Wurzel bedeuten soll, würde ich die 1/2 in Klammern setzen (weiß nicht ganz genau, müßte man testen), weil sonst womöglich erst hoch 1 (das ändert nix) und dann erst / 2 ausgeführt werden *könnte*.
3. erwartet

Sub Boundary(ByRef Fvec() As Double, i As Integer, knock As Double, _
jMax As Integer, settle As Double, dprice As Double)

sechs Parameter, Du rufst es aber nur mit fünfen auf:
Call Boundary(Fvec, jMax, dprice, knock, settle)

das sollte der Fehler sein.
Schöne Grüße,
Michael
Anzeige
AW: ByRef argument type mismatch
25.02.2017 16:19:13
Fabian
Hi Michael,
vielen Dank für deine Antwort und deine Hinweise. Ich habe nun einige Änderungen vorgenommen, im speziellen auch die CRIsigma calculation, habe ich direkt in die Matrix integriert.
Nun erhalte ich jedoch den Error Division by Zero, kann leider nicht finde wo diese Berechnung stattfindet.
Habe dir dieses mal auch die SolveAxb angehängt.
Vielen Dank und Grüße
Fabian
Option Explicit
Dim iMax As Integer, jMax As Integer, maturity As Double, strike As Double, riskFree As Double, sigma As Double, dprice As Double
Dim dtime As Double, qcontract As Double, settle As Double, knock As Double
Sub IFD()
'Input parameters from worksheet
Dim iMax As Integer: iMax = Range("B3").Value
Dim jMax As Integer: jMax = Range("B2").Value
Dim maturity As Double: maturity = Range("B4").Value
Dim strike As Double: strike = Range("B5").Value
Dim riskFree As Double: riskFree = Range("B6").Value
Dim sigma As Double: sigma = Range("B7").Value
Dim dprice As Double: dprice = Range("B8").Value
Dim qcontract As Double: qcontract = Range("B10").Value
Dim knock As Double: knock = Range("B11").Value
Dim settle As Double: settle = Range("B12").Value
'Perform the matrix calculation
Dim Fvec() As Double: ReDim Fvec(0 To jMax)
Call CalAccumulatorPrices(knock, settle, qcontract, maturity, strike, riskFree, sigma, iMax,  _
jMax, dprice, Fvec())
'Put results back to worksheet
Dim i As Integer
For i = 0 To jMax: Range("C15").Offset(i, 0) = Fvec(i): Next i
End Sub

Sub CalAccumulatorPrices(knock As Double, settle As Double, qcontract As Double, maturity As  _
Double, strike As Double, riskFree As Double, sigma As Double, _
iMax As Integer, jMax As Integer, dprice As Double, ByRef Fvec() As Double)
Dim dtime As Double: dtime = maturity / iMax
Dim Lr As Integer
Dim i As Integer
'Construct the matrix P and Q
Dim Pmatrix() As Double: ReDim Pmatrix(0 To jMax, 0 To jMax)
Dim Qmatrix() As Double: ReDim Qmatrix(0 To jMax, 0 To jMax)
Pmatrix(0, 0) = Exp(riskFree * dtime)
Pmatrix(jMax, jMax) = 1
Qmatrix(0, 0) = 0
Qmatrix(jMax, jMax) = 1
For Lr = 1 To jMax - 1
Pmatrix(Lr, Lr - 1) = 0.25 * ((Lr * riskFree * dtime) - (Lr ^ 2 * sigma ^ 2 * Lr * dprice *  _
dtime))
Pmatrix(Lr, Lr) = 1 + 0.5 * (riskFree * dtime) + (Lr ^ 2 * sigma ^ 2 * Lr * dprice * dtime)
Pmatrix(Lr, Lr + 1) = -0.25 * ((Lr * riskFree * dtime) + (Lr ^ 2 * sigma ^ 2 * Lr * dprice * _
dtime))
Next Lr
For Lr = 1 To jMax - 1
Qmatrix(Lr, Lr - 1) = -0.25 * ((Lr * riskFree * dtime) - (Lr ^ 2 * sigma ^ 2 * Lr * dprice * _
dtime))
Qmatrix(Lr, Lr) = 1 - 0.5 * (riskFree * dtime) + (Lr ^ 2 * sigma ^ 2 * Lr * dprice * dtime)
Qmatrix(Lr, Lr + 1) = 0.25 * ((Lr * riskFree * dtime) + (Lr ^ 2 * sigma ^ 2 * Lr * dprice *  _
dtime))
Next Lr
'Initialize the option vector according to the payoff condition
For Lr = 0 To jMax: Fvec(Lr) = Payoff(Lr * dprice, strike) * qcontract: Next Lr
'Perform the iteration
For i = iMax - 1 To 1 Step -1
Call SolveAxb(Pmatrix, Qmatrix, Fvec, Fvec, jMax + 1, 0, 0, 0)
Call Boundary(Fvec, i)
Next i
End Sub
'Put option payoff condition
Function Payoff(strike As Double, price As Double) As Double
Payoff = (price - strike)
End Function
'Accumulator settlement day and knock out feature
Sub Boundary(ByRef Fvec() As Double, i As Integer)
Dim Lr As Integer
Dim N As Double: N = iMax / settle
If (i Mod N) = 0 Then
Lr = 0
Do While Lr = knock Then
Fvec(Lr) = 0
End If
Lr = Lr + 1
Loop
End If
End Sub
Sub SolveAxb(Pmatrix() As Double, Qmatrix() As Double, bvec() As Double, ByRef xvec() As Double, _
_
N As Integer, iptr As Integer, jptr As Integer, kptr As Integer)
Dim wsPmatrix As Variant: ReDim wsPmatrix(1 To N, 1 To N)
Dim wsQmatrix As Variant: ReDim wsQmatrix(1 To N, 1 To N)
Dim row As Integer, column As Integer
For row = 1 To N
For column = 1 To N: wsPmatrix(row, column) = Pmatrix(iptr + row - 1, jptr + column - 1):  _
Next column
Next row
For row = 1 To N
For column = 1 To N: wsQmatrix(row, column) = Qmatrix(iptr + row - 1, jptr + column - 1):  _
Next column
Next row
Dim wsbvec As Variant: ReDim wsbvec(1 To N, 1 To 1)
For row = 1 To N: wsbvec(row, 1) = bvec(kptr + row - 1): Next row  '
Dim wsxvec As Variant:
With Application.WorksheetFunction
wsGmatrix = .MMult(.MInverse(wsPmatrix), wsQmatrix)
wsxvec = .MMult(wsGmatrix, wsbvec)
End With
Dim i As Integer
If N = 1 Then
For i = kptr To kptr + N - 1: xvec(i) = wsxvec(i - kptr + 1): Next i
Else
For i = kptr To kptr + N - 1: xvec(i) = wsxvec(i - kptr + 1, 1): Next i
End If
End Sub

Anzeige
Variablen-Wirrwarr
25.02.2017 17:47:20
Michael
Hi,
sag, mit Datei (es sind ja nur ein paar Werte in Spalte B) wäre es leichter nachzuvollziehen....
Der Fehler, den ich direkt sehe, resultiert aus Deiner inflationären Verwendung von Variablen.
Ich persönlich würde gar nicht erst mit so vielen Namen rumtun, sondern einfach B2:B12 als Array einlesen. Dann sieht man zwar nicht, was was ist, aber was hintert einen daran, einen entsprechenden Kommentar zu Beginn der "kritischen" Subs anzubringen, á la
' B2: jmax: dient für dies und das
' B3: imax: bla und bla
Der Punkt ist der Gültigkeitsbereich von Variablen, hier insbesondere "settle": die ist global definiert UND lokal.
Innerhalb der Sub IFD definierst Du:
Dim settle As Double: settle = Range("B12").Value
Der Aufruf
Call CalAccumulatorPrices(knock, settle, qcontract, maturity, usw.)
erfolgt innerhalb der Sub mit dem Wert aus B12.
In der Sub CalAccumulatorPrices wird settle als ByVal übernommen - so weit ok, allerdings überflüssig, weil settle in der ganzen Sub nicht verwendet wird, auch nicht beim Aufruf von
Call Boundary(Fvec, i)
Das heißt, die Sub Boundary greift mangels Parameterübergabe auf die GLOBALE settle zu, und die ist 0, weil das Ding bis dahin nie verwendet wurde: also MUSS N = iMax / settle div/0 werfen.
Ich sehe grad: iMax wird auch NICHT übergeben, so daß hier auch das Globale = 0 zum Zuge kommt!
Ich kann Dir nur raten, Dir mal ganz genau zu überlegen, was wann übergeben wird.
Bei simplen Projekten schadet es auch nicht, in aufgerufenen Subs die gleichen Variablennamen zu verwenden, aber hier solltest Du sie vielleicht entsprechend kennzeichnen:
globales iMax: giMax
aufrufendes iMax: aiMax
iMax als Parameter: piMax
oder so ähnlich, sinngemäß.
Viel Spaß,
Michael
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige