This post is not about C# 4.0 programming itself but what have been done so far. Please keep in mind I'm IT guy who is learning C# 4.0 (I'm experienced in VB and VBscript ) and how trading world works in parallel.
There is one more form accessible which (from Main in menu bar or Trader 2012 item in 11) covers trader's portfolio (probably the most important part of trading ;-) ). Data are stored in Access database and managed by SQL. Also, on this form hidden frame(at the moment) can be invoked where trading transactions can be entered. So, this is only part of whole functionality but still enough to demonstrate C# 4.0 against Japanese candlesticks, trading volumes, three days flag and RSI. Development is in progress and new options will be added.
1. Table with history trading information which could be entered manually or pulled/filled from Internet. Also, if I click on certain date in the past, day analyze of that row date will happen. Candles will be redrawn and new findings will be placed in 3. It is useful to test trading strategies.
2. During trading day I can follow more shares which can be seen in 12. So, if I hit "timer Stopped" (it will change his label to "timer Started" and back color to red) button program will pull data (price) form Internet in a pace defined in field before "sec." label. Next field defines time of a day after which automatic update of trading information will stop.
3. Findings according to Japanese candlesticks and volumes for trading day. Back color is the same as for "Conclusion" field in 6.
4. Findings from previous trading day for easier trading decisions, since trading is field full of explosive devices which can blow out money.
5. During trading day field in green (it means present prices is bigger then previous) fills last row in table 1 in appropriate, in case I enter data manually. Two next fields are prices to Sell/Buy with commission. Two fields bellow represents Bid and Ask prices. These fields are filled/calculated if automatic pulling is chosen.
6. Actually this puts this program to an expert system. It consider three (at the moment) parameters and suggest action. At the moment, he says "Do not buy" ("Do not sell", "Buy", "Sell" or "Unknown" are other options) since price suggest buying action. Back color is yellow and could be white, green or red depending on suggested action.
7. These are live transactions with zero and one per cent profit. If selected (by application according to actual price) it means it could be sold with profit. Otherwise, no profit.
8. These are transaction from the past so I can follow what I did in past. These are very useful if kept up to date. Frame which maintains data of 7. and 8. can be invoked by Menu-> Ledger or button "Ledg/stats".
9. RSI as described in previous chapter. It is automatically recalculated by change of green field in 5. It can be used to test RSI limits with no influence to actual data.
10. This is Japanese candlestick chart with dates and volume bars.
11. It is list with active forms (indexes) at the moment and if item is selected I jump to corresponding form/share to see full details of that index/share. I'm not in CZ but in HR and shares as well (of course DAX is German index). This is mistake from Internet but no influence on nothing of importance.
12. This is summary status for all active shares. It is updated automatically when green field (Price) is changed on any listed/active form, active or in background.
13. This is reach text field for comments for specific share index.
14. This is list with different prices and indexes based on yesterday's average price. Selections are based on minimum and maximum prices for previous six days.
As mentioned, other functionality exists but since programming / learnig is in progress there will be time to present them.
C# 4.0 programming using Japanese candlesticks as an example. Calculation, drawing and trading decision management.
Monday, 1 October 2012
Sunday, 30 September 2012
30. Japanese candlestiscks and C# - Two dimensional array
How to calculate RSI (relative strength index)?
Now, application analyses Japanese candlesticks, volumes and RSI to advise trading action.
We'll use 2D array to calculate RSI value. If you are interested in theory of RSI please read this
http://en.wikipedia.org/wiki/Relative_strength_index
and related
http://en.wikipedia.org/wiki/Moving_average_(finance)#Simple_moving_average (SMA chapter)
Under RSI button is code which uses values of these Excel calculation example
http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:relative_strength_index_rsi
It is worth to have a look how it works in Excel, first.
So, now you can easier follow code. 2D table does not use all 8 columns but I did it so to be more easier to follow Excel example. Number of array rows is variable and type of data is double.
Under commented lines is code which is used for daily live trading analysis. Variable noDays is set to 14 as in Excel example. On your form you will need one button (any name) and text field rsItext. Of course, you can use string variable and change code to
string rsIstring== rsI.ToString(); // fill last value to string
and you'll need debugger to see result or you can use line such as this
MessageBox.Show("RSI value", rsIstring)
Also, if you are interested in RSI and how it changes with different number of days (traders use different values according to their trading goals for example 2,..9,14,20) then you can add text filed rsidayS to form and delete in bold line code( // also). With rsidayS filed change RSI will change, also.
noDays = 14; // noDays = Convert.ToInt16(rsidayS.Text);
Great example for debugger usage. :-)
And code:
private void rsI_Click(object sender, EventArgs e)
{ // how to calculate RSI - Relative strength index
int noRows = 44; // number or days to look back
double[,] rsiTable=new double[noRows,9]; // two dimensional array declaration with noRows rows
rsiTable[1, 1] = 43.13; // 1 means today - table filled with test data from
rsiTable[2, 1] = 42.66; // http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:relative_strength_index_rsi
rsiTable[3, 1] = 43.42;
rsiTable[4, 1] = 44.57;
rsiTable[5, 1] = 44.22;
rsiTable[6, 1] = 44.18;
rsiTable[7, 1] = 44.03;
rsiTable[8, 1] = 45.35;
rsiTable[9, 1] = 45.78;
rsiTable[10, 1] = 46.45;
rsiTable[11, 1] = 45.71;
rsiTable[12, 1] = 46.25;
rsiTable[13, 1] = 46.21;
rsiTable[14, 1] = 45.64;
rsiTable[15, 1] = 46.22;
rsiTable[16, 1] = 46.41;
rsiTable[17, 1] = 46.03;
rsiTable[18, 1] = 46.00;
rsiTable[19, 1] = 46.28;
rsiTable[20, 1] = 46.28;
rsiTable[21, 1] = 45.61;
rsiTable[22, 1] = 46.03;
rsiTable[23, 1] = 45.89;
rsiTable[24, 1] = 46.08;
rsiTable[25, 1] = 45.84;
rsiTable[26, 1] = 45.42;
rsiTable[27, 1] = 45.10;
rsiTable[28, 1] = 44.83;
rsiTable[29, 1] = 44.33;
rsiTable[30, 1] = 43.61;
rsiTable[31, 1] = 44.15;
rsiTable[32, 1] = 44.09;
rsiTable[33, 1] = 44.34;
/* for (int m = 0; m < noRows-1; m++) // load from live data table for number of days
{
rsiTable[m + 1, 1] = historyArrayL[m, 2];
} */
int noDays = 0;
int firstDayForAverage = 19;
int lastDayForAverage = 0;
double averageGainSum=0;
double averageLossSum=0;
double gainAverage=0;
double lossAverage=0;
double rS=0;
double rsI=0;
double deltA = 0;
noDays = 14; // noDays = Convert.ToInt16(rsidayS.Text);
if (noDays * 2 + 2 > noRows) { MessageBox.Show("Too many days", "Maximum is 20"); goto kraj; } // we have 44 days to examine
for (int k=gloB.rowSelected+1;k<noRows-1;k++) // calclulate loss
{
deltA=Math.Round(rsiTable[k,1]-rsiTable[k+1,1],2); // close yesterday - close today
if (deltA > 0) { rsiTable[k,3]=deltA; } // delta gain fill column 3
if (deltA < 0) { rsiTable[k, 4] = Math.Abs(deltA); } // delta loss fill column for as positive value
}
firstDayForAverage=firstDayForAverage+gloB.rowSelected; // calculate first average day index
lastDayForAverage=firstDayForAverage+noDays-1; // calculate last average day index
if (lastDayForAverage >= noRows) { MessageBox.Show("Too far in the past", "Maximum is 20"); goto kraj; } // if we are not in range
for (int k = firstDayForAverage; k <= lastDayForAverage; k++)
{
averageGainSum = averageGainSum + rsiTable[k, 3]; averageLossSum = averageLossSum + rsiTable[k, 4]; // for numebr of days
}
gainAverage = Math.Round(averageGainSum / noDays,3); //
lossAverage = Math.Round(averageLossSum / noDays,3); // average of 20th day is calculated
rsiTable[firstDayForAverage,5]=gainAverage; // average gain column 5
rsiTable[firstDayForAverage,6]=lossAverage; // average loss column 6
if (lossAverage > 0) { rS = gainAverage / lossAverage; } else { rS = 100; } // calc. loss avarege - value 100 is by definiton
rsiTable[firstDayForAverage, 7] = Math.Round(rS,2); // RS column 7
if (rsiTable[firstDayForAverage, 6] == 0) { rsiTable[firstDayForAverage, 8] = 100; } // calc. of first RSI value (column 8 of nth day)- value 100 is by definiton
else{rsiTable[firstDayForAverage, 8] = Math.Round(100-(100/(1+rsiTable[firstDayForAverage, 7])) ,2);} // RSI column 8
for (int k = firstDayForAverage -1; k > 0; k--) // calculte other RSI valuse
{
gainAverage = Math.Round((rsiTable[k + 1, 5] * (noDays - 1) + rsiTable[k, 3]) / noDays, 3); // previous and today day
lossAverage = Math.Round((rsiTable[k + 1, 6] * (noDays - 1) + rsiTable[k, 4]) / noDays,3);
rsiTable[k, 5] = gainAverage; // fill column 5
rsiTable[k, 6] = lossAverage;
rS = rsiTable[k, 5] / rsiTable[k, 6];
if (rsiTable[k, 6] == 0) { rsI = 100; } else { rsI = Math.Round(100 - 100 / (1 + rS), 2); rsiTable[k, 8] = rsI; } // calclulate RSI
}
rsItext.Text = rsI.ToString(); // fill last value to field rsIText
kraj: ;
}
Now, application analyses Japanese candlesticks, volumes and RSI to advise trading action.
We'll use 2D array to calculate RSI value. If you are interested in theory of RSI please read this
http://en.wikipedia.org/wiki/Relative_strength_index
and related
http://en.wikipedia.org/wiki/Moving_average_(finance)#Simple_moving_average (SMA chapter)
Under RSI button is code which uses values of these Excel calculation example
http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:relative_strength_index_rsi
It is worth to have a look how it works in Excel, first.
So, now you can easier follow code. 2D table does not use all 8 columns but I did it so to be more easier to follow Excel example. Number of array rows is variable and type of data is double.
Under commented lines is code which is used for daily live trading analysis. Variable noDays is set to 14 as in Excel example. On your form you will need one button (any name) and text field rsItext. Of course, you can use string variable and change code to
string rsIstring== rsI.ToString(); // fill last value to string
and you'll need debugger to see result or you can use line such as this
MessageBox.Show("RSI value", rsIstring)
Also, if you are interested in RSI and how it changes with different number of days (traders use different values according to their trading goals for example 2,..9,14,20) then you can add text filed rsidayS to form and delete in bold line code( // also). With rsidayS filed change RSI will change, also.
noDays = 14; // noDays = Convert.ToInt16(rsidayS.Text);
Great example for debugger usage. :-)
And code:
private void rsI_Click(object sender, EventArgs e)
{ // how to calculate RSI - Relative strength index
int noRows = 44; // number or days to look back
double[,] rsiTable=new double[noRows,9]; // two dimensional array declaration with noRows rows
rsiTable[1, 1] = 43.13; // 1 means today - table filled with test data from
rsiTable[2, 1] = 42.66; // http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:relative_strength_index_rsi
rsiTable[3, 1] = 43.42;
rsiTable[4, 1] = 44.57;
rsiTable[5, 1] = 44.22;
rsiTable[6, 1] = 44.18;
rsiTable[7, 1] = 44.03;
rsiTable[8, 1] = 45.35;
rsiTable[9, 1] = 45.78;
rsiTable[10, 1] = 46.45;
rsiTable[11, 1] = 45.71;
rsiTable[12, 1] = 46.25;
rsiTable[13, 1] = 46.21;
rsiTable[14, 1] = 45.64;
rsiTable[15, 1] = 46.22;
rsiTable[16, 1] = 46.41;
rsiTable[17, 1] = 46.03;
rsiTable[18, 1] = 46.00;
rsiTable[19, 1] = 46.28;
rsiTable[20, 1] = 46.28;
rsiTable[21, 1] = 45.61;
rsiTable[22, 1] = 46.03;
rsiTable[23, 1] = 45.89;
rsiTable[24, 1] = 46.08;
rsiTable[25, 1] = 45.84;
rsiTable[26, 1] = 45.42;
rsiTable[27, 1] = 45.10;
rsiTable[28, 1] = 44.83;
rsiTable[29, 1] = 44.33;
rsiTable[30, 1] = 43.61;
rsiTable[31, 1] = 44.15;
rsiTable[32, 1] = 44.09;
rsiTable[33, 1] = 44.34;
/* for (int m = 0; m < noRows-1; m++) // load from live data table for number of days
{
rsiTable[m + 1, 1] = historyArrayL[m, 2];
} */
int noDays = 0;
int firstDayForAverage = 19;
int lastDayForAverage = 0;
double averageGainSum=0;
double averageLossSum=0;
double gainAverage=0;
double lossAverage=0;
double rS=0;
double rsI=0;
double deltA = 0;
noDays = 14; // noDays = Convert.ToInt16(rsidayS.Text);
if (noDays * 2 + 2 > noRows) { MessageBox.Show("Too many days", "Maximum is 20"); goto kraj; } // we have 44 days to examine
for (int k=gloB.rowSelected+1;k<noRows-1;k++) // calclulate loss
{
deltA=Math.Round(rsiTable[k,1]-rsiTable[k+1,1],2); // close yesterday - close today
if (deltA > 0) { rsiTable[k,3]=deltA; } // delta gain fill column 3
if (deltA < 0) { rsiTable[k, 4] = Math.Abs(deltA); } // delta loss fill column for as positive value
}
firstDayForAverage=firstDayForAverage+gloB.rowSelected; // calculate first average day index
lastDayForAverage=firstDayForAverage+noDays-1; // calculate last average day index
if (lastDayForAverage >= noRows) { MessageBox.Show("Too far in the past", "Maximum is 20"); goto kraj; } // if we are not in range
for (int k = firstDayForAverage; k <= lastDayForAverage; k++)
{
averageGainSum = averageGainSum + rsiTable[k, 3]; averageLossSum = averageLossSum + rsiTable[k, 4]; // for numebr of days
}
gainAverage = Math.Round(averageGainSum / noDays,3); //
lossAverage = Math.Round(averageLossSum / noDays,3); // average of 20th day is calculated
rsiTable[firstDayForAverage,5]=gainAverage; // average gain column 5
rsiTable[firstDayForAverage,6]=lossAverage; // average loss column 6
if (lossAverage > 0) { rS = gainAverage / lossAverage; } else { rS = 100; } // calc. loss avarege - value 100 is by definiton
rsiTable[firstDayForAverage, 7] = Math.Round(rS,2); // RS column 7
if (rsiTable[firstDayForAverage, 6] == 0) { rsiTable[firstDayForAverage, 8] = 100; } // calc. of first RSI value (column 8 of nth day)- value 100 is by definiton
else{rsiTable[firstDayForAverage, 8] = Math.Round(100-(100/(1+rsiTable[firstDayForAverage, 7])) ,2);} // RSI column 8
for (int k = firstDayForAverage -1; k > 0; k--) // calculte other RSI valuse
{
gainAverage = Math.Round((rsiTable[k + 1, 5] * (noDays - 1) + rsiTable[k, 3]) / noDays, 3); // previous and today day
lossAverage = Math.Round((rsiTable[k + 1, 6] * (noDays - 1) + rsiTable[k, 4]) / noDays,3);
rsiTable[k, 5] = gainAverage; // fill column 5
rsiTable[k, 6] = lossAverage;
rS = rsiTable[k, 5] / rsiTable[k, 6];
if (rsiTable[k, 6] == 0) { rsI = 100; } else { rsI = Math.Round(100 - 100 / (1 + rS), 2); rsiTable[k, 8] = rsI; } // calclulate RSI
}
rsItext.Text = rsI.ToString(); // fill last value to field rsIText
kraj: ;
}
Thursday, 20 September 2012
29. Japanese candlestiscks and C# - RichTextBox
How to have comments and use RichTextBox control? I can enter free text in commenT (control name) RichTextBox and save it for later. It means when form is loaded or activated commneT is filled with text saved in disk.
So, how to save data from RichTextBox to file. Under menu item Comments are Save and Load code.
This code is used to save content:
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
if (activeIndice.Text == "") { MessageBox.Show("No indice name", "Saving error - Select indice"); goto end1; } // to save file name I need index name
makeSaveFileName msfN = new makeSaveFileName(gloB.workingPath, activeIndice.Text, true); // fix and make file name and path
string fileNameFull = msfN.indexPathName;
string fileName = msfN.indexName;
fileNameFull = fileNameFull.Replace(fileName, fileName + "Comment"); // full file name is finished
File.WriteAllText(fileNameFull, commenT.Text); // save stream to file
end1: ;
}
This is code which fills RichTextBox from text file:
private void loadToolStripMenuItem_Click(object sender, EventArgs e)
{
if (activeIndice.Text == "") { MessageBox.Show("No indice name", "Loading error - Select indice"); goto end1; } // to read file name I need index name
makeSaveFileName msfN = new makeSaveFileName(gloB.workingPath, activeIndice.Text, true); // fix and make file name and path
string fileNameFull = msfN.indexPathName;
string fileName = msfN.indexName;
fileNameFull = fileNameFull.Replace(fileName, fileName + "Comment"); // full name is finished
if (File.Exists(fileNameFull))
{ commenT.Text = File.ReadAllText(fileNameFull); } // load file to form field
end1: ;
}
These codes could be under buttons, no difference.
Code for class MakeFileSaveName which fixes file name and generates filename and path. from indices's name. You can use absolute string definitions for fileNameFull and FileName and comment class:
internal class makeSaveFileName // construct file name from global path and selected index
{
public makeSaveFileName(string patH, string indeX, Boolean daNe)
{
indeX = indeX.Replace(":", "-");
if (daNe== true) indeX = indeX.Replace("CZ", "HR");
indexPathName = patH + indeX + ".txt"; // make full path,file name and add .txt extension as it is text file
indexName=indeX;
}
public string indexPathName { get; private set; }
public string indexName { get; private set;}
}
And small trick if we want to automate saving process. If we put code under event LostFocus of commenT control text we'll be saved as soon as we leave commenT field. We call the procedure under menu control (in bold).
private void commenT_LostFocus(object sender, EventArgs e)
{ saveToolStripMenuItem.PerformClick(); }
This code is used to save content:
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
if (activeIndice.Text == "") { MessageBox.Show("No indice name", "Saving error - Select indice"); goto end1; } // to save file name I need index name
makeSaveFileName msfN = new makeSaveFileName(gloB.workingPath, activeIndice.Text, true); // fix and make file name and path
string fileNameFull = msfN.indexPathName;
string fileName = msfN.indexName;
fileNameFull = fileNameFull.Replace(fileName, fileName + "Comment"); // full file name is finished
File.WriteAllText(fileNameFull, commenT.Text); // save stream to file
end1: ;
}
This is code which fills RichTextBox from text file:
private void loadToolStripMenuItem_Click(object sender, EventArgs e)
{
if (activeIndice.Text == "") { MessageBox.Show("No indice name", "Loading error - Select indice"); goto end1; } // to read file name I need index name
makeSaveFileName msfN = new makeSaveFileName(gloB.workingPath, activeIndice.Text, true); // fix and make file name and path
string fileNameFull = msfN.indexPathName;
string fileName = msfN.indexName;
fileNameFull = fileNameFull.Replace(fileName, fileName + "Comment"); // full name is finished
if (File.Exists(fileNameFull))
{ commenT.Text = File.ReadAllText(fileNameFull); } // load file to form field
end1: ;
}
These codes could be under buttons, no difference.
Code for class MakeFileSaveName which fixes file name and generates filename and path. from indices's name. You can use absolute string definitions for fileNameFull and FileName and comment class:
internal class makeSaveFileName // construct file name from global path and selected index
{
public makeSaveFileName(string patH, string indeX, Boolean daNe)
{
indeX = indeX.Replace(":", "-");
if (daNe== true) indeX = indeX.Replace("CZ", "HR");
indexPathName = patH + indeX + ".txt"; // make full path,file name and add .txt extension as it is text file
indexName=indeX;
}
public string indexPathName { get; private set; }
public string indexName { get; private set;}
}
And small trick if we want to automate saving process. If we put code under event LostFocus of commenT control text we'll be saved as soon as we leave commenT field. We call the procedure under menu control (in bold).
private void commenT_LostFocus(object sender, EventArgs e)
{ saveToolStripMenuItem.PerformClick(); }
Subscribe to:
Posts (Atom)


