Max BIN Volume under constraints for single box - excel

I have a single box with sides l, w, h (natural numbers). I have to pack this standard box to the BIN under constraints: Longest BIN side <=150, Longest BIN side + 2*(sum of other 2 sides)<=300. Based on Lagrange Multipliers the maximum BIN volume and length of sides under these constraints are 100x50x50=250000. The optimal BIN sides should be close to 100x50x50 and must have maximum volume. Now the below code works, but for a box with small sides it is taking more time. For example, if box sides are 1x1x1, then it calculates all options 150x150x150 under above constraints. If anybody has better idea how to improve this code, please help.
`Sub Macro1()
l = Sheets("list").Range("a" & 2)'45
w = Sheets("list").Range("b" & 2)'20
h = Sheets("list").Range("c" & 2)'30
result = 150 / l
ll = Math.Round(150 / l, 0)
If result <> ll Then
ll = ll + 1
Else
End If
result = 150 / w
lw = Math.Round(150 / w, 0)
If result <> lw Then
lw = lw + 1
Else
End If
result = 150 / h
lh = Math.Round(150 / h, 0)
If result <> lh Then
lh = lh + 1
Else
End If
Dim londis() As Double
Dim shortdis() As Double
Dim options() As Double
ReDim options(lw * ll * lh)
ReDim longdis(lw * ll * lh)
ReDim shortdis(lw * ll * lh)
k = 6
s = 0
`
For i = 0 To lh
For j = 0 To lw
For n = 0 To ll
summa = i * h + j * w + n * l
If summa <= 150 Then
'Sheets("list").Range("a" & k) = summa
s = s + 1
options(s) = summa
'longdis(s) = 100 - summa
'shortdis(s) = 50 - summa
If summa > 100 Then
longdis(s) = 100 - summa
Else
longdis(s) = summa - 100
End If
If summa <= 50 Then
shortdis(s) = summa - 50
Else
shortdis(s) = 50 - summa
End If
k = k + 1
Else
GoTo 1
End If
Next n
1:
Next j
Next i
For i = 1 To s - 1
For j = i + 1 To s
If shortdis(i) < shortdis(j) Then
pTemp1 = options(i)
pTemp2 = longdis(i)
pTemp3 = shortdis(i)
options(i) = options(j)
shortdis(i) = shortdis(j)
longdis(i) = longdis(j)
options(j) = pTemp1
longdis(j) = pTemp2
shortdis(j) = pTemp3
Else
End If
Next j
Next i
t = 1
maxVol = 0
pT = 0
pL = 0
prodVol = l * w * h
maxPosUnit = Int(250000 / prodVol)
maxPosVol = maxPosUnit * prodVol
Do While t < s - 2
longside = 300 - 2 * (options(t) + options(t + 1))
For i = 1 To s
If options(i) <= longside Then
vol = options(i) * options(t) * options(t + 1)
If vol > maxVol Then
maxVol = vol
pT = t
pL = i
Else
End If
Else
End If
If options(i) = longside Then
Exit Do
End If
Next i
t = t + 1
Loop
Sheets("list").Range("d" & 2) = prodVol
Sheets("list").Range("e" & 2) = maxPosUnit
'Sheets("list").Range("f" & 2) = 250000 - maxPosVol
Sheets("list").Range("a" & 3) = options(pT)
Sheets("list").Range("b" & 3) = options(pT + 1)
Sheets("list").Range("c" & 3) = options(pL)
boxVol = options(pT) * options(pT + 1) * options(pL)
Sheets("list").Range("d" & 3) = boxVol
Sheets("list").Range("e" & 3) = Int(boxVol / prodVol)
Sheets("list").Range("f" & 3) = boxVol - Int(boxVol / prodVol) * prodVol
End Sub

Related

Custom Function conditional LOGEST

I created a function that takes a range as an argument and attempts to perform a conditional LOGEST as long as the cell is not blank AND the cell does not have strike through text. However, I cannot get it to run:
Function CustomTrend(rng As Range) As Double
Dim TrendArr() As Variant
Dim ArrSpot As Integer
Dim count, countsq, countsum As Double
Dim LNy, Xsq, XxLNy As Double
Dim last As Integer
last = rng.End(xlDown).row
LNy = 0
Xsq = 0
XxLNy = 0
ArrSpot = 0
count = 0
countsq = 0
countsum = 0
For i = 1 To last Step 1
If rng.Cells(i, 1).Value <> "" And rng.Cells(i, 1).Font.Strikethrough = False Then
ArrSpot = ArrSpot + 1
count = count + 1
TrendArr(ArrSpot) = rng.Cells(i, 1).Value
End If
Next i
For k = ArrSpot To 0 Step -1
LNy = LNy + WorksheetFunction.Ln(TrendArr(ArrSpot))
XxLNy = ArrSpot * WorksheetFunction.Ln(TrendArr(ArrSpot)) + XxLNy
countsq = ArrSpot ^ 2 + countsq
countsum = countsum + ArrSpot
Next k
CustomTrend = (count * XxLNy - countsum * LNy) / (count * countsq - countsum ^ 2)
End Function
Sorted it out on my own, please see revised code below. As a note, I also had to add a .calculatefull into other parts of the code to make sure the function would update when used in a cell.
Function CustomTrend(rng As Range) As Double
Dim count, countsq, countsum As Double
Dim LNy, Xsq, XxLNy As Double
LNy = 0
Xsq = 0
XxLNy = 0
ArrSpot = 0
count = 0
countsq = 0
countsum = 0
For Each cell In rng
If cell.Value <> "" And cell.Font.Strikethrough = False Then
count = count + 1
countsum = countsum + count
LNy = LNy + WorksheetFunction.Ln(cell.Value)
XxLNy = count * WorksheetFunction.Ln(cell.Value) + XxLNy
countsq = count ^ 2 + countsq
End If
Next cell
CustomTrend = (count * XxLNy - countsum * LNy) / (count * countsq - countsum ^ 2)
End Function

Excel: Comparing text strings in Columns using VBA

I have been reading on some of the posts that others were having similar issues for comparing text strings in cells.
The results were close but not quite what the goal is so I a confident that I will get the results.
The image attached is just the desired result. Goal: Compare Old SQL (Column B) to New SQL(Column A)/change font color of the difference in Column A (if any).
image attached shows the desired result
Being 20 yrs removed, I am beyond rusty.
I have tried the leverstein (?? sorry forget the author); tried dupeword and a couple others. Just havent found the right code. I am going to keep looking at examples - I am sure someone has figured it out - just not me.
Public Sub AlignStrings()
Dim a() As Byte, b() As Byte, a_$, b_$, i&, j&, d&, u&, l&, x&, y&, f&()
Const GAP = -1
Const PAD = "$"
a = [a3].Text: b = [b3].Text 'column A &B needs to be a range
'[c2:d2].Clear
'[a1:a6].Font.Name = "Calibri"
ReDim f(0 To UBound(b) \ 2 + 1, 0 To UBound(a) \ 2 + 1)
For i = 1 To UBound(f, 1)
For j = 1 To UBound(f, 2)
x = j - 1: y = i - 1
If a(x * 2) = b(y * 2) Then
d = 1 + f(y, x)
u = 0 + f(y, j)
l = 0 + f(i, x)
Else
d = -1 + f(y, x)
u = GAP + f(y, j)
l = GAP + f(i, x)
End If
f(i, j) = Max(d, u, l)
Next
Next
i = UBound(f, 1): j = UBound(f, 2)
On Error Resume Next
Do
x = j - 1: y = i - 1
d = f(y, x)
u = f(y, j)
l = f(i, x)
Select Case True
Case Err
If y < 0 Then GoTo left Else GoTo up
Case d >= u And d >= l Or Mid$(a, j, 1) = Mid$(b, i, 1)
diag:
a_ = Mid$(a, j, 1) & a_
b_ = Mid$(b, i, 1) & b_
i = i - 1: j = j - 1
Case u > l
up:
a_ = PAD & a_
b_ = Mid$(b, i, 1) & b_
i = i - 1
Case l > u
left:
a_ = Mid$(a, j, 1) & a_
b_ = PAD & b_
j = j - 1
End Select
Loop Until i < 1 And j < 1
DecorateStrings a_, b_, [a3], [b3], PAD 'output needs to be in same
columns/range

How to output results set of every iteration in VBA?

How do I output the sets of results from each iteration in a new line in the worksheet? i.e looping through all the possible combinations of (i,j,k,l,m)
avg protein1 = (0,j,k,l,m)
avg protein2 = (1,j,k,l,m)
avg protein3 = (2,j,k,l,m) ...
.. .
avg protein (n-2) = (i,j,k,l,0)
avg protein (n-1) = (i,j,k,l,1)
avg protein (n) = (i,j,k,l,2)
Here's the code from a modified knapsack optimization problem (code works). It maximizes the avg protein value from 5 different bins subject to margin constraint from each bin.
Option Explicit
Sub ProteinCalc()
Dim limit As Double, tol As Double, Protein As Double, Margin As Double, averageprotein As Double, maximumMargin As Double
Dim i, j, k, l, m As Integer
Dim Proteini, Proteinj, Proteink, Proteinl, Proteinm As Double
Dim Margini, Marginj, Margink, Marginl, Marginm As Double
Worksheets("simplecalc").Range("B19:H23").ClearContents
Worksheets("simplecalc").Range("B4:F4").ClearContents
limit = Range("D6").Value 'declare max protein target on blend
tol = Range("G6").Value 'declare tolarance on protein blend to get close to max protien target
maximumMargin = Range("G8").Value 'declare minimum margin $/MT want to make
Proteini = Range("B2").Value
Proteinj = Range("C2").Value
Proteink = Range("D2").Value
Proteinl = Range("E2").Value
Proteinm = Range("F2").Value
Margini = Range("B3").Value
Marginj = Range("C3").Value
Margink = Range("D3").Value
Marginl = Range("E3").Value
Marginm = Range("F3").Value
For i = 0 To 2 'loop up to 2 to signify a possible double spot for train at station i
For j = 0 To 2
For k = 0 To 2
For l = 0 To 2
For m = 0 To 2
Protein = (Proteini * i + Proteinj * j + Proteink * k + Proteinl * l + Proteinm * m) / 5 'linear avg of 5 stations
Margin = (Margini * i + Marginj * j + Margink * k + Marginl * l + Marginm * m) / 5 ' linear avg of margin from 5 stations
If Margin > maximumMargin And Protein <= limit Then
Range("B4").Value = i
Range("C4").Value = j
Range("D4").Value = k
Range("E4").Value = l
Range("F4").Value = m
averageprotein = Protein
maximumMargin = Margin
Debug.Print i
End If
If m >= 0 And m <= 2 Then
Worksheets("simplecalc").Range("B23").Value = averageprotein
Worksheets("simplecalc").Range("C23").Value = Proteini
Worksheets("simplecalc").Range("D23").Value = Proteinj
Worksheets("simplecalc").Range("E23").Value = Proteink
Worksheets("simplecalc").Range("F23").Value = Proteinl
Worksheets("simplecalc").Range("G23").Value = Proteinm
Worksheets("simplecalc").Range("H23").Value = m
Worksheets("simplecalc").Range("i23").Value = l
Worksheets("simplecalc").Range("j23").Value = k
Worksheets("simplecalc").Range("k23").Value = j
Worksheets("simplecalc").Range("l23").Value = i
End If
Next m
If l >= 0 And l <= 2 Then
Worksheets("simplecalc").Range("B22").Value = averageprotein
Worksheets("simplecalc").Range("C22").Value = Proteini
Worksheets("simplecalc").Range("D22").Value = Proteinj
Worksheets("simplecalc").Range("E22").Value = Proteink
Worksheets("simplecalc").Range("F22").Value = Proteinl
Worksheets("simplecalc").Range("G22").Value = Proteinm
Worksheets("simplecalc").Range("H22").Value = l
End If
Next l
If k >= 0 And k <= 2 Then
Worksheets("simplecalc").Range("B21").Value = averageprotein
Worksheets("simplecalc").Range("C21").Value = Proteini
Worksheets("simplecalc").Range("D21").Value = Proteinj
Worksheets("simplecalc").Range("E21").Value = Proteink
Worksheets("simplecalc").Range("F21").Value = Proteinl
Worksheets("simplecalc").Range("G21").Value = Proteinm
Worksheets("simplecalc").Range("H21").Value = k
End If
Next k
If j >= 0 And j <= 2 Then
Worksheets("simplecalc").Range("B20").Value = averageprotein
Worksheets("simplecalc").Range("C20").Value = Proteini
Worksheets("simplecalc").Range("D20").Value = Proteinj
Worksheets("simplecalc").Range("E20").Value = Proteink
Worksheets("simplecalc").Range("F20").Value = Proteinl
Worksheets("simplecalc").Range("G20").Value = Proteinm
Worksheets("simplecalc").Range("H20").Value = j
End If
Next j
If i >= 0 And i <= 2 Then
Worksheets("simplecalc").Range("B19").Value = averageprotein
Worksheets("simplecalc").Range("C19").Value = Proteini
Worksheets("simplecalc").Range("D19").Value = Proteinj
Worksheets("simplecalc").Range("E19").Value = Proteink
Worksheets("simplecalc").Range("F19").Value = Proteinl
Worksheets("simplecalc").Range("G19").Value = Proteinm
Worksheets("simplecalc").Range("H19").Value = i
End If
Next i
Range("B6").Value = averageprotein
Range("B8").Value = maximumMargin
End Sub
You will need to up the row number in every iteration before writing the value to the worksheet. So, declare an iteration counter variable:
Dim itrCount As Long
then change this:
If m >= 0 And m <= 2 Then
Worksheets("simplecalc").Range("B23").Value = averageprotein
Worksheets("simplecalc").Range("C23").Value = Proteini
to this:
If m >= 0 And m <= 2 Then
itrCount = itrCount + 1
Worksheets("simplecalc").Range("B23").Offset(itrCount).Value = averageprotein
Worksheets("simplecalc").Range("C23").Offset(itrCount).Value = Proteini
in every loop accordingly.
That's the minimum needed to make it work, there are other improvements you can apply here.

creating excel charts with dynamic data range in vb.net

I am creating an Excel pie and bar charts from exported data pragmatically. Here I need to pick the cell range dynamically. For example, after header name all data should be picked up until cell contains "TOTAL" line.
Below is my current code.
If String.IsNullOrEmpty(HttpContext.Current.Request.QueryString("oversight")) Then 'This is Summary Level
Dim worksheet2 As ExcelWorksheet = pkg.Workbook.Worksheets.Add("Chart - CY Consumable")
worksheet2.DefaultColWidth = 15
Dim consumableChart As OfficeOpenXml.Drawing.Chart.ExcelPieChart = worksheet2.Drawings.AddChart("ConsumableChart", OfficeOpenXml.Drawing.Chart.eChartType.Pie)
Dim r1, r2 As ExcelRange
r1 = worksheet.Cells("A6:A12") // here I want it to be selected dynamically after header and before the total line
r2 = worksheet.Cells("B6:B12")
consumableChart.Series.Add(r2, r1)
consumableChart.Style = OfficeOpenXml.Drawing.Chart.eChartStyle.Style2
consumableChart.Title.Text = "FY 2018 Consumable by Regional & Central Oversight Programs"
consumableChart.Legend.Remove()
consumableChart.SetPosition(1, 1, 1, 1)
consumableChart.SetSize(1040, 880)
consumableChart.DataLabel.ShowLeaderLines = True
consumableChart.DataLabel.ShowCategory = True
consumableChart.DataLabel.ShowPercent = True
Thanks in advance.
Dim totalRow As Integer
If ds.Tables.Count > 0 Then
Dim k As Integer = 0
For j As Integer = 0 To ds.Tables(0).Columns.Count - 1
If Not skip.Contains(j) Then
If columnNames.Count > 0 AndAlso columnNames.Count = (ds.Tables(0).Columns.Count - skip.Count) Then
strTitle = columnNames(k)
Else
strTitle = ds.Tables(0).Columns(j).ColumnName.Replace("_", " ")
End If
worksheet.Cells(p, k + 1).Value = strTitle
k = k + 1
End If
Next
Dim i As Integer = p + 1
For Each r As DataRow In ds.Tables(0).Rows
If includeTotals OrElse (Not r.Item(2).ToString().Trim().ToUpper().StartsWith("TOTAL") AndAlso _
Not r.Item(2).ToString().Trim().ToUpper().StartsWith("SUBTOTAL") AndAlso _
Not r.Item(2).ToString().Trim().ToUpper().StartsWith("TOTAL") AndAlso _
Not r.Item(2).ToString().Trim().ToUpper().StartsWith("SUBTOTAL")) Then
k = 0
For j As Integer = 0 To ds.Tables(0).Columns.Count - 1
If Not skip.Contains(j) Then
If r.Item(j) Is DBNull.Value Then
worksheet.Cells(i, k + 1).Value = ""
Else
If k = 0 Then
worksheet.Cells(i, k + 1).Style.Numberformat.Format = "#"
worksheet.Cells(i, k + 1).Value = r.Item(j).ToString()
Else
worksheet.Cells(i, k + 1).Value = r.Item(j)
End If
End If
// Checking if it is first col last row
If r.Item(j).ToString().Contains("TOTAL") Then
totalRow = i
End If
If r.Item(j).GetType().Name = "Decimal" Then
If roundUp Then
If useParens Then
worksheet.Cells(i, k + 1).StyleID = 2
Else
worksheet.Cells(i, k + 1).StyleID = 2 '4
End If
Else
If useParens Then
worksheet.Cells(i, k + 1).StyleID = 1
Else
worksheet.Cells(i, k + 1).StyleID = 1 '3
End If
End If
End If
k = k + 1
End If
Next
i = i + 1
End If
Next
End If
If String.IsNullOrEmpty(HttpContext.Current.Request.QueryString("oversight")) Then 'This is Summary Level
Dim worksheet2 As ExcelWorksheet = pkg.Workbook.Worksheets.Add("Chart - CY Consumable")
worksheet2.DefaultColWidth = 15
// showing the criteria
p = 1
If includeCriteria Then
Try
Dim reportTitle As String = String.Empty
reportTitle = "Central/Regional Oversight Programs"
Dim sb As StringBuilder = New StringBuilder()
sb.Append(reportTitle)
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
sb.Append("Budget Fiscal Year : ")
sb.Append(HttpContext.Current.Session("bfy"))
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
sb.Append("Currently viewing transactions from inception through ")
Dim fm As Integer = CInt(HttpContext.Current.Session("fm"))
If fm < 4 Then
sb.Append(MonthName(fm + 9))
sb.Append(" ")
sb.Append(CInt(HttpContext.Current.Session("fy")) - 1)
Else
sb.Append(MonthName(fm - 3))
sb.Append(" ")
sb.Append(HttpContext.Current.Session("fy"))
End If
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
If String.IsNullOrEmpty(HttpContext.Current.Request.QueryString("division")) Then
sb.Append("Fund Center(s) : ALL")
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
Else
sb.Append("Fund Center(s) : ")
sb.Append(HttpContext.Current.Request.QueryString("division"))
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
End If
If String.IsNullOrEmpty(HttpContext.Current.Request.QueryString("fa5")) Then
sb.Append("Func Area 5 : ALL")
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
Else
sb.Append("Func Area 5 : ")
sb.Append(HttpContext.Current.Request.QueryString("fa5"))
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
End If
If Not String.IsNullOrEmpty(HttpContext.Current.Request.QueryString("oversight")) Then
sb.Append("Oversight Program - ")
sb.Append(HttpContext.Current.Request.QueryString("oversight"))
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
End If
sb.Append("FBMS data as of ")
sb.Append(HttpContext.Current.Application("lastUpdated_BIA"))
sb.Append(" at close of business.")
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
worksheet2.Cells(p, 1).Value = ""
p = p + 1
Catch ex As Exception
For r As Integer = 1 To p - 1
worksheet2.DeleteRow(1, True)
Next
p = 1
End Try
End If
//create chart in new tab
Dim consumableChart As OfficeOpenXml.Drawing.Chart.ExcelPieChart = worksheet2.Drawings.AddChart("ConsumableChart", OfficeOpenXml.Drawing.Chart.eChartType.Pie)
Dim r1, r2 As ExcelRange
// setting the value to check the last row
Dim startColumn As String = "A"
Dim endColumn As String = "B"
Dim startIndex As Integer = 8 // Index where to start
Dim endIndex As Integer = totalRow - 1 'this is determined based on the TOTAL Line from above code
// checking and setting the values and label of pie chart
r1 = worksheet.Cells(String.Concat(startColumn, startIndex.ToString(), ":", startColumn, endIndex))
r2 = worksheet.Cells(String.Concat(endColumn, startIndex.ToString(), ":", endColumn, endIndex))
consumableChart.Series.Add(r2, r1)
consumableChart.Style = OfficeOpenXml.Drawing.Chart.eChartStyle.Style2
consumableChart.Title.Text = "FY 2018 Consumable by Regional & Central Oversight Programs"
consumableChart.Legend.Remove()
consumableChart.SetPosition(5, 5, 5, 5)
consumableChart.SetSize(1040, 880)
consumableChart.DataLabel.ShowLeaderLines = True
consumableChart.DataLabel.ShowCategory = True
consumableChart.DataLabel.ShowPercent = True

Pairs Trading VBA Loop

I have a problem when I want to build a pairs trading automation using Excel VBA.
My strategy is to open a position (OTC_Sell or OTC_Buy) when the spreads of two stocks hit +/- 2 standard deviation, and to close a position (CTC_buy or CTC_sell) when the spreads of two stocks hit +/- 4 standard deviation or hit back to the mean. Once the position is closed, I can open another position once I received another open trade condition(OTC).
However, when I run the code, it seems that the loop only runs one time since I can only get one trade (highlighted in yellow).After this cell, I can only get zeros but no other trade signals. I re-run the code starting from that cell beside the original column and get another trade (highlighted in green).still, I get all zeros afterwards. Whereas I want to get all trade signals within one column.
Function SignalCTC(Price1, Price2, Mean, SD, StopLoss)
Dim i, j, k, m, n, o, p, numRows, numOTC, order, list, flag, finish
numRows = Price1.Rows.Count
Dim SignalColOTC()
ReDim SignalColOTC(numRows, 1)
Dim Price1Col()
ReDim Price1Col(numRows)
Dim Price2Col()
ReDim Price2Col(numRows)
Dim P_Ratio()
ReDim P_Ratio(numRows)
'Loop 1
For i = 1 To numRows
P_Ratio(i) = Price1(i) / Price2(i)
Next i
UpperLim = Mean + (2 * SD)
LowerLim = Mean - (2 * SD)
Count = 0
flag = 0
For i = 1 To numRows
If (Count = 0 And (P_Ratio(i) < UpperLim) And (P_Ratio(i) > LowerLim)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "Wait&See"
ElseIf (Count = 0 And (P_Ratio(i) > UpperLim)) Then
Count = 1
flag = 1
SignalColOTC(i, 1) = "Wait&See"
ElseIf (Count = 0 And (P_Ratio(i) < LowerLim)) Then
Count = 1
flag = -1
SignalColOTC(i, 1) = "Wait&See"
ElseIf (Count = 1 And flag = 1 And (P_Ratio(i) < UpperLim) And (P_Ratio(i) > Mean)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "OTC_Sell"
ElseIf (Count = 1 And flag = -1 And (P_Ratio(i) > LowerLim) And (P_Ratio(i) < Mean)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "OTC_Buy"
Else: SignalColOTC(i, 1) = "Wait&See"
End If
Next i
numOTC = 0
order = 0
list = 0
For i = 1 To numRows
If (SignalColOTC(i, 1) = "OTC_Sell") Or (SignalColOTC(i, 1) = "OTC_Buy") Then
numOTC = numOTC + 1
Else: numOTC = numOTC
End If
Next i
'Dim x
'Loop 2
Dim SignalColCTC()
ReDim SignalColCTC(numRows, numOTC)
For n = 1 To numRows
If (SignalColOTC(n, 1) = "OTC_Sell") Then
list = list + 1
SignalColCTC(n, list) = "OTC_Sell"
For j = n + 1 To numRows
If ((P_Ratio(j) < Mean) Or (Abs(P_Ratio(j)) > (1 + StopLoss) * Abs(P_Ratio(n)))) Then
SignalColCTC(j, list) = "CTC_Buy"
Else: SignalColCTC(j, list) = "Wait&See"
End If
Next j
ElseIf (SignalColOTC(n, 1) = "OTC_Buy") Then
list = list + 1
SignalColCTC(n, list) = "OTC_Buy"
For k = n + 1 To numRows
If ((P_Ratio(k) > Mean) Or (Abs(P_Ratio(k)) < (1 - StopLoss) * Abs(P_Ratio(n)))) Then
SignalColCTC(k, list) = "CTC_Sell"
Else: SignalColCTC(k, list) = "Wait&See"
End If
Next k
End If
Next n
'Loop 3
For o = 1 To numRows
For list = 1 To numOTC
If (SignalColCTC(o, list) = "CTC_Buy") Or (SignalColCTC(o, list) = "CTC_Sell") Then
For p = o + 1 To numRows
SignalColCTC(p, list) = "0"
Next p
End If
Next list
Next o
SignalCTC = SignalColCTC
End Function
Should this be a problem with Loop 3? I tried to put both loop 2 and loop 3 under one loop, but I get not even one trade signal but all zero this time.
Function SignalCTC(Price1, Price2, Mean, SD, StopLoss)
Dim i, j, k, m, n, o, p, numRows, numOTC, order, list, flag, finish
numRows = Price1.Rows.Count
Dim SignalColOTC()
ReDim SignalColOTC(numRows, 1)
Dim Price1Col()
ReDim Price1Col(numRows)
Dim Price2Col()
ReDim Price2Col(numRows)
Dim P_Ratio()
ReDim P_Ratio(numRows)
'Loop 1
For i = 1 To numRows
P_Ratio(i) = Price1(i) / Price2(i)
Next i
UpperLim = Mean + (2 * SD)
LowerLim = Mean - (2 * SD)
Count = 0
flag = 0
For i = 1 To numRows
If (Count = 0 And (P_Ratio(i) < UpperLim) And (P_Ratio(i) > LowerLim)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "Wait&See"
ElseIf (Count = 0 And (P_Ratio(i) > UpperLim)) Then
Count = 1
flag = 1
SignalColOTC(i, 1) = "Wait&See"
ElseIf (Count = 0 And (P_Ratio(i) < LowerLim)) Then
Count = 1
flag = -1
SignalColOTC(i, 1) = "Wait&See"
ElseIf (Count = 1 And flag = 1 And (P_Ratio(i) < UpperLim) And (P_Ratio(i) > Mean)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "OTC_Sell"
ElseIf (Count = 1 And flag = -1 And (P_Ratio(i) > LowerLim) And (P_Ratio(i) < Mean)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "OTC_Buy"
Else: SignalColOTC(i, 1) = "Wait&See"
End If
Next i
numOTC = 0
order = 0
list = 0
For i = 1 To numRows
If (SignalColOTC(i, 1) = "OTC_Sell") Or (SignalColOTC(i, 1) = "OTC_Buy") Then
numOTC = numOTC + 1
Else: numOTC = numOTC
End If
Next i
'Dim x
x=1
For Y=x to numRows
'Loop 2
Dim SignalColCTC()
ReDim SignalColCTC(numRows, numOTC)
For n = x To numRows
If (SignalColOTC(n, 1) = "OTC_Sell") Then
list = list + 1
SignalColCTC(n, list) = "OTC_Sell"
For j = n + 1 To numRows
If ((P_Ratio(j) < Mean) Or (Abs(P_Ratio(j)) > (1 + StopLoss) * Abs(P_Ratio(n)))) Then
SignalColCTC(j, list) = "CTC_Buy"
Else: SignalColCTC(j, list) = "Wait&See"
End If
Next j
ElseIf (SignalColOTC(n, 1) = "OTC_Buy") Then
list = list + 1
SignalColCTC(n, list) = "OTC_Buy"
For k = n + 1 To numRows
If ((P_Ratio(k) > Mean) Or (Abs(P_Ratio(k)) < (1 - StopLoss) * Abs(P_Ratio(n)))) Then
SignalColCTC(k, list) = "CTC_Sell"
Else: SignalColCTC(k, list) = "Wait&See"
End If
Next k
End If
Next n
'Loop 3
For o = x To numRows
For list = 1 To numOTC
If (SignalColCTC(o, list) = "CTC_Buy") Or (SignalColCTC(o, list) = "CTC_Sell") Then
For p = o + 1 To numRows
SignalColCTC(p, list) = "0"
Next p
End If
x = p
Next list
Next o
Next Y
SignalCTC = SignalColCTC
End Function
interesting problem here. had a quick look through your code and nothing jumps out. Loop 3 seems fine to me, and didn't seem critical anyway.
maybe the logic you're implementing isn't quite what you want? I've added my commented version (no real changes except tabbing). might be a good approach for you to do similar to check loop 1 and 2 are doing what you want them to.
also, I assume mean and SD inputs are of the price ratios? why not just work them out in the function?
lastly, make sure when you're declaring variables in future you specify data types. can avoid errors and confusion down the line. e.g. 'dim i as integer'
Function SignalCTC(Price1, Price2, Mean, SD, StopLoss)
Dim i, j, k, m, n, o, p, numRows, numOTC, order, list, flag, finish
numRows = Price1.Rows.Count
Dim SignalColOTC()
ReDim SignalColOTC(numRows, 1)
Dim Price1Col()
ReDim Price1Col(numRows)
Dim Price2Col()
ReDim Price2Col(numRows)
Dim P_Ratio()
ReDim P_Ratio(numRows)
'calculate ratios
For i = 1 To numRows
P_Ratio(i) = Price1(i) / Price2(i)
Next i
UpperLim = Mean + (2 * SD)
LowerLim = Mean - (2 * SD)
Count = 0
flag = 0
'Loop 1
'identify possible opening events
For i = 1 To numRows
'if no events (within limits), reset
If (Count = 0 And (P_Ratio(i) < UpperLim) And (P_Ratio(i) > LowerLim)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "Wait&See"
'if exceeds for the first time
ElseIf (Count = 0 And (P_Ratio(i) > UpperLim)) Then
Count = 1
flag = 1
SignalColOTC(i, 1) = "Wait&See"
'if under limit for the first time
ElseIf (Count = 0 And (P_Ratio(i) < LowerLim)) Then
Count = 1
flag = -1
SignalColOTC(i, 1) = "Wait&See"
'if already exceeded once and now within limits
ElseIf (Count = 1 And flag = 1 And (P_Ratio(i) < UpperLim) And (P_Ratio(i) > Mean)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "OTC_Sell"
'if were under limit once and now within limits
ElseIf (Count = 1 And flag = -1 And (P_Ratio(i) > LowerLim) And (P_Ratio(i) < Mean)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "OTC_Buy"
Else
SignalColOTC(i, 1) = "Wait&See"
End If
Next i
numOTC = 0
order = 0
list = 0
'count opening events
For i = 1 To numRows
If (SignalColOTC(i, 1) = "OTC_Sell") Or (SignalColOTC(i, 1) = "OTC_Buy") Then
numOTC = numOTC + 1
Else
'numOTC = numOTC 'redundant, don't need
End If
Next i
'Loop 2
'identify closing events
Dim SignalColCTC()
ReDim SignalColCTC(numRows, numOTC)
For n = 1 To numRows
If (SignalColOTC(n, 1) = "OTC_Sell") Then
list = list + 1 'scroll to next column
SignalColCTC(n, list) = "OTC_Sell" 'we know this is the sale event
For j = n + 1 To numRows 'remaining rows
'if hits mean, or makes a big loss
If ((P_Ratio(j) < Mean) Or (Abs(P_Ratio(j)) > (1 + StopLoss) * Abs(P_Ratio(n)))) Then
SignalColCTC(j, list) = "CTC_Buy" 'close position
Else
SignalColCTC(j, list) = "Wait&See"
End If
Next j
ElseIf (SignalColOTC(n, 1) = "OTC_Buy") Then 'logic repeated for sale
list = list + 1
SignalColCTC(n, list) = "OTC_Buy"
For k = n + 1 To numRows
If ((P_Ratio(k) > Mean) Or (Abs(P_Ratio(k)) < (1 - StopLoss) * Abs(P_Ratio(n)))) Then
SignalColCTC(k, list) = "CTC_Sell"
Else
SignalColCTC(k, list) = "Wait&See"
End If
Next k
End If
Next n
'Loop 3
'just filling zeros after position is closed
For o = 1 To numRows
For list = 1 To numOTC
If (SignalColCTC(o, list) = "CTC_Buy") Or (SignalColCTC(o, list) = "CTC_Sell") Then
For p = o + 1 To numRows
SignalColCTC(p, list) = "0"
Next p
End If
Next list
Next o
SignalCTC = SignalColCTC
End Function
EDIT:
Looking through the procedure, I expect the output matrix will look something like:
SignalColCTC:
OTC_Buy Null Null
Wait&See Null Null
Wait&See OTC_Sell Null
Wait&See Wait&See Null
CTC_Sell Wait&See Null
0 CTC_Buy OTC_Buy
0 0 Wait&See
(N.B. I think nulls become zeros later)
Which seems reasonable to me. Maybe what you are trying to do is transform the pairs into a single column? It seems in the image you uploaded that this is what you want.

Resources