#region Using declarations
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Data;
using NinjaTrader.Indicator;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Strategy;
using System.Linq; // check if a value is in array
using System.Collections.Generic; // pouzitie vektorov
#endregion
// This namespace holds all strategies and is required. Do not change it.
namespace NinjaTrader.Strategy
{
///
/// Strategy, where the computer looks after strong S/R lines.
/// If the actual price is on strong S/R line, then check Time & Sales and according to that we can realize to open the position or not
///
[Description("Strategy, where the computer looks after strong S/R lines. If the actual price is on strong S/R line, then check Time & Sales and according to that we can realize to open the position or not")]
public class orderflow : Strategy
{
#region Variables
private List mins = new List(); // declaration of a vector @mins
private List maxs = new List(); // declaration of a vector @maxs
private Dictionary> priceMin = new Dictionary>() ; // declaration of map %priceMin; key=price, value=array of times
private Dictionary> priceMax = new Dictionary>() ; // declaration of map %priceMax; key=price, value=array of times
private List sr = new List(); // vector of support/resistance lines
private int foo = 10; // this variable is used in the findSR() method
private int countOfStagnationBars = 1;
private List stagnationBars = new List();
private List pomPrices = new List(); // analogously like findMins()
private const double tick = 0.25; // value of a tick
private Dictionary> priority = new Dictionary>(); // hash, kluc=$stagnationBars; hodnota=pole cien ktore boli stagnujuce na pocte stagnujucich barov, ktory je klucom tejto struktury
/*
TOTO JE NAJDOLEZITEJSIA STRUKTURA
- budu v nej ulozene informacie, ktore nam budu hovorit, aka silna je dana S/R uroven
- kluce budu ceny, hodnoty budu vektory s hodnotami poctov jednotlivych cien pri roznych countOfStagnationBars, ktore su indexy tohoto vektora
- napr: kluc= 101.75; hodnota=
*/
private Dictionary> p = new Dictionary>(); // cim vyssia hodnota budev tejto mape, tym vacsiu prioritu potencionalny obchod ma
private HashSet set = new HashSet(); // mnozina pripustnych hodnot pri porovnavani dvoch za sebou iducich barov
private double howMuch = 0.50; // udava hodnotu, o kolko +- sa jednotlive po sebe iduce bary mozu lisit tak, aby boli stale stagnujuce. Pouzitie v metode #createSet
#endregion
///
/// This method is used to configure the strategy and is called once before any strategy method is called.
/// ------------------------------------------------------------------------------------------------------
/// Vysvetlivky predpon vyrazov pouzitych v komentaroch tohoto dokumentu:
/// $ -> symbolizuje premennu bazoveho typu (nestrukturovana premenna)
/// @ -> symbolizuje premennu pole
/// % -> symbolizuje asociativne pole
/// # -> symbolizuje nazov metody
///
protected override void Initialize()
{
CalculateOnBarClose = true;
}
///
/// Called on each bar update event (incoming tick)
///
protected override void OnBarUpdate()
{
openPositionControll();
}
/*
#### GETTING BOTTOMS ###
- time will be saved as integer.. same price may have more times
- append actual time into map %priceMin .. key=price; value=array of time
- according to %priceMin we can get the repeating prices == supports
- the support is more stronger if the value of %priceMin (array of time) is bigger
*/
void findMins(){
// the bottom is Close[1]. It takes last 3 bars and analyze if there is bottom of these 3 bars in the middle bar
if((Close[0] > Close[1]) && (Close[1] < Close[2]))
{
List pomTimesOfMins = new List(); // create an empty vector @pomTimesOfMins
if (mins.Contains(Close[1])==false){ // if there’s not $Close[1] then add
mins.Add(Close[1]); // add
}
if (priceMin[Close[1]].Count > 0) { // if the %priceMin[Close[1]] is not empty
pomTimesOfMins = priceMin[Close[1]]; // assign the %priceMin[Close[1]] into @pomTimeMins
pomTimesOfMins.Add(ToTime(Time[1])); // add $Time into @pomTimeMins
priceMin.Add(Close[1],pomTimesOfMins); // actualize the value of %priceMin[Close[1]]
}else{
pomTimesOfMins.Add(ToTime(Time[1]));
priceMin.Add(Close[1],pomTimesOfMins);
}
pomTimesOfMins.Clear(); // clear the List
}
}
/*
#### GETTING TOPS ###
- time will be saved as integer.. same price may have more times
- append actual time into map %priceMax .. key=price; value=array of time
- according to %priceMax we can get the repeating prices == resistance
- the resistance is more stronger if the value of %priceMax (array of time) is bigger */
void findMaxs(){
// the top is Close[1]. It takes last 3 bars and analyze if there is top of these bars in the middle bar
if(Close[0] < Close[1] && Close[1] > Close[2] )
{
List pomTimesOfMaxs = new List(); // analogously like findMins()
if (!maxs.Contains(Close[1])){ // analogously like findMins()
maxs.Add(Close[1]); // analogously like findMins()
}
if (priceMax[Close[1]].Count > 0) { // analogously like findMins()
pomTimesOfMaxs = priceMax[Close[1]]; // analogously like findMins()
pomTimesOfMaxs.Add(ToTime(Time[1])); // analogously like findMins()
priceMax.Add(Close[1],pomTimesOfMaxs); // analogously like findMins()
}else{
pomTimesOfMaxs.Add(ToTime(Time[1]));
priceMax.Add(Close[1],pomTimesOfMaxs);
}
pomTimesOfMaxs.Clear(); // analogously like findMins()
}
}
/*
### GETTING NEW S/R LINES ###
- compares all values of @mins with all values of @maxs
- if there’s match (any value from @mins == any value from @maxs) then Add into vector @sr.
*/
void findSR()
{
findMins();
findMaxs();
if (mins.Count != 0 && maxs.Count != 0) { // if the vectors are not empty
for (int i=0; i= foo*100){ // difference has to be more than 10 minutes
if(!sr.Contains(mins[i])){
sr.Add(mins[i]);
}
}
}
}
}
/*
### IT TESTS IF IT SHOULD OPEN THE POSITION ###
- TO-DO orderflow (buyers vs. sellers)
- if the market is not volatile around the S/R line, than everything’s OK.
*/
void openPositionControll(){
double pom = 0.0; // local variable to store a value of $sr
if(p.ContainsKey(Close[0]) && getStrengthOfSR(Close[0])==true){
if(!isInSRChop(Close[0])){ // if the market is not volatile around the SR line then =>
if(Close[5]Close[0]){ // if the market will come to S/R line from upside and it will touch it, go long
EnterLong();
}
}
}
}
/*
### IT TESTS IF THE MARKET IS VOLATILE AROUND THE S/R ###
- if it's volatile (return TRUE), don't trade
*/
bool isInSRChop(double srValue){
int pom = 0;
bool chop = false;
int i = 10; // 10 is a $constant which says that the market is in chop (is volatile)
// around S/R line if during last 10 bars it touched the S/R line two times.
do{
if(didCrossSR(srValue, i, i-1)){
pom++;
if(pom>=2){
chop = true;
}
}
i--;
}while (pom >= 2 || i==1);
return chop;
}
/*
### IT TESTS THE CROSSING OF S/R LINE ###
*/
bool didCrossSR(double srValue, int a, int b){
bool p = false;
if(Close[a]<=srValue && Close[b]>srValue){
p = true;
}
if(Close[a]>=srValue && Close[b] list = new List();
int a;
//if(Close[0]==Close[1]){
if(areApproxEqual(Close[0], Close[1])==true){
x = Close[0];
countOfStagnationBars++; // 2;3;4....10
}else
if(areApproxEqual(Close[0], Close[1])==false && areApproxEqual(Close[1], Close[2])==true){
// ak dana priorita neobsahuje Close[1] => pridaj do vektora k danej priorite
// spocitaj pocet hodnot $x v kazdej priorite
// uloz do mapy %p,kde key=cena; value=vektor poctu vyskytov v kazdej priorite.. index vektora je priorita
if(!priority[countOfStagnationBars].Contains(Close[1])){ // Close[1] = x
pomPrices = priority[countOfStagnationBars];
pomPrices.Add(x);
priority[countOfStagnationBars] = pomPrices;
}
// spocitat pocet vyskytov v priorite a ulozit do mapy (key=cena; value=vektor poctu vyskytov v kazdej priorite)
insertIntoStagnationBars(countOfStagnationBars);
a = getMaxCountOfStagnationBars();
for(int i=2; i vrat true; inak vrat false
bool pom = false;
createSet(b);
if(set.Contains(a)){
pom = true;
}
set.Clear();
return pom;
}
// vytvori mnozinu hodnot od hodnoty b-howMuch po hodnotu b+howMuch
void createSet(double b){
double i=b-howMuch;
do{
set.Add(i);
i+=tick;
}while(i>=b+howMuch);
}
bool getStrengthOfSR(double a){
// je to silna S/R uroven, ak je sucet v indexoch vacsich od 3 viac ako 3
bool l_pom = false;
int i=3; // i=3 preto, lebo priority ma zaujimaju az od 3 stagnujucich barov
int l_p = 0; // pocita sucet hodnot v indexoch %p vacsich ako 3
int x = getMaxCountOfStagnationBars();
do{
l_p += p[a][i];
if(l_p>=3){
l_pom = true;
}
i++;
}while(l_pom=true || i>=x);
return l_pom;
}
} // END OF CLASS orderflow: Strategy
} // END OF NAMESPACE NinjaTrader.Strategy