Pricing a European Option using Simulaitons - vba

I have created a user form that allows the user to change the various variables involved in pricing an option (Exercise Price, volatility..etc) along with allowing the user to change the simulations needed to arrive at the Price (or mean price in this case). However, I am unable to call the public subs within my code once I click the OK Button. Any suggestions on what I'm doing wrong would be greatly appreciated. [I have also included a picture of my user form below]
Option Explicit
Private cancel As Boolean
Public Function ShowInputsDialog(currentPrice As Single, _
exercisePrice As Single, riskfreeRate As Double, _
volatility As Single, duration As Single, simulation As Double) As Boolean
Call Initialize
Me.Show
If Not cancel Then
'Capture the other inputs.
currentPrice = txtCurrentPrice.Text
exercisePrice = txtExercisePrice.Text
riskfreeRate = txtRiskfreeRate.Text
volatility = txtVolatility.Text
duaration = txtDuration.Text
simulation = txtSimulation.Text
ShowInputsDialog = Not cancel
Unload Me
End Function
Public Sub ErrorCheck()
' Perform error checking for user inputs.
If IsNumeric(currentPrice) = False Or currentPrice < 0 Then
MsgBox ("Please enter a numeric value for the Current Price")
End If
If IsNumeric(exercisePrice) = False Or exercusePrice < 0 Then
MsgBox ("Please enter a positive numeric value for the exercise price")
End If
If IsNumeric(riskfreeRate) = False Then
MsgBox ("Please enter a numerical value for the risk-free rate")
End If
If IsNumeric(volatility) = False Then
MsgBox ("Please enter a numerical value for the Standard deviation")
End If
If IsNumeric(duration) = False Then
MsgBox ("Please enter a numerical valye for duration")
End If
End Sub
Public Sub Call_Eur(currentPrice As Single, _
exercisePrice As Single, riskfreeRate As Double, _
volatility As Single, duration As Single, simulation As Double)
Dim stockPrice As Single
Dim CallcashflowTermination As Single
Dim PutcashflowTermination As Single
Dim CalldiscountedValue As Double
Dim PutdiscountedValue As Double
Dim i As Integer
Dim CallMean As Double
Dim PutMean As Double
Dim arrayCallPrice() As Integer
Dim arrayPutPrice() As Integer
For i = 1 To simulation
' stock price
stockPrice = currentPrice * Exp((riskfreeRate - 0.5 * volatility ^ 2) * duration + volatility * Application.WorksheetFunction.Norm_Inv(Rnd(), 0, 1) * Sqr(duration))
' option cash flow at termination
CallcashflowTermination = Application.WorksheetFunction.Max(0, stockPrice - exercisePrice)
PutcashflowTerminatio = Application.WorksheetFunction.Funciton.Max(0, exercisePrice - stockPrice)
' discounted value of the option
CalldiscountedValue = CallcashflowTermination * Exp(-duration * riskfreeRate)
PutdiscountedValue = PutcashflowTermination * Exp(-duration * riskfreeRate)
arrayCallPrice(i) = CalldiscountedValue
arrayPutPrice(i) = PutdiscountedValue
CallMean = Application.WorsheetFunction.Average(arrayCallPrice)
PutMean = Application.WorksheetFunction.Average(arrayPutPrice)
Next i
MsgBox "The Call option price is " & CallMean & " the Put option price is " & PutMean
End Sub
Private Sub CmdCancel_Click()
Me.Hide
cancel = True
End Sub
Private Sub CmdOK_Click() '<--- ERROR!!!
Call Call_Eur(currentPrice As Single, _
exercisePrice As Single, riskfreeRate As Double, _
volatility As Single, duration As Single, simulation As Double)
End Sub
Private Sub UserForm_Click()
End Sub

BIG RED FLAG!!!!
When calling a subroutine. you need to pass values into it. Not redefine it's parameters.
Private Sub CmdOK_Click() '<--- ERROR!!!
Call Call_Eur(12.50, 13.43, 14, 33.56, 100, 13.67)
End Sub
I prefer removing the parenthesis and not using Call at all.
Private Sub CmdOK_Click() '<--- ERROR!!!
Call_Eur 12.50, 13.43, 14, 33.56, 100, 13.67
End Sub

Related

texbox calculation not correct

I'm running this code that should sum the values of two textboxes which it does correctly up to 999 if the number goes into the thousands the result comes back as 2.00 this is my code:
Private Sub Txtunitcost_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Me.TxtTotal.Value = Val(Me.TxtQty.Value) * Val(Me.TxtUnitCost.Value)
TxtTotal.Value = Format(TxtTotal.Value, ("#,##0.00;-#,##0.00"))
TxtUnitCost.Value = Format(TxtUnitCost.Value, ("#,##0.00;-#,##0.00"))
End Sub
For your code a quick fix could be to remove the thousand separator during the calculation like that
Private Sub Txtunitcost_Exit(ByVal Cancel As MSForms.ReturnBoolean)
txtUnitCost = Replace(txtUnitCost, Application.ThousandsSeparator, "")
Me.txtTotal.Value = Val(Me.txtQty.Value) * Val(Me.txtUnitCost.Value)
txtTotal.Value = Format(txtTotal.Value, ("#,##0.00;-#,##0.00"))
txtUnitCost.Value = Format(txtUnitCost.Value, ("#,##0.00;-#,##0.00"))
End Sub
For further expalnation have a look at the output of the following code
Sub Test()
Debug.Print Val("1000,00"), Val("1.000,00")
End Sub
1000 1
The strings represent thousand for me (german version, depending on the thousand separator) but the result of the conversion is different because of the thousand separator.
And the quick fix is
Sub Test()
Dim s1 As String
Dim s2 As String
s1 = "1000,00"
s2 = "1.000,00"
Debug.Print Val(s1), Val(s2), Val(Replace(s2, _
Application.ThousandsSeparator, ""))
End Sub
1000 1 1000
Even better would be to use CLng or CDbl instead of Val because
The Val function stops reading the string at the first character it
can't recognize as part of a number.
So the better fix would be
Private Sub Txtunitcost_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Me.txtTotal.Value = CDbl(Me.txtQty.Value) * CDbl(Me.txtUnitCost.Value)
txtTotal.Value = Format(txtTotal.Value, ("#,##0.00;-#,##0.00"))
txtUnitCost.Value = Format(txtUnitCost.Value, ("#,##0.00;-#,##0.00"))
End Sub
This is also stated in the above documentation
Note: The only valid decimal separator recognized by the Val()
function is the period (.). If you use a different decimal separator,
as some international applications do, use the CDbl function instead.
How about:
Private Sub Txtunitcost_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Dim TxtQty, TxtUnitCost, TxtTotat as Long
TxtQty = Format(Me.TxtQty.Value, ("#,##0.00;-#,##0.00"))
TxtUnitCost = Format(Me.TxtQty.Value, ("#,##0.00;-#,##0.00"))
TxtTotat = Format(TxtQty * TxtUnitCost, ("#,##0.00;-#,##0.00"))
End Sub

Passing Values in VBA

In the code I am posting, I am using a check box called "ACDS Test" and whenever it is checked it creates a sheet, then when it becomes unchecked it calls the upper function and deletes the sheet.
I am trying to add a message box that essentially works like a fail safe to ensure they want to delete the page. If they say they do not want to delete the page then I want the checkbox to stay checked.
For some reason I am getting this error message when I try to pass the value to make sure the checkbox stays checked and I cannot figure out why.
The error comes up on the line:
Sub ACDSTest_Click(CorrectValue As Integer)
And the specific error is: "Compile error: Procedure Declaration does not match description of event or procedure having the same name".
Any help is much appreciated! IF any more clarification is needed please feel free to ask!
Sub DeleteWorksheet(NameSheet As String)
Dim Ans As Long
Dim t As String
Dim CorrectValue As Integer
Dim i As Long, k As Long
k = Sheets.Count
Ans = MsgBox("Would you like to take this test off of the form?", vbYesNo)
Select Case Ans
Case vbYes
'Code reads through each page and finds one with corresponding name to string t
'Once it finds the correct page, it deletes it
For i = k To 1 Step -1
t = Sheets(i).Name
If t = NameSheet Then
Sheets(i).Delete
End If
Next i
CorrectValue = 0
Case vbNo
CorrectValue = 1
End Select
End Sub
Sub ACDSTest_Click(CorrectValue As Integer)
Dim NameSheet As String
Dim NameValue As String
NameSheet = "ACDS"
NameValue = "ACDS Test"
If ACDSTest.Value = True Then
CreateWorksheet (NameSheet), (NameValue)
Worksheets("Sheet1").Activate
Else
DeleteWorksheet (NameSheet)
If CorrectValue = 1 Then
ActiveSheet.Shapes("ACDS Test").ControlFormat.Value = 1
End If
End If
End Sub
The issue here is that the CorrectValue variable as you define it in DeleteWorksheet does not exist in the context of the
variable does not exist in context of the ACDSTest_Click subroutine. This is because variables defined within subroutines or functions are local to those functions. To correct this I would convert DeleteWorksheet to a function such as the below.
Further, the event that fires Private Sub ACDSTest_Click() cannot handle passing a value to that function, so changing it to Sub ACDSTest_Click(CorrectValue As Integer) causes an error.
Function DeleteWorksheet(ByVal SheetName As String) As Boolean
On Error GoTo SheetDNE
SheetName = Sheets(SheetName).Name 'Check if sheet exists w/o other objects
On Error GoTo 0
Select Case MsgBox("Would you like to take this test off of the form?", vbYesNo)
Case vbYes
Application.DisplayAlerts = False
Sheets(SheetName).Delete
Application.DisplayAlerts = True
DeleteWorksheet = True
Case Else: DeleteWorksheet = False
End Select
Exit Function 'Exit The Function w/o error
SheetDNE: 'Sheet Does Not Exist
MsgBox "The indicated sheet, " & SheetName & ", does not exist", vbOKOnly
End Function
And
Private Sub ACDSTest_Click()
Dim NameSheet As String
Dim NameValue As String
NameSheet = "ACDS"
NameValue = "ACDS Test"
If ACDSTest.Value = True Then
CreateWorksheet (NameSheet), (NameValue)
Worksheets("Sheet1").Activate
Else
If Not DeleteWorksheet(NameSheet) Then _
ActiveSheet.Shapes("ACDS Test").ControlFormat.Value = 1
End If
End Sub

Error while comparing msgbox with textbox in vba

I am new to VBA. I have created a program in VBA that compares a msgbox value with a textbox value, but the result is not right. I have copied the code below. What have I done wrong on this? Please help me.
Private Sub CommandButton1_Click()
Dim num As String
num = Application.InputBox("enter num")
If TextBox1.Value * num > TextBox2.Value Then
MsgBox "textbox1 is higher"
Else
MsgBox "textbox2 is higher"
End If
End Sub
You need an input validation before processing it
like follows
Option Explicit
Private Sub CommandButton1_Click()
Dim num As Long, tb1Val As Long, tb2Val As Long
Const DEFNUM As Long = 1 '<--| define a default value for 'num'
If Not ValidateInput(tb1Val, tb2Val) Then Exit Sub '<--| exit if textboxes have improper input
num = Application.InputBox("enter num", , DEFNUM, Type:=1) '<-_| 'Type:=1' forces a number input
With Me
If tb1Val * num > tb2Val.Value Then
MsgBox "textbox1 is higher"
Else
MsgBox "textbox2 is higher"
End If
End With
End Sub
Function ValidateInput(tb1Val As Long, tb2Val As Long) As Boolean
With Me
If IsNumber(.TextBox1) And IsNumber(.TextBox2) Then
tb1Val = CLng(.TextBox1.Value)
tb2Val = CLng(.TextBox2.Value)
ValidateInput = True
Else
MsgBox "Improper textbox input, try again", vbCritical
End If
End With
End Function
as you can see:
demanded to Function ValidateInput() the validation of relevant userfom input
you may want to change it to suit your actual needs
used Application.InputBox() function instead of VBA.InputBox() to exploit its Type parameter and force the input to a number
I assumed you need Long numbers, should not this be the case just change all Long occurrences with the needed data type (Double, Integer,...) and CLng() with corresponding Type conversion function (CDbl(), CInt(), ...
You Need to make sure all values you are getting from the InpoutBox and TextBox are numbers (in my code converted to Long , just to be on the safe side):
Private Sub CommandButton1_Click()
Dim num As Long
' convert the number received from the InputBox to a number (type Long)
num = CLng(Application.InputBox("enter num"))
If CLng(TextBox1.Value) * num > CLng(TextBox2.Value) Then
MsgBox "textbox1 is higher"
Else
MsgBox "textbox2 is higher"
End If
End Sub
What you had to do was just use the Val() function when getting the TextBox values. which means you had to use Val(TextBox1.Value) instead of TextBox1.Value
Private Sub CommandButton1_Click()
Dim num As String
num = Application.InputBox("enter num")
If Val(TextBox1.Value) * num > Val(TextBox2.Value) Then
MsgBox "textbox1 is higher"
Else
MsgBox "textbox2 is higher"
End If
End Sub

Every 5 seconds record the value in 2 cells in another worksheet VBA

Problem:
I have searched extensively for this and cannot seem to get it to work. I have a timer running when the "StartBtn" is pressed:
Dim StopTimer As Boolean
Dim SchdTime As Date
Dim Etime As Date
Dim currentcost As Integer
Const OneSec As Date = 1 / 86400#
Private Sub ResetBtn_Click()
StopTimer = True
Etime = 0
[TextBox21].Value = "00:00:00"
End Sub
Private Sub StartBtn_Click()
StopTimer = False
SchdTime = Now()
[TextBox21].Value = Format(Etime, "hh:mm:ss")
Application.OnTime SchdTime + OneSec, "Sheet1.NextTick"
End Sub
Private Sub StopBtn_Click()
StopTimer = True
Beep
End Sub
Sub NextTick()
If StopTimer Then
'Don't reschedule update
Else
[TextBox21].Value = Format(Etime, "hh:mm:ss")
SchdTime = SchdTime + OneSec
Application.OnTime SchdTime, "Sheet1.NextTick"
Etime = Etime + OneSec
End If
End Sub
Then in another cell (say, C16) I have a manually entered value which is the hourly cost rate. I have a third cell that is calculating total cost by C16*current timer value.
What I want to do is record every 5 seconds after the "StartBtn" is clicked the current time and current calculated cost in another sheet. This is what I have started:
Sub increment()
Dim x As String
Dim n As Integer
Dim Recordnext As Date
n = 0
Record = [TextBox21].Value
Recordnext = [TextBox21].Value + OneSec
Range("B13").Value = Recordnext
Do Until IsEmpty(B4)
If [TextBox21].Value = Recordnext Then ActiveCell.Copy
Application.Goto(ActiveWorkbook.Sheets("Sheet2").Range("A1").Offset(1, 0))
ActiveSheet.Paste
Application.CutCopyMode = False
n = n + 1
Recordnext = [TextBox21].Value + 5 * (OneSec)
Exit Do
End If
ActiveCell.Offset(1, 0).Select
Loop
End Sub
But it doesnt work. Any help would be appreciated.
I have tried to simplify your timer method down to what is actually needed.
Sheet1 code sheet
Option Explicit
Private Sub ResetBtn_Click()
bRun_Timer = False
'use the following if you want to remove the last time cycle
TextBox21.Value = Format(0, "hh:mm:ss")
End Sub
Private Sub StartBtn_Click()
bRun_Timer = True
dTime_Start = Now
TextBox21.Value = Format(Now - dTime_Start, "hh:mm:ss")
Range("D16").ClearContents
Call next_Increment
End Sub
Module1 code sheet
Option Explicit
Public bRun_Timer As Boolean
Public Const iSecs As Integer = 3 'three seconds
Public dTime_Start As Date
Sub next_Increment()
With Worksheets("Sheet1")
.TextBox21.Value = Format(Now - dTime_Start, "hh:mm:ss")
.Range("D16") = Sheet1.Range("C16") / 3600 * _
Second(TimeValue(Sheet1.TextBox21.Value)) '# of secs × rate/sec
Worksheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Resize(1, 2).Offset(1, 0) = _
Array(.TextBox21.Value, .Range("D16").Value)
End With
If bRun_Timer Then _
Application.OnTime Now + TimeSerial(0, 0, iSecs), "next_Increment"
End Sub
Note that the operation of transferring the data to Sheet2 is a direct value transfer¹ with no .GoTo, ActiveCell or Select.
It was not entirely clear to me what you were trying to do with the value transfer. I have stacked them one after another on Sheet1.
        
You would benefit by adding Option Explicit² to the top of all your code sheets. This requires variable declaration and if you misplace a public variable, you will quickly know.
¹ See How to avoid using Select in Excel VBA macros for more methods on getting away from relying on select and activate to accomplish your goals.
² Setting Require Variable Declaration within the VBE's Tools ► Options ► Editor property page will put the Option Explicit statement at the top of each newly created code sheet. This will avoid silly coding mistakes like misspellings as well as influencing you to use the correct variable type in the variable declaration. Variables created on-the-fly without declaration are all of the variant/object type. Using Option Explicit is widely considered 'best practice'.

Displaying Input into textbox

I am trying to display a calculation into a TextBox, but having trouble with getting it to show. I want it to show once all input fields are true.
Public Class VehicleAudit
Private Sub Calculate()
Dim validMiles As Boolean = False
Dim validPercent As Boolean = False
Dim validAvg As Boolean = False
Dim inputtedMiles As Double
Dim inputtedPercent As Double
Dim inputtedAvgCost As Double
Dim servTruck As Integer
Try
inputtedMiles = Double.Parse(txtMilesDriven.Text)
inputtedPercent = Double.Parse(txtPercent.Text)
inputtedAvgCost = Double.Parse(txtAvgCost.Text)
Catch ex As FormatException
MessageBox.Show("Please enter all values and try again")
Return
End Try
Dim cal As String = FormatCurrency(Convert.ToString(inputtedAvgCost * inputtedMiles * (1.0 + inputtedPercent))) + " dollars."
ValidateBoxes(inputtedMiles, 0, 10000, "Miles must range from 0-10000.", validMiles)
ValidateBoxes(inputtedPercent, 0.1, 0.5, "Please enter percent from .10 to .50", validPercent)
ValidateBoxes(inputtedAvgCost, 0.25, 0.75, " Please enter Average cost from .25 to .75", validAvg)
If (validAvg And validMiles And validPercent) Then
Dim totalCost As Double
If boxVehicleSelect.SelectedIndex = 9 Then
servTruck = inputtedMiles / 100 'this way we lose precision using the integer, so values below 100s are dropped.
totalCost = servTruck * 15.46
Else
totalCost = inputtedAvgCost * inputtedMiles * (1.0 + inputtedPercent)
End If
End If
End Sub
Private Sub txtTotalCost_TextChanged(ByVal Calculate As String, e As EventArgs) Handles txtTotalCost.TextChanged
End Sub
You appear to already have a block that runs when all three values are "valid". Simply output that value at the bottom of it:
If (validAvg And validMiles And validPercent) Then
Dim totalCost As Double
If boxVehicleSelect.SelectedIndex = 9 Then
servTruck = inputtedMiles / 100 'this way we lose precision using the integer, so values below 100s are dropped.
totalCost = servTruck * 15.46
Else
totalCost = inputtedAvgCost * inputtedMiles * (1.0 + inputtedPercent)
End If
' Output the computed "totalCost" some where.
' Here I'm using a Textbox called "txtTotalCost":
txtTotalCost.Text = totalCost.ToString()
End If
Edit...
Also call your Calculate() method whenever one of your textboxes changes:
Private Sub TextChanged(sender As Object, e As EventArgs) Handles txtMilesDriven.TextChanged, txtAvgCost.TextChanged, txtPercent.TextChanged
Calculate()
End Sub
Note how all three textboxes are listed after the handles keyword.