#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