variable has different value then operator - c#

First time poster, c# beginner.
Problem:
Some values result in incorrect calculations, though the operator shows a correct value (when hovering over it in debug)
Variable value should be: 49.9006...
But instead 47.4344... is stored.
Program:
Split a spiral into arc segments.
Input: straight line and a curve (curve being a circle or an arc)
Get Arc coordinates, center point & angle.
Code snippet: (all variables are defined as doubles, except for i & iNe as these are counters thus defined as int)
for (i = 0; i < 20; i++)
{
iNe = i + 1;
if (i == 0)
nRay = 0;
else
nRay = this.RadiusBase / i;
nRayNe = this.RadiusBase / iNe;
nAng = this.Alpha * i;
nAngNe = this.Alpha * iNe;
if (i == 0)
{
cumAng = 0;
cumAngNe = cumAng + nAngNe;
}
else
{
cumAng = nAng + cumAng;
cumAngNe = cumAng + nAngNe;
}
nSin = Math.Sin(cumAng);
nSinNe = Math.Sin(cumAngNe);
nCos = Math.Cos(cumAng);
nCosNe = Math.Cos(cumAngNe);
n1minCos = 1 - nCos;
nXjonc = nXcp + ((double)iNe * (nXcpNe - nXcp));
nYjonc = nYcp - ((double)iNe * (nYcp - nYcpNe));
What am i doing wrong?

Related

Calculate EMA for MACD with 2 lines indicator in C#

I'm trying to write an indicator script that will plot the MACD with 2 lines in a practice trading tool.
At the moment, I'm following the formula which is using the EMA formula to calculate it.
I'm able to plot the chart. But somehow my indicator result does not have the exact same result as the one on meta trader 4 or on trading view. The indicator result on these apps is exactly the same.
I think I have missed something when I try to convert from the formula to actual code. Please help me fix it. Thank you.
Here is the part that will calculate the EMA.
/// ==================================================================
/// ======================== calculations ============================
/// ==================================================================
public void Calculate()
{
for (int i = 0; i < Bars.Length; i++){
if (i >= SlowEMA) {
MACD[i] = CalculateEMA(FastEMA, i) - CalculateEMA(SlowEMA, i);
Signal[i] = CalculateEMA_MACD(MACD, SignalEMA, i);
Histogram[i] = MACD[i] - Signal[i];
}
}
}
private double CalculateEMA(int Period, int index)
{
var currentValue = 0d;
var currentEMA = 0d;
var yesterdayEMA = 0d;
var smooth = 2d;
var multiplier = smooth / (1 + Period);
for (int i = 0; i < Period; i++){
currentValue = GetPrice(index + i - Period);
currentEMA = (currentValue * multiplier) + (yesterdayEMA * (1 - multiplier));
yesterdayEMA = currentEMA;
};
return yesterdayEMA;
}
private double CalculateEMA_MACD(double[] MACD, int Period, int index)
{
var currentValue = 0d;
var currentEMA = 0d;
var yesterdayEMA = 0d;
var smooth = 2d;
var multiplier = smooth / (1 + Period);
for (int i = 0; i < Period; i++){
currentValue = MACD[index + i - Period];
currentEMA = (currentValue * multiplier) + (yesterdayEMA * (1 - multiplier));
yesterdayEMA = currentEMA;
};
return yesterdayEMA;
}
private double GetPrice(int index)
{
Bar bar = Bars[index];
switch (Source)
{
case Sources.Close:
return bar.Close;
case Sources.Open:
return bar.Open;
case Sources.High:
return bar.High;
case Sources.Low:
return bar.Low;
case Sources.MedianPrice:
return (bar.High + bar.Low) / 2;
case Sources.TypicalPrice:
return (bar.High + bar.Low + bar.Close) / 3;
case Sources.WeightedClose:
return (bar.High + bar.Low + bar.Close + bar.Close) / 4;
}
throw new NotSupportedException("Unsupported price source type: " + Source);
}
It looks like your logic for EMA calculation is wrong. Based on your code, yesterdayEMA is always 0 and therefore right part of EMA equation is also 0.
private double CalculateEMA(int Period, int index)
{
...
var yesterdayEMA = 0D;
...
currentEMA = (currentValue * multiplier) + (yesterdayEMA * (1 - multiplier));
currentEMA = (currentValue * multiplier) + 0
...
}
You need to store yesterdayEMA outside of CalculateEMA and pass it as parameter for recursive calculation.
0 comes true in the first cycle, but yesterday EMA = current EMA; It starts to take values different from 0 in the next cycle due to its equality.

How to loop through a range of cells in Excel using Excel-DNA to build the UDF?

I'm building a UDF using C# and Excel-DNA. However I hit a brick wall when I was trying loop though the range of cells that is one of the UDF parameters. My first tried was to tranform that range of cells into an array in C#, but I don't know how to do it using Excel-DNA. I'm using the following VBA code to build my C# code.
Function my_UDF(stk, F)
Dim i As Integer
z = stk
k = 0
i = 1
sum_if = 0
count_if = 0
Do Until i = 30
'If F(i) > 0 Then
If z >= F(i) Then
z = z - F(i)
If F(i) > 0 Then
k = k + 1
sum_if = sum_if + F(i)
count_if = count_if + 1
End If
Else
k = k + (z / F(i))
z = 0
End If
i = i + 1
Loop
If z > 0 Then k = k + (z / (sum_if / count_if))
my_UDF = k
End Function
In C#, I'm trying to come with something like this:
using ExcelDna.Integration;
namespace my_project
{
public class my_UDF_class
{
[ExcelFunction(Name = "my_UDF_function")]
public static double my_UDF_function(double stk, double f)
{
// transform range of cells into array?
int i = 1;
double c = 0;
double sum_f = 0;
double count_f = 0;
while (i > 30)
{
if (stk >= f(i))
{
stk = stk - f(i);
if (f(i) > 0)
{
c = c + 1;
sum_f = sum_f + f(i);
count_f = count_f + 1;
}
}
else
{
c = c + (stk / f(i));
stk = 0;
}
i++;
}
if (stk > 0)
{
c = c + (stk / (sum_f / count_f));
}
return c;
}
}
}
Perharps, if there's a way to loop through the cells directly, I don't even need an array.
To get an array of values in your UDF, you'd set the type of the matching parameter to double[] for a simple list, double[,] for a 2D range or maybe object[,] if you're expecting more than numbers.
So your function signature will probably be:
public static double my_UDF_function(double stk, double[] f)
And you might use the items with code like this:
double total = 0;
for (int i = 0; i < f.Length; i++)
{
total = total + f[i];
}
Note that arrays in C# are 0-based.
You can get the number of items in the array with f.Length.
For 2D arrays you get the number of items in the two dimension with f.GetLength(0) and g.GetLength(1).
You could also do all of this using VB.NET instead of C#.

Points on chart graphic don't fit y-lines

Points on my second chart don't fit y-axis as you can see here:
Points values are exactly 50.0000, 49.9999, 49.9998 and 50.0001. But they are not on lines. And when I add point and with it increase number of values on y-axis, then points would fit y-axis, like in this picture.
Here is my code (sorry for Serbian text values)
TacnostVage tacnost = bazaPodataka.UcitajTacnostVage(Convert.ToString(dataGridView2.SelectedRows[0].Cells[2].Value), Convert.ToInt32(comboBox18.Text));
List<TestTacnostVage> testoviTacnost = bazaPodataka.UcitajTestoveTacnostVage(Convert.ToString(dataGridView2.SelectedRows[0].Cells[2].Value), Convert.ToInt32(comboBox18.Text));
chart2.ChartAreas.Clear();
chart2.Series.Clear();
prikažiToolStripMenuItem.DropDownItems.Clear();
tabeluToolStripMenuItem.DropDownItems.Clear();
string format = Convert.ToString(vaga.Podeljak);
format = format.Remove(format.Length - 1, 1) + "0";
if (testoviTacnost.Count != 0)
{
for (int i = 0; i < tacnost.NominalneMase.Count(); i++)
{
ChartArea area = new ChartArea();
Series series = new Series();
area.AxisY.MajorGrid.LineColor = Color.LightGray;
area.AxisX.MajorGrid.LineColor = Color.LightGray;
area.AxisY.LabelStyle.Format = format;
area.BorderColor = Color.LightGray;
area.BorderDashStyle = ChartDashStyle.Solid;
area.AxisY.Interval = vaga.Podeljak;
area.Name = "ChartArea" + (i + 1);
series.ChartType = SeriesChartType.Point;
series.ChartArea = "ChartArea" + (i + 1);
series.Name = "Tačka" + (i + 1);
string text = "";
TegoviTacnostVaga tegoviTacnost = bazaPodataka.UcitajTegoveTacnostVage(Convert.ToString(dataGridView2.SelectedRows[0].Cells[2].Value), Convert.ToInt32(comboBox18.Text), i);
if (tegoviTacnost != null)
{
for (int j = 0; j < tegoviTacnost.Proizvodjac.Count(); j++)
{
text += tegoviTacnost.Proizvodjac[j] + " ";
text += tegoviTacnost.SerijskiBrojevi[j] + " ";
text += tegoviTacnost.NominalneMase[j] + "g";
text += (j == tegoviTacnost.Proizvodjac.Count() - 1 ? "" : "\n");
}
}
series.LegendText = (text == "" ? "Nema podataka" : text);
for (int j = 0; j < testoviTacnost.Count(); j++)
series.Points.AddXY(testoviTacnost[j].RedniBrojTesta, testoviTacnost[j].RezultatiMerenja[i]);
area.AxisY.StripLines.Add(new StripLine() { BorderColor = Color.Red, IntervalOffset = (tacnost.RezultatiMerenja[i].Average() + koeficijentTacnost * ponovljivost.ReferentnaVrednost), Text = "Gornja granica: " + Convert.ToDouble(tacnost.RezultatiMerenja[i].Average() + koeficijentTacnost * ponovljivost.ReferentnaVrednost).ToString(format) });
area.AxisY.StripLines.Add(new StripLine() { BorderColor = Color.Red, IntervalOffset = (tacnost.RezultatiMerenja[i].Average() - koeficijentTacnost * ponovljivost.ReferentnaVrednost), Text = "Donja granica: " + Convert.ToDouble(tacnost.RezultatiMerenja[i].Average() - koeficijentTacnost * ponovljivost.ReferentnaVrednost).ToString(format) });
area.AxisY.Maximum = area.AxisY.StripLines[0].IntervalOffset + area.AxisY.Interval;
if (series.Points.FindMaxByValue().YValues[0] >= area.AxisY.Maximum)
area.AxisY.Maximum = series.Points.FindMaxByValue().YValues[0] + area.AxisY.Interval;
area.AxisY.Minimum = area.AxisY.StripLines[1].IntervalOffset - area.AxisY.Interval;
if (series.Points.FindMinByValue().YValues[0] <= area.AxisY.Minimum)
area.AxisY.Minimum = series.Points.FindMinByValue().YValues[0] - area.AxisY.Interval;
chart2.ChartAreas.Add(area);
chart2.Series.Add(series);
}
}
I found solution, but I'm not sure if this explanation is true. The problem was Axis-Y maximum. Charts Axis-Y interval was 0.0001 (4 decimals), but in my code, I put maximum to be StripLines IntervalOffset (which was more than 4 decimals) plus Charts Interval (in result that is more than 4 decimals). So probably this happens when your Chars Axis-Y Maximum and your Interval (if you set Interval) have different number of decimals. So I just simply rounded Strip Lines InvervalOffset to 4 decimals (in this case), and put Axis-Y Maximum to have 4 decimals like Interval has.

choosing a next point in boundary

I'm trying to apply bound hall algorithm on set of points which are deployed randomly.
I based on the angle between the previous point and the neighborhood points of the current point to choose the next point with minimal angel.
What i'm asking for is in some cases the boundary stop generating any point and I've actually debugged the code many times and couldn't figure out what the problem.
The pic of case and the code are given below.
ArrayList angles = new ArrayList();
for (int s = 0; s < node.SensorNeighbors.Count; s++)
{
Node n = node.SensorNeighbors[s];
if (backboneNodes.Count != 1) // backboneNode is array hase nodes in boundary
{
Node previous = backboneNodes[backboneNodes.Count - 2];
Double Angle = Math.Atan2(previous.y - node.y, previous.x - node.x) - Math.Atan2(n.y - node.y, n.x - node.x);
angles.Add(Angle);
}
if (backboneNodes.Count == 1)
{
Double Angle = Math.Atan2(520 - node.y, node.x - node.x) - Math.Atan2(n.y - node.y, n.x - node.x);
angles.Add(Angle);
}
}
int index = 0;
double minAngle = int.MaxValue;
for (int s = 0; s < angles.Count; s++)
{
if ((double)angles[s] < minAngle)
{
minAngle = (double)angles[s];
index = angles.IndexOf(minAngle);
}
}
Node Nnode = node.SensorNeighbors[index];
int iRadius = (int)Math.Sqrt(Math.Pow(node.x - Nnode.x, 2) + Math.Pow(node.y - Nnode.y, 2));
node.aConnections.Add(node, Nnode, (int)(fTransmissionCost * iRadius / iTransmissionRadius), iReceiveCost, iTransmitterDelay);
node = Nnode;

How to group near coordinates

I'm having my thesis "Multiple Choice Examination Checker" and I'm having a big issue about what to do with my problem. I got a picture image (a bitmap specifically) here it is, so you can see:
This is the image with the detectedbox, I will describe this:
This is an examination paper, 1-50 items. each number has a corresponding box(right side of the number, that serves as a container for the answer)
This pictures is just a sample, the number of detected boxes may vary. My approximation is it contains 150-200 detected boxes.
Each detectedboxes are stored in a List(MCvBOX2D) which holds the detectedboxes' size, center, etc.
I transferred those center coordinates in a new list List(PointF) center;
Each box from the image, may have 3-5 detectedboxes. as you can see there are more than one detectedboxes in each of the boxes from the image.
I sorted all the detectedboxes in ascending order, so I would know which will possibly be the number1, number2, and so on..
Here is some of my code, which contains the sorting of boxes.
List<PointF> center = new List<PointF>();
List<PointF> centernew = new List<PointF>();
foreach (MCvBox2D box in lstRectangles)
{
// this code transfers every center-coordinates of detected boxes
// to a new list which is center
center.Add(new PointF(box.center.X, box.center.Y));
}
// and this one sorts the coordinates in ascending order.
centernew = center.OrderBy(p => p.Y).ThenBy(p => p.X).ToList();
I'm done with the sorting part, now my problem is, since there many detected boxes in every box from the image, I would like to group the sortedlist of center-coordinates, so I could eliminate the other detectedboxes and get only one detectedbox for each number.
I know it's hard to understand so I'll explain more.
Let's say my sortedlist of detectedboxes contains first five center-coordinates which are:
let's say this are the center-coordinates of each of the detectedboxes from first box of the image.
center[0] = [ 45.39, 47.6]
center[1] = [ 65.39, 47.6]
center[2] = [ 45.40, 47.10]
center[3] = [ 65.45, 47.25]
center[4] = [ 46.01, 47.50]
and the 2nd are:
center[5] = [ 200.39, 47.2]
center[6] = [ 45.39, 47.2]
center[7] = [ 45.39, 47.3]
center[8] = [ 45.39, 47.55]
My goal is to organize all the sorted detectedboxes inside the list, I must be able to group all the center-coordinates that have close value with the other center, specifically their Y-coordinates.
var rand = new Random();
var threshold = 1;
var points = new List<PointF>();
for (int i = 0; i < 20; i++)
{
points.Add(new PointF((float) rand.NextDouble()*10, (float) rand.NextDouble()*10));
}
Console.WriteLine(points.Count);
for (int i = 0; i < points.Count(); i++)
{
for (int j = i + 1; j < points.Count(); )
{
var pointHere = points[i];
var pointThere = points[j];
var vectorX = pointThere.X - pointHere.X;
var vectorY = pointThere.Y - pointHere.Y;
var length = Math.Sqrt(Math.Pow(vectorX, 2) + Math.Pow(vectorY, 2));
if (length <= threshold)
{
points.RemoveAt(j);
}
else
{
j += 1;
}
}
}
Console.WriteLine(points.Count);
You can calculate the distance between a given point and any other point in the list. If the distance is less than half the width of a box, you can be pretty sure that it's part of the same box.
double threshold = 3.0; // Make this whatever is appropriate
for (int i = center.Count - 1; i >= 0; --i)
if (center.Any(p => p != center[i] && Distance(center[i], p) < threshold))
center.Remove(center[i]);
And you could use this for your Distance() method:
private double Distance(PointF p1, PointF p2)
{
double deltaX = Math.Abs(p1.X - p2.X);
double deltaY = Math.Abs(p1.Y - p2.Y);
return Math.Sqrt((deltaX * deltaX) + (deltaY * deltaY));
}
You could use Distinct with an custom IEqualityComparer (see MSDN).
As an example, define a class:
class BoxEqualityComparer : IEqualityComparer<MCvBox2D>
{
private static Double Tolerance = 0.01; //set your tolerance here
public Boolean Equals(MCvBox2D b1, MCvBox2D b2)
{
if (CentersAreCloseEnough(b1.Center, b2.Center))
{
return true;
}
else
{
return false;
}
}
private Boolean CentersAreCloseEnough(PointF c1, PointF c2)
{
return Math.Abs(c1.X - c2.X) < Tolerance && Math.Abs(c1.Y - c2.Y) < Tolerance;
}
}
then use the method in your code like so:
var distinctRectangles = lstRectangles.Distinct(new BoxEqualityComparer());
You are free to implement CentersAreCloseEnough(PointF c1, PointF c2) however you would like; you could use vector distance, absolute distance in x and y, etc.
If you are just concerned about positions with Y coordinates, just sort by that number. If you want to sort both you can add both X and Y and use that number to sort them. Here is an example of what I meen.
for(int i = 0; i < points.length - 1; i++)
{
int temp = points[i].x + points[i].y;
for(int j = i+1; j < points.length; i++)
{
int temp2 = point[j].x + points[j].y;
if(temp2 < temp)
{
Point jugglePoint = points[i];
points[i] = points[j];
points[j] = jugglePoint;
}
}
}

Categories

Resources