I'm trying to calculate the relative strength index, RSI, for a financial instrument. When I compare my calculation with one done by a commercial software, they don't look the same. I can't figure out what I'm doing wrong. Can anyone help?
The RSI formula:
{100} - (100/(1+RS)). Where RS is AvgGain(N periods)/AvgLoss( N periods)
public DataTable RSI(string instrument, int period, string oper, int entryVal)
{
DataTable dtRSI = new DataTable(); //table to return
dtRSI.Columns.Add("Date");
dtRSI.Columns.Add("Instrument");
dtRSI.Columns.Add("Close");
dtRSI.Columns.Add("RSI");
//Load Datatable from database
DataTable dt = new DataTable();
dt = conn.ExtractDataFromDb(instrument);
int column = 1; //Close price
//variables to RSI formula
Queue<float> avgUp = new Queue<float>();
Queue<float> avgDown = new Queue<float>();
float close1, close2, rsi, rs;
float avgUp1, avgUp2, newAvgUp, avgDown1, avgDown2, newAvgDown;
string[] dateCloseRsi = new string[3]; //row of data to insert into new table
string date; //date of calculation
string[] splitDate = new string[2];
//get first close
close1 = float.Parse(dt.Rows[0][column].ToString());
dt.Rows.RemoveAt(0);
//get close for number of periods into the que-list
for (int i = 1; i <= period; i++)
{
close2 = float.Parse(dt.Rows[0][column].ToString());
//are todays close higher then yesterday?
if (close2 > close1)
{
avgUp.Enqueue(close2 - close1);
avgDown.Enqueue(0);
}
else if (close2<close1)
{
avgUp.Enqueue(0);
avgDown.Enqueue(close1 - close2);
}
else
{
avgUp.Enqueue(0);
avgDown.Enqueue(0);
}
close1 = close2;
dt.Rows.RemoveAt(0);
}
//iterate datatable and calculate RSI
foreach (DataRow rows in dt.Rows)
{
avgUp1 = float.Parse(avgUp.Average().ToString("n2")); //calculate yesterdays avg difference on up days
avgDown1 = float.Parse(avgDown.Average().ToString("n2")); //calculate yesterdays avg difference on down days
avgUp.Dequeue();
avgDown.Dequeue();
close2 = float.Parse(rows[column].ToString()); //todays close
//close today higher then yesterday?
if (close2 > close1)
{
avgUp.Enqueue(close2 - close1);
avgDown.Enqueue(0);
}
else if (close2 < close1)
{
avgDown.Enqueue(close1 - close2);
avgUp.Enqueue(0);
}
else
{
avgUp.Enqueue(0);
avgDown.Enqueue(0);
}
avgUp2 = float.Parse(avgUp.Average().ToString("n2")); //todays avg difference on up days
avgDown2 = float.Parse(avgDown.Average().ToString("n2")); //todays avg difference on down days
newAvgUp = ((avgUp1 * (period - 1)) + avgUp2) / period; //yesterdays and todays avg diff value on up days
newAvgDown = ((avgDown1 * (period - 1)) + avgDown2) / period; //yesterdays and todays avg diff value on down days
newAvgUp = float.Parse(newAvgUp.ToString("n2")); //round to 2 decimals
newAvgDown = float.Parse(newAvgDown.ToString("n2")); //round to 2 decimals
rs = newAvgUp / newAvgDown; //calc Relative Strength
rs = float.Parse(rs.ToString("n2")); //round to 2 decimals
rsi = 100 - (100 / (1 + rs)); //Calc RSI
rsi = float.Parse(rsi.ToString("n2")); //round to 2 decimals
close1 = close2; //todays close become yesterdays close for tomorrow
//remove time from date
date = rows[0].ToString();
splitDate = date.Split(' ');
date = splitDate[0];
//add data to dtRSI
DataRow rsiRow = dtRSI.NewRow();
rsiRow["Date"] = date;
rsiRow["Instrument"] = instrument;
rsiRow["Close"] = rows[column];
rsiRow["RSI"] = rsi;
dtRSI.Rows.Add(rsiRow);
}
return dtRSI; //returns a table with Date, Instrument, Close Price and RSI
}
Hello, here's a tested and verified C# class which generates RSI values with 100% accuracy:
using System;
using System.Data;
using System.Globalization;
namespace YourNameSpace
{
class PriceEngine
{
public static DataTable data;
public static double[] positiveChanges;
public static double[] negativeChanges;
public static double[] averageGain;
public static double[] averageLoss;
public static double[] rsi;
public static double CalculateDifference(double current_price, double previous_price)
{
return current_price - previous_price;
}
public static double CalculatePositiveChange(double difference)
{
return difference > 0 ? difference : 0;
}
public static double CalculateNegativeChange(double difference)
{
return difference < 0 ? difference * -1 : 0;
}
public static void CalculateRSI(int rsi_period, int price_index = 5)
{
for(int i = 0; i < PriceEngine.data.Rows.Count; i++)
{
double current_difference = 0.0;
if (i > 0)
{
double previous_close = Convert.ToDouble(PriceEngine.data.Rows[i-1].Field<string>(price_index));
double current_close = Convert.ToDouble(PriceEngine.data.Rows[i].Field<string>(price_index));
current_difference = CalculateDifference(current_close, previous_close);
}
PriceEngine.positiveChanges[i] = CalculatePositiveChange(current_difference);
PriceEngine.negativeChanges[i] = CalculateNegativeChange(current_difference);
if(i == Math.Max(1,rsi_period))
{
double gain_sum = 0.0;
double loss_sum = 0.0;
for(int x = Math.Max(1,rsi_period); x > 0; x--)
{
gain_sum += PriceEngine.positiveChanges[x];
loss_sum += PriceEngine.negativeChanges[x];
}
PriceEngine.averageGain[i] = gain_sum / Math.Max(1,rsi_period);
PriceEngine.averageLoss[i] = loss_sum / Math.Max(1,rsi_period);
}else if (i > Math.Max(1,rsi_period))
{
PriceEngine.averageGain[i] = ( PriceEngine.averageGain[i-1]*(rsi_period-1) + PriceEngine.positiveChanges[i]) / Math.Max(1, rsi_period);
PriceEngine.averageLoss[i] = ( PriceEngine.averageLoss[i-1]*(rsi_period-1) + PriceEngine.negativeChanges[i]) / Math.Max(1, rsi_period);
PriceEngine.rsi[i] = PriceEngine.averageLoss[i] == 0 ? 100 : PriceEngine.averageGain[i] == 0 ? 0 : Math.Round(100 - (100 / (1 + PriceEngine.averageGain[i] / PriceEngine.averageLoss[i])), 5);
}
}
}
public static void Launch()
{
PriceEngine.data = new DataTable();
//load {date, time, open, high, low, close} values in PriceEngine.data (6th column (index #5) = close price) here
positiveChanges = new double[PriceEngine.data.Rows.Count];
negativeChanges = new double[PriceEngine.data.Rows.Count];
averageGain = new double[PriceEngine.data.Rows.Count];
averageLoss = new double[PriceEngine.data.Rows.Count];
rsi = new double[PriceEngine.data.Rows.Count];
CalculateRSI(14);
}
}
}
For detailed step-by-step instructions, I wrote a lengthy article, you can check it here:
https://turmanauli.medium.com/a-step-by-step-guide-for-calculating-reliable-rsi-values-programmatically-a6a604a06b77
P.S. You need global variables to store prevous values, this is not an option for indicators like RSI, simple function work only for simple indicators like Simple Moving Average. All smoothed / Weighted indicators need buffers / global arrays to store data.
Related
In my array, arr3 has 1000 numbers in it. I have to split this array into k subintervals of width differenceofMaxMin . How can I do that? Later I have to count how many times, the values in arr3 have matched to each interval. But I am stuck at creating intervals from array with a given width.
Any kind of help will be really appreciated!
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
double[] Statistics1 = new double[500];
double[] Statistics2 = new double[500];
double Alpha1;
double Alpha2;
double RV1;
double RV2;
Random random = new Random();
public double RandomDoubleInclusive() //We are using this method because random.NextDouble() method gives random number
//between 0 and 1 where 0 is inclusive and 1 is exclusive.
//Since the value of probability lies between 0 and 1, both inclusive that's why we need
//to use this method.
{
double d = 0.0;
int i = 0;
do
{
d = random.NextDouble();
i = random.Next(2);
}
while (i == 1 && d > 0);
return d + i;
}
private void label3_Click(object sender, EventArgs e)
{
}
int i,j;
private void button1_Click(object sender, EventArgs e)
{
int SampleSize = Convert.ToInt32(textBox3.Text);
for ( i = 0; i<500;)
{
for (j = 0; j < 500;)
{
Alpha1 = RandomDoubleInclusive();
Alpha2 = RandomDoubleInclusive();
double LnPart = Math.Log(Alpha1);
double part1 = (-2) * LnPart;
double part2 = 2 * 3.14159 * Alpha2;
double CosPart = Math.Cos(part2);
double SinPart = Math.Sin(part2);
RV1 = Math.Sqrt(part1) * CosPart;
Statistics1[i] = RV1;
RV2 = Math.Sqrt(part1) * SinPart;
Statistics2[j] = RV2;
i++;
j++;
}
}
var myList = new List<double>();
myList.AddRange(Statistics1);
myList.AddRange(Statistics2);
double[] arr3 = myList.ToArray();
double Max = arr3.Max();
double Min = arr3.Min();
double differenceofMaxMin = Max - Min; //calculating size of width of interval
double k;
k = Math.Log(SampleSize,2) + 1; //calculating number of subintervals
}
}
I'm not sure I fully understand what exactly you're trying to achieve, but I can certainly try to help you out with an example on how to split an array arr3 into k subintervals with (max) number of elements differenceofMaxMin
var arr3 = Enumerable.Range(0, 1000);
// given: the max number of elements
var differenceofMaxMin = 300;
// determine the number of subintervals
// note that the last subinterval may contain less than differenceofMaxMin elements
var k = (int)Math.Ceiling((double)arr3.Count() / differenceofMaxMin);
var arr3_split = Enumerable.Range(0, k)
.Select(i => arr3.Skip(i * differenceofMaxMin).Take(differenceofMaxMin));
Looking at your method to generate a random double from [0, 1], I think it's overkill since the likelihood to actually draw exactly 1.0 is extremely low.
The following formula would calculate RSI for all prices. Whenever I add a new price to the array, it would have to recalculate the RSI for the entire array/all prices. Is there a way I can calculate the RSI for the new price without having to recalculate the entire thing? I want to do that because when I'm calculating this for every new candle and it has to be executed for the least possible time. If it's not possible, can you please suggest me a way to optimize it, so it executes as fast as possible. Right now, it's not so fast.
decimal[] prices = ...
Calculate(prices, 14);
public decimal[] Calculate(decimal[] price, int period)
{
var rsi = new decimal[price.Length];
decimal gain = 0m;
decimal loss = 0m;
rsi[0] = 0m;
for (int i = 1; i <= period; ++i)
{
var diff = price[i] - price[i - 1];
if (diff >= 0)
{
gain += diff;
}
else
{
loss -= diff;
}
}
decimal avrg = gain / period;
decimal avrl = loss / period;
decimal rs = gain / loss;
rsi[period] = 100m - (100m / (1m + rs));
for (int i = period + 1; i < price.Length; ++i)
{
var diff = price[i] - price[i - 1];
if (diff >= 0)
{
avrg = ((avrg * (period - 1)) + diff) / period;
avrl = (avrl * (period - 1)) / period;
}
else
{
avrl = ((avrl * (period - 1)) - diff) / period;
avrg = (avrg * (period - 1)) / period;
}
rs = avrg / avrl;
rsi[i] = 100m - (100m / (1m + rs));
}
return rsi;
}
I am having trouble getting a smoothed RSI. The below picture is from freestockcharts.com. The calculation uses this code.
public static double CalculateRsi(IEnumerable<double> closePrices)
{
var prices = closePrices as double[] ?? closePrices.ToArray();
double sumGain = 0;
double sumLoss = 0;
for (int i = 1; i < prices.Length; i++)
{
var difference = prices[i] - prices[i - 1];
if (difference >= 0)
{
sumGain += difference;
}
else
{
sumLoss -= difference;
}
}
if (sumGain == 0) return 0;
if (Math.Abs(sumLoss) < Tolerance) return 100;
var relativeStrength = sumGain / sumLoss;
return 100.0 - (100.0 / (1 + relativeStrength));
}
https://stackoverflow.com/questions/...th-index-using-some-programming-language-js-c
This seems to be the pure RSI with no smoothing. How does a smoothed RSI get calculated? I have tried changing it to fit the definitions of the these two sites however the output was not correct. It was barely smoothed.
(I don't have enough rep to post links)
tc2000 -> Indicators -> RSI_and_Wilder_s_RSI (Wilder's smoothing = Previous MA value + (1/n periods * (Close - Previous MA)))
priceactionlab -> wilders-cutlers-and-harris-relative-strength-index (RS = EMA(Gain(n), n)/EMA(Loss(n), n))
Can someone actually do the calculation with some sample data?
Wilder's RSI vs RSI
In order to calculate the RSI, you need a period to calculate it with. As noted on Wikipedia, 14 is used quite often.
So the calculation steps would be as follows:
Period 1 - 13, RSI = 0
Period 14:
AverageGain = TotalGain / PeriodCount;
AverageLoss = TotalLoss / PeriodCount;
RS = AverageGain / AverageLoss;
RSI = 100 - 100 / (1 + RS);
Period 15 - to period (N):
if (Period(N)Change > 0
AverageGain(N) = ((AverageGain(N - 1) * (PeriodCount - 1)) + Period(N)Change) / PeriodCount;
else
AverageGain(N) = (AverageGain(N - 1) * (PeriodCount - 1)) / PeriodCount;
if (this.Change < 0)
AverageLoss(N) = ((AverageLoss(N - 1) * (PeriodCount - 1)) + Math.Abs(Period(N)Change)) / PeriodCount;
else
AverageLoss(N) = (AverageLoss(N - 1) * (PeriodCount - 1)) / PeriodCount;
RS = AverageGain / AverageLoss;
RSI = 100 - (100 / (1 + RS));
Thereafter, to smooth the values, you need to apply a moving average of a certain period to your RSI values. To do that, traverse your RSI values from the last index to the first and calculate your average for the current period based on the preceding x smoothing periods.
Once done, just reverse the list of values to get the expected order:
List<double> SmoothedRSI(IEnumerable<double> rsiValues, int smoothingPeriod)
{
if (rsiValues.Count() <= smoothingPeriod)
throw new Exception("Smoothing period too large or too few RSI values passed.");
List<double> results = new List<double>();
List<double> reversedRSIValues = rsiValues.Reverse().ToList();
for (int i = 1; i < reversedRSIValues.Count() - smoothingPeriod - 1; i++)
results.Add(reversedRSIValues.Subset(i, i + smoothingPeriod).Average());
return results.Reverse().ToList();
}
The Subset method is just a simple extension method as follows:
public static List<double> Subset(this List<double> values, int start, int end)
{
List<double> results = new List<double>();
for (int i = start; i <= end; i++)
results.Add(values[i]);
return results;
}
Disclaimer, I did not test the code, but it should give you an idea of how the smoothing is applied.
You can't get accurate values without buffers / global variables to store data.
This is a smoothed indicator, meaning it doesn't only use 14 bars but ALL THE BARS:
Here's a step by step article with working and verified source codes generating exactly the same values if prices and number of available bars are the same, of course (you only need to load the price data from your source):
Tested and verified:
using System;
using System.Data;
using System.Globalization;
namespace YourNameSpace
{
class PriceEngine
{
public static DataTable data;
public static double[] positiveChanges;
public static double[] negativeChanges;
public static double[] averageGain;
public static double[] averageLoss;
public static double[] rsi;
public static double CalculateDifference(double current_price, double previous_price)
{
return current_price - previous_price;
}
public static double CalculatePositiveChange(double difference)
{
return difference > 0 ? difference : 0;
}
public static double CalculateNegativeChange(double difference)
{
return difference < 0 ? difference * -1 : 0;
}
public static void CalculateRSI(int rsi_period, int price_index = 5)
{
for(int i = 0; i < PriceEngine.data.Rows.Count; i++)
{
double current_difference = 0.0;
if (i > 0)
{
double previous_close = Convert.ToDouble(PriceEngine.data.Rows[i-1].Field<string>(price_index));
double current_close = Convert.ToDouble(PriceEngine.data.Rows[i].Field<string>(price_index));
current_difference = CalculateDifference(current_close, previous_close);
}
PriceEngine.positiveChanges[i] = CalculatePositiveChange(current_difference);
PriceEngine.negativeChanges[i] = CalculateNegativeChange(current_difference);
if(i == Math.Max(1,rsi_period))
{
double gain_sum = 0.0;
double loss_sum = 0.0;
for(int x = Math.Max(1,rsi_period); x > 0; x--)
{
gain_sum += PriceEngine.positiveChanges[x];
loss_sum += PriceEngine.negativeChanges[x];
}
PriceEngine.averageGain[i] = gain_sum / Math.Max(1,rsi_period);
PriceEngine.averageLoss[i] = loss_sum / Math.Max(1,rsi_period);
}else if (i > Math.Max(1,rsi_period))
{
PriceEngine.averageGain[i] = ( PriceEngine.averageGain[i-1]*(rsi_period-1) + PriceEngine.positiveChanges[i]) / Math.Max(1, rsi_period);
PriceEngine.averageLoss[i] = ( PriceEngine.averageLoss[i-1]*(rsi_period-1) + PriceEngine.negativeChanges[i]) / Math.Max(1, rsi_period);
PriceEngine.rsi[i] = PriceEngine.averageLoss[i] == 0 ? 100 : PriceEngine.averageGain[i] == 0 ? 0 : Math.Round(100 - (100 / (1 + PriceEngine.averageGain[i] / PriceEngine.averageLoss[i])), 5);
}
}
}
public static void Launch()
{
PriceEngine.data = new DataTable();
//load {date, time, open, high, low, close} values in PriceEngine.data (6th column (index #5) = close price) here
positiveChanges = new double[PriceEngine.data.Rows.Count];
negativeChanges = new double[PriceEngine.data.Rows.Count];
averageGain = new double[PriceEngine.data.Rows.Count];
averageLoss = new double[PriceEngine.data.Rows.Count];
rsi = new double[PriceEngine.data.Rows.Count];
CalculateRSI(14);
}
}
}
For detailed step-by-step instructions, I wrote a lengthy article, you can check it here: https://turmanauli.medium.com/a-step-by-step-guide-for-calculating-reliable-rsi-values-programmatically-a6a604a06b77
P.S. functions only work for simple indicators (Simple Moving Average), even Exponential Moving Average, Average True Range absolutely require global variables to store previous values.
how to find the min and max for quadratic equation using c# ??
f(x,y) = x^2 + y^2 + 25 * (sin(x)^2 + sin(y)^2) ,where (x,y) from (-2Pi, 2Pi) ??
in the manual solving I got min is = 0 , max = 8Pi^2 = 78.957 .
I tried to write the code based on liner quadratic code but something goes totally wrong
this code give the min = -4.?? and the max = 96 could you help to know where is my mistake please ??
I uploaded the code to dropbox if anyone can have look : https://www.dropbox.com/s/p7y6krk2gk29i9e/Program.cs
double[] X, Y, Result; // Range array and result array.
private void BtnRun_Click(object sender, EventArgs e)
{
//Set any Range for the function
X = setRange(-2 * Math.PI, 2 * Math.PI, 10000);
Y = setRange(-2 * Math.PI, 2 * Math.PI, 10000);
Result = getOutput_twoVariablesFunction(X, Y);
int MaxIndex = getMaxIndex(Result);
int MinIndex = getMinIndex(Result);
TxtMin.Text = Result[MinIndex].ToString();
TxtMax.Text = Result[MaxIndex].ToString();
}
private double twoVariablesFunction(double x,double y)
{
double f;
//Set any two variables function
f = Math.Pow(x, 2) + Math.Pow(y, 2) + 25 * (Math.Pow(Math.Sin(x), 2) + Math.Pow(Math.Sin(y), 2));
return f;
}
private double[] setRange(double Start, double End, int Sample)
{
double Step = (End - Start) / Sample;
double CurrentVaue = Start;
double[] Array = new double[Sample];
for (int Index = 0; Index < Sample; Index++)
{
Array[Index] = CurrentVaue;
CurrentVaue += Step;
}
return Array;
}
private double[] getOutput_twoVariablesFunction(double[] X, double[] Y)
{
int Step = X.Length;
double[] Array = new double[Step];
for (int Index = 0; Index < X.Length ; Index++)
{
Array[Index] = twoVariablesFunction(X[Index], Y[Index]);
}
return Array;
}
private int getMaxIndex(double[] ValuesArray)
{
double M = ValuesArray.Max();
int Index = ValuesArray.ToList().IndexOf(M);
return Index;
}
private int getMinIndex(double[] ValuesArray)
{
double M = ValuesArray.Min();
int Index = ValuesArray.ToList().IndexOf(M);
return Index;
}
Do you want to compute (sin(x))^2 or sin(x^2)? In your f(x,y) formula it looks like (sin(x))^2, but in your method twoVariablesFunction like sin(x^2).
Has anyone come across the issue that the RowsAdded event only fires twice and then leaves the loop?
I programatically am populating a DataGridView and then performing a couple of calculations to give appropriate figures.
My code is below but when run the DataGridView pulls and displays all the data but the calculated fields are only done for the first 2 rows. By using breakpoints this loops through correctly twice but then leaves the 3rd row and others without looping through the RowsAdded event.
private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
DataClasses1DataContext getIsEmployed = new DataClasses1DataContext();
var result = from a in getIsEmployed.writers
where a.name == dataGridView1.Rows[e.RowIndex].Cells["nameDataGridViewTextBoxColumn"].Value.ToString()
select a;
foreach (var b in result)
{
if (b.IsEmployed == true)
{
int val1 = Convert.ToInt32(dataGridView1.Rows[e.RowIndex].Cells["articlesPerWeekDataGridViewTextBoxColumn"].Value);
decimal val2 = val1 * 300;
decimal hourlyRate = Convert.ToDecimal(dataGridView1.Rows[e.RowIndex].Cells["hourlyRateDataGridViewTextBoxColumn"].Value);
int contractedEmployedHours = Convert.ToInt32(dataGridView1.Rows[e.RowIndex].Cells["hoursDataGridViewTextBoxColumn"].Value);
decimal employedWage = (((hourlyRate * contractedEmployedHours) * 52) / 12);
decimal employedBonusPerArticle = Convert.ToDecimal(dataGridView1.Rows[e.RowIndex].Cells["bonusDataGridViewTextBoxColumn"].Value);
decimal maximumEmployedBonus = (((val1 * employedBonusPerArticle) * 52) / 12);
decimal maximumEmployedLiability = employedWage + maximumEmployedBonus;
dataGridView1.Rows[e.RowIndex].Cells["ExpectedWeeklyWords"].Value = val2;
dataGridView1.Rows[e.RowIndex].Cells["CostOfContent"].Value = employedWage;
dataGridView1.Rows[e.RowIndex].Cells["MaximumBonus"].Value = maximumEmployedBonus;
dataGridView1.Rows[e.RowIndex].Cells["MaximumLiability"].Value = maximumEmployedLiability;
}
else
{
int val1 = Convert.ToInt32(dataGridView1.Rows[e.RowIndex].Cells["articlesPerWeekDataGridViewTextBoxColumn"].Value);
decimal val2 = val1 * 300;
int basicCost = Convert.ToInt32(dataGridView1.Rows[e.RowIndex].Cells["articlesPerWeekDataGridViewTextBoxColumn"].Value);
int calculatedBasicCost = (((basicCost * 3) * 52) / 12);
decimal bonusPerArticle = Convert.ToDecimal(dataGridView1.Rows[e.RowIndex].Cells["bonusDataGridViewTextBoxColumn"].Value);
decimal maximumBonus = (((val1 * bonusPerArticle) * 52) / 12);
decimal maximumLiability = calculatedBasicCost + maximumBonus;
dataGridView1.Rows[e.RowIndex].Cells["ExpectedWeeklyWords"].Value = val2;
dataGridView1.Rows[e.RowIndex].Cells["CostOfContent"].Value = calculatedBasicCost;
dataGridView1.Rows[e.RowIndex].Cells["MaximumBonus"].Value = maximumBonus;
dataGridView1.Rows[e.RowIndex].Cells["MaximumLiability"].Value = maximumLiability;
}
}
}
I managed to work out a workaround but I am still unsure why it happens. I ended up having to use the RowStateChanged event in DataGridview and perfoming a check to chen the state changes to "Displayed" and then running the calculations.
Code used is below:
private void dataGridView1_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
{
if(e.StateChanged.ToString() == "Displayed")
{
DataClasses1DataContext getIsEmployed = new DataClasses1DataContext();
var result = from a in getIsEmployed.writers
where a.name == dataGridView1.Rows[e.Row.Index].Cells["nameDataGridViewTextBoxColumn"].Value.ToString()
select a;
foreach (var b in result)
{
if (b.IsEmployed == true)
{
int val1 = Convert.ToInt32(dataGridView1.Rows[e.Row.Index].Cells["articlesPerWeekDataGridViewTextBoxColumn"].Value);
decimal val2 = val1 * 300;
decimal hourlyRate = Convert.ToDecimal(dataGridView1.Rows[e.Row.Index].Cells["hourlyRateDataGridViewTextBoxColumn"].Value);
int contractedEmployedHours = Convert.ToInt32(dataGridView1.Rows[e.Row.Index].Cells["hoursDataGridViewTextBoxColumn"].Value);
decimal employedWage = (((hourlyRate * contractedEmployedHours) * 52) / 12);
decimal employedBonusPerArticle = Convert.ToDecimal(dataGridView1.Rows[e.Row.Index].Cells["bonusDataGridViewTextBoxColumn"].Value);
decimal maximumEmployedBonus = (((val1 * employedBonusPerArticle) * 52) / 12);
decimal maximumEmployedLiability = employedWage + maximumEmployedBonus;
dataGridView1.Rows[e.Row.Index].Cells["ExpectedWeeklyWords"].Value = val2;
dataGridView1.Rows[e.Row.Index].Cells["CostOfContent"].Value = employedWage;
dataGridView1.Rows[e.Row.Index].Cells["MaximumBonus"].Value = maximumEmployedBonus;
dataGridView1.Rows[e.Row.Index].Cells["MaximumLiability"].Value = maximumEmployedLiability;
}
else
{
int val1 = Convert.ToInt32(dataGridView1.Rows[e.Row.Index].Cells["articlesPerWeekDataGridViewTextBoxColumn"].Value);
decimal val2 = val1 * 300;
int basicCost = Convert.ToInt32(dataGridView1.Rows[e.Row.Index].Cells["articlesPerWeekDataGridViewTextBoxColumn"].Value);
int calculatedBasicCost = (((basicCost * 3) * 52) / 12);
decimal bonusPerArticle = Convert.ToDecimal(dataGridView1.Rows[e.Row.Index].Cells["bonusDataGridViewTextBoxColumn"].Value);
decimal maximumBonus = (((val1 * bonusPerArticle) * 52) / 12);
decimal maximumLiability = calculatedBasicCost + maximumBonus;
dataGridView1.Rows[e.Row.Index].Cells["ExpectedWeeklyWords"].Value = val2;
dataGridView1.Rows[e.Row.Index].Cells["CostOfContent"].Value = calculatedBasicCost;
dataGridView1.Rows[e.Row.Index].Cells["MaximumBonus"].Value = maximumBonus;
dataGridView1.Rows[e.Row.Index].Cells["MaximumLiability"].Value = maximumLiability;
}
}
}
}
Today, I have encountered the same problem in one of our old applications. Actually the problem is "we are using the "RowsAdded" event incorrectly. If you read the documentation for DataGridViewRowsAddedEventArgs class, you will see that it can contain information about addition of more than one row.
public class DataGridViewRowsAddedEventArgs : EventArgs
{
//The number of rows that have been added.
public int RowCount { get; }
//The index of the first added row.
public int RowIndex { get; }
}
So, you must process e.RowCount number of rows starting at index e.RowIndex in order to process all the newly added rows.
for (int i = 0; i < e.RowCount; i++)
{
DataGridViewRow _row = m_dgMetadata.Rows[e.RowIndex + i];
//.. Do whatever you want
}