/// <summary> /// Saves bar data to a CSV file. /// </summary> private void SaveBars(List <Bar> barList, DataPeriods period) { var sb = new StringBuilder(); foreach (Bar bar in barList) { sb.AppendLine( String.Format("{0:D4}-{1:D2}-{2:D2}\t{3:D2}:{4:D2}\t{5}\t{6}\t{7}\t{8}\t{9}", bar.Time.Year, bar.Time.Month, bar.Time.Day, bar.Time.Hour, bar.Time.Minute, bar.Open, bar.High, bar.Low, bar.Close, bar.Volume)); } string fileName = TxbSymbol.Text + (int)period + ".csv"; string path = Path.Combine(_outFolder, fileName); try { var sw = new StreamWriter(path); sw.Write(sb.ToString()); sw.Close(); SetInfoText(Language.T("Saved") + " " + Data.DataPeriodToString(period) + " " + Language.T("bars") + " - " + barList.Count + Environment.NewLine); } catch (Exception exc) { MessageBox.Show(exc.Message); } }
/// <summary> /// Updates the chart. /// </summary> protected void UpdateChart() { if (_chart == null) return; bool repaintChart = ( _chartSymbol != Data.Symbol || _chartPeriod != Data.Period || _chartBars != Data.Bars || _chartTime != Data.Time[Data.Bars - 1] || _chartTime10 != Data.Time[Data.Bars - 11]); _chartSymbol = Data.Symbol; _chartPeriod = Data.Period; _chartBars = Data.Bars; _chartTime = Data.Time[Data.Bars - 1]; _chartTime10 = Data.Time[Data.Bars - 11]; // Prepares chart data. ChartData chartData = GetChartDataObject(); try { UpdateChartThreadSafely(repaintChart, chartData); } catch (ObjectDisposedException) { } catch (Exception exc) { MessageBox.Show(exc.Message, Language.T("Indicator Chart"), MessageBoxButtons.OK, MessageBoxIcon.Error); DisposeChart(); CreateChart(); } }
/// <summary> /// Gets the tick type depending on its time. /// </summary> TickType GetTickType(DataPeriods period, DateTime open, DateTime time, int volume) { TickType tick = TickType.Regular; bool isOpen = volume == 1 && barOpenTimeForLastOpenTick != open; bool isClose = (open.AddMinutes((int)period) - time) < TimeSpan.FromSeconds(Configs.BarCloseAdvance); if (isOpen) { barOpenTimeForLastCloseTick = DateTime.MinValue; tick = TickType.Open; } if (isClose) { if (barOpenTimeForLastCloseTick == open) { tick = TickType.AfterClose; } else { barOpenTimeForLastCloseTick = open; tick = isOpen ? TickType.OpenClose : TickType.Close; } } return(tick); }
private List <Bar> CompileBars(IEnumerable <Bar> minuteBarList, DataPeriods period) { var barList = new List <Bar>(); var lastBarEndTime = new DateTime(); foreach (var bar in minuteBarList) { if (bar.Time >= lastBarEndTime) { DateTime lastBarStartTime = GetBarStartTime(bar.Time, (int)period); lastBarEndTime = lastBarStartTime.AddMinutes((int)period); Bar newBar = bar; newBar.Time = lastBarStartTime; barList.Add(newBar); continue; } Bar lastBar = barList[barList.Count - 1]; if (lastBar.High < bar.High) { lastBar.High = bar.High; } if (lastBar.Low > bar.Low) { lastBar.Low = bar.Low; } lastBar.Close = bar.Close; lastBar.Volume += bar.Volume; barList[barList.Count - 1] = lastBar; } return(barList); }
/// <summary> /// Converts a data period from DataPeriods type to string. /// </summary> public static string DataPeriodToString(DataPeriods dataPeriod) { switch (dataPeriod) { case DataPeriods.min1: return("1 " + Language.T("Minute")); case DataPeriods.min5: return("5 " + Language.T("Minutes")); case DataPeriods.min15: return("15 " + Language.T("Minutes")); case DataPeriods.min30: return("30 " + Language.T("Minutes")); case DataPeriods.hour1: return("1 " + Language.T("Hour")); case DataPeriods.hour4: return("4 " + Language.T("Hours")); case DataPeriods.day: return("1 " + Language.T("Day")); case DataPeriods.week: return("1 " + Language.T("Week")); default: return(String.Empty); } }
/// <summary> /// Check the needed market conditions /// </summary> /// <param name="isMessage">To show the message or not</param> void AfterStrategyOpening(bool isMessage) { if (Data.Strategy.Symbol != Data.Symbol || Data.Strategy.DataPeriod != Data.Period) { bool toReload = true; if (isMessage) { DialogResult result; result = MessageBox.Show( Language.T("The loaded strategy has been designed for a different market!") + Environment.NewLine + Environment.NewLine + Data.Strategy.Symbol + " " + Data.DataPeriodToString(Data.Strategy.DataPeriod) + Environment.NewLine + Environment.NewLine + Language.T("Do you want to load this market data?"), Data.Strategy.StrategyName, MessageBoxButtons.YesNo, MessageBoxIcon.Question); toReload = (result == DialogResult.Yes); } if (toReload) { if (!Instruments.InstrumentList.ContainsKey(Data.Strategy.Symbol)) { MessageBox.Show( Language.T("There is no information for this market!") + Environment.NewLine + Environment.NewLine + Data.Strategy.Symbol + " " + Data.DataPeriodToString(Data.Strategy.DataPeriod), Data.Strategy.StrategyName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } string symbol = Data.Symbol; DataPeriods dataPeriod = Data.Period; SetMarket(Data.Strategy.Symbol, Data.Strategy.DataPeriod); if (LoadInstrument(false) == 0) { Calculate(true); PrepareScannerCompactMode(); } else { SetMarket(symbol, dataPeriod); } } } else if (!Data.IsIntrabarData) { PrepareScannerCompactMode(); } return; }
/// <summary> /// Sets the market according the strategy /// </summary> void SetMarket(string symbol, DataPeriods dataPeriod) { Data.InstrProperties = Instruments.InstrumentList[symbol].Clone(); Data.Period = dataPeriod; isDiscardSelectedIndexChange = true; tscbSymbol.SelectedIndex = tscbSymbol.Items.IndexOf(symbol); switch (dataPeriod) { case DataPeriods.min1: tscbPeriod.SelectedIndex = 0; break; case DataPeriods.min5: tscbPeriod.SelectedIndex = 1; break; case DataPeriods.min15: tscbPeriod.SelectedIndex = 2; break; case DataPeriods.min30: tscbPeriod.SelectedIndex = 3; break; case DataPeriods.hour1: tscbPeriod.SelectedIndex = 4; break; case DataPeriods.hour4: tscbPeriod.SelectedIndex = 5; break; case DataPeriods.day: tscbPeriod.SelectedIndex = 6; break; case DataPeriods.week: tscbPeriod.SelectedIndex = 7; break; default: break; } isDiscardSelectedIndexChange = false; return; }
/// <summary> /// Check if the incoming data is from the same chart. /// </summary> bool IsChartChangeged(string symbol, DataPeriods period) { if (!Data.IsConnected) { return(true); } if (Data.Symbol != symbol || Data.Period != period) { return(true); } return(false); }
protected override void TsbtTrading_Click(object sender, EventArgs e) { if (isTrading) { StopTrade(); symbolReconnect = ""; periodReconnect = DataPeriods.week; accountReconnect = 0; } else { StartTrade(); } }
/// <summary> /// Saves the strategy in XML format. /// </summary> public void Save(string fileName) { strategyName = Path.GetFileNameWithoutExtension(fileName); symbol = Data.Symbol; period = Data.Period; // Create the XmlDocument. Strategy_XML strategyXML = new Strategy_XML(); XmlDocument xmlDocStrategy = strategyXML.CreateStrategyXmlDoc(this); try { xmlDocStrategy.Save(fileName); // Save the document to a file. } catch (Exception e) { System.Windows.Forms.MessageBox.Show(e.Message); } }
/// <summary> /// Starts the trade. /// </summary> void StartTrade() { isTrading = true; // Resets trade global variables. InitTrade(); Data.SetStartTradingTime(); JournalMessage msg = new JournalMessage(JournalIcons.StartTrading, DateTime.Now, Language.T("Automatic trade started.")); AppendJournalMessage(msg); symbolReconnect = Data.Symbol; periodReconnect = Data.Period; accountReconnect = Data.AccountNumber; barOpenTimeForLastCloseEvent = Data.Time[Data.Bars - 1]; SetTradeStrip(); return; }
/// <summary> /// Updates the chart. /// </summary> protected void UpdateChart() { if (chart == null) { return; } bool repaintChart = ( chartSymbol != Data.Symbol || chartPeriod != Data.Period || chartBars != Data.Bars || chartTime != Data.Time[Data.Bars - 1] || chartTime10 != Data.Time[Data.Bars - 11]); chartSymbol = Data.Symbol; chartPeriod = Data.Period; chartBars = Data.Bars; chartTime = Data.Time[Data.Bars - 1]; chartTime10 = Data.Time[Data.Bars - 11]; // Prepares chart data. Chart_Data chartData = GetChartDataObject(); try { UpdateChartThreadSafely(repaintChart, chartData); } catch (ObjectDisposedException) { return; } catch (Exception exc) { MessageBox.Show(exc.Message, Language.T("Indicator Chart"), MessageBoxButtons.OK, MessageBoxIcon.Error); DisposeChart(); CreateChart(); } return; }
/// <summary> /// LoadInstrument /// </summary> int LoadInstrument(bool bUseResource) { string sSymbol = "EURUSD"; DataPeriods dataPeriod = DataPeriods.day; Instrument_Properties instrProperties = new Instrument_Properties(sSymbol); Instrument instrument = new Instrument(instrProperties, (int)dataPeriod); int iLoadDataResult = instrument.LoadResourceData(); if (instrument.Bars > 0 && iLoadDataResult == 0) { Data.InstrProperties = instrProperties.Clone(); Data.Bars = instrument.Bars; Data.Period = dataPeriod; Data.Time = new DateTime[Data.Bars]; Data.Open = new double[Data.Bars]; Data.High = new double[Data.Bars]; Data.Low = new double[Data.Bars]; Data.Close = new double[Data.Bars]; Data.Volume = new int[Data.Bars]; for (int iBar = 0; iBar < Data.Bars; iBar++) { Data.Open[iBar] = instrument.Open(iBar); Data.High[iBar] = instrument.High(iBar); Data.Low[iBar] = instrument.Low(iBar); Data.Close[iBar] = instrument.Close(iBar); Data.Time[iBar] = instrument.Time(iBar); Data.Volume[iBar] = instrument.Volume(iBar); } Data.IsData = true; } return(0); }
/// <summary> /// LoadInstrument /// </summary> private void LoadInstrument() { const string symbol = "EURUSD"; const DataPeriods dataPeriod = DataPeriods.day; var instrProperties = new InstrumentProperties(symbol); var instrument = new Instrument(instrProperties, (int)dataPeriod); int loadResourceData = instrument.LoadResourceData(); if (instrument.Bars <= 0 || loadResourceData != 0) { return; } Data.InstrProperties = instrProperties.Clone(); Data.Bars = instrument.Bars; Data.Period = dataPeriod; Data.Time = new DateTime[Data.Bars]; Data.Open = new double[Data.Bars]; Data.High = new double[Data.Bars]; Data.Low = new double[Data.Bars]; Data.Close = new double[Data.Bars]; Data.Volume = new int[Data.Bars]; for (int bar = 0; bar < Data.Bars; bar++) { Data.Open[bar] = instrument.Open(bar); Data.High[bar] = instrument.High(bar); Data.Low[bar] = instrument.Low(bar); Data.Close[bar] = instrument.Close(bar); Data.Time[bar] = instrument.Time(bar); Data.Volume[bar] = instrument.Volume(bar); } Data.IsData = true; }
private void StoreConfigs() { maxBarsDefault = Configs.MaxBars; isCheckDataDefault = Configs.CheckData; isFillDataGapsDefault = Configs.FillInDataGaps; isCutBadDataDefault = Configs.CutBadData; isCutSatSunDataDefault = Configs.CutSatSunData; isUseEndTimeDefault = Configs.UseEndTime; isUseStartTimeDefault = Configs.UseStartTime; isUseTickDataDefault = Configs.UseTickData; isAutoscanDefault = Configs.Autoscan; isAccountInCurrencyDefault = Configs.AccountInMoney; accountCurrencyDefault = Configs.AccountCurrency; initialAccountDefault = Configs.InitialAccount; leverageDefault = Configs.Leverage; isTradeUntilMarginCallDefault = Configs.TradeUntilMarginCall; isAdditionalStatsDefault = Configs.AdditionalStatistics; isUseLogicalGroupsDefault = Configs.UseLogicalGroups; symbolDefault = Data.Symbol; periodDefault = Data.Period; instrPropertiesDefault = Instruments.InstrumentList[symbolDefault].Clone(); strategyDefault = Data.Strategy.Clone(); }
/// <summary> /// Loads the data. /// </summary> void LoadData(BackgroundWorker worker, DoWorkEventArgs e) { int periodsToLoad = 0; int allPeriods = Enum.GetValues(typeof(DataPeriods)).Length; Data.IntraBars = new int[allPeriods]; Data.IntraBarData = new Bar[Data.Bars][]; Data.IntraBarBars = new int[Data.Bars]; Data.IntraBarsPeriods = new DataPeriods[Data.Bars]; Data.LoadedIntraBarPeriods = 0; for (int bar = 0; bar < Data.Bars; bar++) { Data.IntraBarsPeriods[bar] = Data.Period; Data.IntraBarBars[bar] = 0; } // Counts how many periods to load for (int prd = 0; prd < allPeriods; prd++) { DataPeriods period = (DataPeriods)Enum.GetValues(typeof(DataPeriods)).GetValue(prd); if (period < Data.Period) { periodsToLoad++; } } // Load the intrabar data (Starts from 1 Min) for (int prd = 0; prd < allPeriods && isLoadingNow; prd++) { if (worker.CancellationPending) { break; } int loadedBars = 0; DataPeriods period = (DataPeriods)Enum.GetValues(typeof(DataPeriods)).GetValue(prd); SetLabelProgressText(Language.T("Loading:") + " " + Data.DataPeriodToString(period) + "..."); if (period < Data.Period) { loadedBars = LoadIntrabarData(period); if (loadedBars > 0) { Data.IsIntrabarData = true; Data.LoadedIntraBarPeriods++; } } else if (period == Data.Period) { loadedBars = Data.Bars; Data.LoadedIntraBarPeriods++; } Data.IntraBars[prd] = loadedBars; // Report progress as a percentage of the total task. int percentComplete = periodsToLoad > 0 ? 100 * (prd + 1) / periodsToLoad : 100; percentComplete = percentComplete > 100 ? 100 : percentComplete; if (percentComplete > progressPercent) { progressPercent = percentComplete; worker.ReportProgress(percentComplete); } } CheckIntrabarData(); RepairIntrabarData(); if (Configs.UseTickData) { SetLabelProgressText(Language.T("Loading:") + " " + Language.T("Ticks") + "..."); worker.ReportProgress(200); try { LoadTickData(); } catch (Exception ex) { MessageBox.Show(ex.Message); } } return; }
/// <summary> /// Converts a data period from DataPeriods type to string. /// </summary> public static string DataPeriodToString(DataPeriods dataPeriod) { switch (dataPeriod) { case DataPeriods.min1: return "1 " + Language.T("Minute"); case DataPeriods.min5: return "5 " + Language.T("Minutes"); case DataPeriods.min15: return "15 " + Language.T("Minutes"); case DataPeriods.min30: return "30 " + Language.T("Minutes"); case DataPeriods.hour1: return "1 " + Language.T("Hour"); case DataPeriods.hour4: return "4 " + Language.T("Hours"); case DataPeriods.day: return "1 " + Language.T("Day"); case DataPeriods.week: return "1 " + Language.T("Week"); default: return String.Empty; } }
/// <summary> /// Gets the tick type depending on its time. /// </summary> private TickType GetTickType(DataPeriods period, DateTime open, DateTime time, int volume) { TickType tick = TickType.Regular; bool isOpen = volume == 1 && _barOpenTimeForLastOpenTick != open; bool isClose = (open.AddMinutes((int) period) - time) < TimeSpan.FromSeconds(Configs.BarCloseAdvance); if (isOpen) { _barOpenTimeForLastCloseTick = DateTime.MinValue; tick = TickType.Open; } if (isClose) { if (_barOpenTimeForLastCloseTick == open) { tick = TickType.AfterClose; } else { _barOpenTimeForLastCloseTick = open; tick = isOpen ? TickType.OpenClose : TickType.Close; } } return tick; }
/// <summary> /// Sets the instrument's properties after connecting; /// </summary> private bool UpdateDataFeedInfo(DateTime time, string symbol, DataPeriods period) { lock (_lockerDataFeed) { Data.ResetBidAskClose(); Data.ResetAccountStats(); Data.ResetPositionStats(); Data.ResetBarStats(); Data.ResetTicks(); // Reads market info from the chart MT4Bridge.MarketInfo marketInfo = _bridge.GetMarketInfoAll(symbol); if (marketInfo == null) { if (JournalShowSystemMessages) { var jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (PeriodType) (int) period + " " + Language.T("Cannot update market info.")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } return false; } // Sets instrument properties Data.Period = period; Data.InstrProperties.Symbol = symbol; Data.InstrProperties.LotSize = (int) marketInfo.ModeLotSize; Data.InstrProperties.MinLot = marketInfo.ModeMinLot; Data.InstrProperties.MaxLot = marketInfo.ModeMaxLot; Data.InstrProperties.LotStep = marketInfo.ModeLotStep; Data.InstrProperties.Digits = (int) marketInfo.ModeDigits; Data.InstrProperties.Spread = marketInfo.ModeSpread; Data.InstrProperties.SwapLong = marketInfo.ModeSwapLong; Data.InstrProperties.SwapShort = marketInfo.ModeSwapShort; Data.InstrProperties.TickValue = marketInfo.ModeTickValue; Data.InstrProperties.StopLevel = marketInfo.ModeStopLevel; Data.InstrProperties.MarginRequired = marketInfo.ModeMarginRequired; SetNumUpDownLots(marketInfo.ModeMinLot, marketInfo.ModeLotStep, marketInfo.ModeMaxLot); // Sets Market Info var values = new[] { symbol, Data.DataPeriodToString(period), marketInfo.ModeLotSize.ToString(CultureInfo.InvariantCulture), marketInfo.ModePoint.ToString("F" + marketInfo.ModeDigits.ToString(CultureInfo.InvariantCulture)), marketInfo.ModeSpread.ToString(CultureInfo.InvariantCulture), marketInfo.ModeSwapLong.ToString(CultureInfo.InvariantCulture), marketInfo.ModeSwapShort.ToString(CultureInfo.InvariantCulture) }; UpdateStatusPageMarketInfo(values); Bars bars = _bridge.GetBars(symbol, (PeriodType) (int) period); if (bars == null) { if (JournalShowSystemMessages) { Data.SoundError.Play(); var jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (PeriodType) (int) period + " " + Language.T("Cannot receive bars!")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } return false; } if (bars.Count < MaxBarsCount((int) period)) { if (JournalShowSystemMessages) { Data.SoundError.Play(); var jmsgsys = new JournalMessage(JournalIcons.Error, DateTime.Now, symbol + " " + (PeriodType) (int) period + " " + Language.T("Cannot receive enough bars!")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } return false; } if (JournalShowSystemMessages) { var jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (PeriodType) (int) period + " " + Language.T("Market data updated, bars downloaded.")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } // Account Information. AccountInfo account = _bridge.GetAccountInfo(); if (account == null) { if (JournalShowSystemMessages) { Data.SoundError.Play(); var jmsgsys = new JournalMessage(JournalIcons.Error, DateTime.Now, symbol + " " + (PeriodType) (int) period + " " + Language.T("Cannot receive account information!")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } return false; } if (JournalShowSystemMessages) { var jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (PeriodType) (int) period + " " + Language.T("Account information received.")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } Data.AccountName = account.Name; Data.IsDemoAccount = account.IsDemo; Data.AccountCurrency = account.Currency; Data.SetCurrentAccount(time, account.Balance, account.Equity, account.Profit, account.FreeMargin); UpdateBalanceChart(Data.BalanceData, Data.BalanceDataPoints); SetTradeStrip(); SetLblSymbolText(symbol); } return true; }
/// <summary> /// Calculates the indicator's components /// </summary> public override void Calculate(SlotTypes slotType) { // Reading the parameters MAMethod maMethod = (MAMethod)IndParam.ListParam[1].Index; int iK = (int)IndParam.NumParam[0].Value; int iDFast = (int)IndParam.NumParam[1].Value; int iDSlow = (int)IndParam.NumParam[2].Value; int iLevel = (int)IndParam.NumParam[3].Value; int iPrvs = IndParam.CheckParam[0].Checked ? 1 : 0; // Convert to Higher Time Frame --------------------------------------------- DataPeriods htfPeriod = DataPeriods.week; double[] hfOpen = new double[Bars]; double[] hfClose = new double[Bars]; double[] hfHigh = new double[Bars]; double[] hfLow = new double[Bars]; double[] hfVolume = new double[Bars]; double[] hfPrice = new double[Bars]; int[] hIndex = new int[Bars]; int iFrame; int hBars; switch (IndParam.ListParam[4].Index) { case 1: htfPeriod = DataPeriods.min5; break; case 2: htfPeriod = DataPeriods.min15; break; case 3: htfPeriod = DataPeriods.min30; break; case 4: htfPeriod = DataPeriods.hour1; break; case 5: htfPeriod = DataPeriods.hour4; break; case 6: htfPeriod = DataPeriods.day; break; case 7: htfPeriod = DataPeriods.week; break; } int err1 = HigherTimeFrame(Period, htfPeriod, out hIndex, out hBars, out iFrame, out hfHigh, out hfLow, out hfOpen, out hfClose, out hfVolume); //int err2 = HigherBasePrice(basePrice, hBars, hfHigh, hfLow, hfOpen, hfClose, out hfPrice); if (err1 == 1) { return; } //------------------------------------------------------------------------ // Calculation int iFirstBar = iK + iDFast + iDSlow + 3; double[] adHighs = new double[Bars]; double[] adLows = new double[Bars]; for (int iBar = iK; iBar < hBars; iBar++) { double dMin = double.MaxValue; double dMax = double.MinValue; for (int i = 0; i < iK; i++) { if (hfHigh[iBar - i] > dMax) { dMax = hfHigh[iBar - i]; } if (hfLow[iBar - i] < dMin) { dMin = hfLow[iBar - i]; } } adHighs[iBar] = dMax; adLows[iBar] = dMin; } double[] adK = new double[Bars]; for (int iBar = iK; iBar < hBars; iBar++) { if (adHighs[iBar] == adLows[iBar]) { adK[iBar] = 50; } else { adK[iBar] = 100 * (hfClose[iBar] - adLows[iBar]) / (adHighs[iBar] - adLows[iBar]); } } double[] adDFast = new double[Bars]; for (int iBar = iDFast; iBar < hBars; iBar++) { double dSumHigh = 0; double dSumLow = 0; for (int i = 0; i < iDFast; i++) { dSumLow += hfClose[iBar - i] - adLows[iBar - i]; dSumHigh += adHighs[iBar - i] - adLows[iBar - i]; } if (dSumHigh == 0) { adDFast[iBar] = 100; } else { adDFast[iBar] = 100 * dSumLow / dSumHigh; } } double[] adDSlow = MovingAverage(iDSlow, 0, maMethod, adDFast); // Convert to Current Time Frame ---------------------------------------------- /// start WTF modfication 2 version 4 // copy of wider time frame array of values double[] hadK = new double[Bars]; double[] hadDFast = new double[Bars]; double[] hadDSlow = new double[Bars]; adK.CopyTo(hadK, 0); adDFast.CopyTo(hadDFast, 0); adDSlow.CopyTo(hadDSlow, 0); int err3 = CurrentTimeFrame(hIndex, hBars, ref adK); int err4 = CurrentTimeFrame(hIndex, hBars, ref adDFast); int err5 = CurrentTimeFrame(hIndex, hBars, ref adDSlow); // if any error, return out of calculation and indicator fails silently if (err3 == 1 || err4 == 1 || err5 == 1) { return; } /// end WTF modfication 2 version 4 //----------------------------------------------------------------------------- // Saving the components Component = new IndicatorComp[5]; Component[0] = new IndicatorComp(); Component[0].CompName = "%K"; Component[0].DataType = IndComponentType.IndicatorValue; Component[0].ChartType = IndChartType.Line; Component[0].ChartColor = Color.Brown; Component[0].FirstBar = iFirstBar; Component[0].Value = adK; Component[1] = new IndicatorComp(); Component[1].CompName = "Fast %D"; Component[1].DataType = IndComponentType.IndicatorValue; Component[1].ChartType = IndChartType.Line; Component[1].ChartColor = Color.Yellow; Component[1].FirstBar = iFirstBar; Component[1].Value = adDFast; Component[2] = new IndicatorComp(); Component[2].CompName = "Slow %D"; Component[2].DataType = IndComponentType.IndicatorValue; Component[2].ChartType = IndChartType.Line; Component[2].ChartColor = Color.Blue; Component[2].FirstBar = iFirstBar; Component[2].Value = adDSlow; Component[3] = new IndicatorComp(); Component[3].ChartType = IndChartType.NoChart; Component[3].FirstBar = iFirstBar; Component[3].Value = new double[Bars]; Component[4] = new IndicatorComp(); Component[4].ChartType = IndChartType.NoChart; Component[4].FirstBar = iFirstBar; Component[4].Value = new double[Bars]; // Sets the Component's type if (slotType == SlotTypes.OpenFilter) { Component[3].DataType = IndComponentType.AllowOpenLong; Component[3].CompName = "Is long entry allowed"; Component[4].DataType = IndComponentType.AllowOpenShort; Component[4].CompName = "Is short entry allowed"; } else if (slotType == SlotTypes.CloseFilter) { Component[3].DataType = IndComponentType.ForceCloseLong; Component[3].CompName = "Close out long position"; Component[4].DataType = IndComponentType.ForceCloseShort; Component[4].CompName = "Close out short position"; } // Calculation of the logic IndicatorLogic indLogic = IndicatorLogic.It_does_not_act_as_a_filter; /// start WTF modfication 3 version 4 // back up Bars value, reset to hBars, for performance improvement in indicator logic function int mtfBars = Data.Bars; Data.Bars = hBars; // use wtf values here, then do expansion after this if clause to cover these IndicatorCrosses cases and the OscillatorLogic cases // replace very small values with 0 for performance improvement; don't know why but works for (int ctr = 0; ctr < hadDSlow.Length; ctr++) { hadK[ctr] = (hadK[ctr] < .000000001 && hadK[ctr] > -.000000001) ? 0 : hadK[ctr]; hadDSlow[ctr] = (hadDSlow[ctr] < .000000001 && hadDSlow[ctr] > -.000000001) ? 0 : hadDSlow[ctr]; } if (IndParam.ListParam[0].Text == "The %K crosses the Slow %D upward") { SpecialValues = new double[1] { 50 }; IndicatorCrossesAnotherIndicatorUpwardLogic(iFirstBar, iPrvs, hadK, hadDSlow, ref Component[3], ref Component[4]); } else if (IndParam.ListParam[0].Text == "The %K crosses the Slow %D downward") { SpecialValues = new double[1] { 50 }; IndicatorCrossesAnotherIndicatorDownwardLogic(iFirstBar, iPrvs, hadK, hadDSlow, ref Component[3], ref Component[4]); } else if (IndParam.ListParam[0].Text == "The %K is higher than the Slow %D") { SpecialValues = new double[1] { 50 }; IndicatorIsHigherThanAnotherIndicatorLogic(iFirstBar, iPrvs, hadK, hadDSlow, ref Component[3], ref Component[4]); } else if (IndParam.ListParam[0].Text == "The %K is lower than the Slow %D") { SpecialValues = new double[1] { 50 }; IndicatorIsLowerThanAnotherIndicatorLogic(iFirstBar, iPrvs, hadK, hadDSlow, ref Component[3], ref Component[4]); } else { switch (IndParam.ListParam[0].Text) { case "The Slow %D rises": indLogic = IndicatorLogic.The_indicator_rises; SpecialValues = new double[1] { 50 }; break; case "The Slow %D falls": indLogic = IndicatorLogic.The_indicator_falls; SpecialValues = new double[1] { 50 }; break; case "The Slow %D is higher than the Level line": indLogic = IndicatorLogic.The_indicator_is_higher_than_the_level_line; SpecialValues = new double[2] { iLevel, 100 - iLevel }; break; case "The Slow %D is lower than the Level line": indLogic = IndicatorLogic.The_indicator_is_lower_than_the_level_line; SpecialValues = new double[2] { iLevel, 100 - iLevel }; break; case "The Slow %D crosses the Level line upward": indLogic = IndicatorLogic.The_indicator_crosses_the_level_line_upward; SpecialValues = new double[2] { iLevel, 100 - iLevel }; break; case "The Slow %D crosses the Level line downward": indLogic = IndicatorLogic.The_indicator_crosses_the_level_line_downward; SpecialValues = new double[2] { iLevel, 100 - iLevel }; break; case "The Slow %D changes its direction upward": indLogic = IndicatorLogic.The_indicator_changes_its_direction_upward; SpecialValues = new double[1] { 50 }; break; case "The Slow %D changes its direction downward": indLogic = IndicatorLogic.The_indicator_changes_its_direction_downward; SpecialValues = new double[1] { 50 }; break; default: break; } OscillatorLogic(iFirstBar, iPrvs, hadDSlow, iLevel, 100 - iLevel, ref Component[3], ref Component[4], indLogic); } // resest Bars to real value Data.Bars = mtfBars; // expand component array from wtf to current time frame double[] wtfCompValue = Component[3].Value; int err6 = CurrentTimeFrame(hIndex, hBars, ref wtfCompValue); if (err6 == 1) { return; } Component[3].Value = wtfCompValue; wtfCompValue = Component[4].Value; int err7 = CurrentTimeFrame(hIndex, hBars, ref wtfCompValue); if (err7 == 1) { return; } Component[4].Value = wtfCompValue; /// end WTF modfication 3 version 4 return; }
/// <summary> /// Calculates the indicator's components /// </summary> public override void Calculate(SlotTypes slotType) { int SSP = (int)IndParam.NumParam[0].Value; int SSK = (int)IndParam.NumParam[2].Value; //int iSenkou = (int)IndParam.NumParam[4].Value; int iPrvs = IndParam.CheckParam[0].Checked ? 1 : 0; // Convert to Higher Time Frame --------------------------------------------- DataPeriods htfPeriod = DataPeriods.week; double[] hfOpen = new double[Bars]; double[] hfClose = new double[Bars]; double[] hfHigh = new double[Bars]; double[] hfLow = new double[Bars]; double[] hfVolume = new double[Bars]; double[] hfPrice = new double[Bars]; int[] hIndex = new int[Bars]; int iFrame; int hBars; switch (IndParam.ListParam[4].Index) { case 0: htfPeriod = DataPeriods.hour1; break; case 1: htfPeriod = DataPeriods.min5; break; case 2: htfPeriod = DataPeriods.min15; break; case 3: htfPeriod = DataPeriods.min30; break; case 4: htfPeriod = DataPeriods.hour1; break; case 5: htfPeriod = DataPeriods.hour4; break; case 6: htfPeriod = DataPeriods.day; break; case 7: htfPeriod = DataPeriods.week; break; } int err1 = HigherTimeFrame(Period, htfPeriod, out hIndex, out hBars, out iFrame, out hfHigh, out hfLow, out hfOpen, out hfClose, out hfVolume); // not used for this indicator, always uses Highs and Lows // int err2 = HigherBasePrice(basePrice, hBars, hfHigh, hfLow, hfOpen, hfClose, out hfPrice); //------------------------------------------------------------------------ // this is never used // double[] adMedianPrice = Price(BasePrice.Median); int iFirstBar = 1 + SSP * 2 + SSK; double[] adTenkanSen = new double[Bars]; for (int iBar = iFirstBar; iBar < hBars; iBar++) { double dHighestHigh = double.MinValue; double dLowestLow = double.MaxValue; for (int i = 0; i < SSP; i++) { if (hfHigh[iBar - i] > dHighestHigh) { dHighestHigh = hfHigh[iBar - i]; } if (hfLow[iBar - i] < dLowestLow) { dLowestLow = hfLow[iBar - i]; } } double dHighestHigh1 = double.MinValue; double dLowestLow1 = double.MaxValue; for (int i = SSK; i < SSK + SSP; i++) { if (hfHigh[iBar - i] > dHighestHigh1) { dHighestHigh1 = hfHigh[iBar - i]; } if (hfLow[iBar - i] < dLowestLow1) { dLowestLow1 = hfLow[iBar - i]; } } adTenkanSen[iBar] = ((dHighestHigh + dLowestLow) / 2 + (dHighestHigh1 + dLowestLow1) / 2) / 2; } double[] adKijunSen = new double[Bars]; // (gi_112 = Bars - SSP; gi_112 >= 0; gi_112--) for (int iBar = iFirstBar; iBar < hBars; iBar++) { double dHighestHigh = double.MinValue; double dLowestLow = double.MaxValue; for (int i = 0; i < 1.62 * SSP; i++) { if (hfHigh[iBar - i] > dHighestHigh) { dHighestHigh = hfHigh[iBar - i]; } if (hfLow[iBar - i] < dLowestLow) { dLowestLow = hfLow[iBar - i]; } } adKijunSen[iBar] = (dHighestHigh + dLowestLow) / 2; } double[] adChikouSpan = new double[Bars]; for (int iBar = iFirstBar; iBar < hBars; iBar++) { adChikouSpan[iBar] = adTenkanSen[iBar]; } double[] adSenkouSpanA = new double[Bars]; for (int iBar = iFirstBar; iBar < hBars; iBar++) { double dHighestHigh = double.MinValue; double dLowestLow = double.MaxValue; for (int i = 0; i < SSP; i++) { if (hfHigh[iBar - i] > dHighestHigh) { dHighestHigh = hfHigh[iBar - i]; } if (hfLow[iBar - i] < dLowestLow) { dLowestLow = hfLow[iBar - i]; } } adSenkouSpanA[iBar] = (dHighestHigh + dLowestLow) / 2; } double[] adSenkouSpanB = new double[Bars]; for (int iBar = iFirstBar; iBar < hBars; iBar++) { double dHighestHigh = double.MinValue; double dLowestLow = double.MaxValue; for (int i = SSK; i < SSK + SSP; i++) { if (hfHigh[iBar - i] > dHighestHigh) { dHighestHigh = hfHigh[iBar - i]; } if (hfLow[iBar - i] < dLowestLow) { dLowestLow = hfLow[iBar - i]; } } adSenkouSpanB[iBar] = (dHighestHigh + dLowestLow) / 2; } // Convert to Current Time Frame ---------------------------------------------- /// start WTF modfication 2 version 4 // copy of wider time frame array of values double[] hadTenkanSen = new double[Bars]; double[] hadKijunSen = new double[Bars]; double[] hadChikouSpan = new double[Bars]; double[] hadSenkouSpanA = new double[Bars]; double[] hadSenkouSpanB = new double[Bars]; adTenkanSen.CopyTo(hadTenkanSen, 0); adKijunSen.CopyTo(hadKijunSen, 0); adChikouSpan.CopyTo(hadChikouSpan, 0); adSenkouSpanA.CopyTo(hadSenkouSpanA, 0); adSenkouSpanB.CopyTo(hadSenkouSpanB, 0); int err3 = CurrentTimeFrame(hIndex, hBars, ref adTenkanSen); int err4 = CurrentTimeFrame(hIndex, hBars, ref adKijunSen); int err5 = CurrentTimeFrame(hIndex, hBars, ref adChikouSpan); int err6 = CurrentTimeFrame(hIndex, hBars, ref adSenkouSpanA); int err7 = CurrentTimeFrame(hIndex, hBars, ref adSenkouSpanB); // if any error, return out of calculation and indicator fails silently if (err3 == 1 || err4 == 1 || err5 == 1 || err6 == 1 || err7 == 1) { return; } /// end WTF modfication 2 version 4 //----------------------------------------------------------------------------- // Saving the components if (slotType == SlotTypes.OpenFilter) { Component = new IndicatorComp[7]; } else { Component = new IndicatorComp[6]; } Component[0] = new IndicatorComp(); Component[0].CompName = "Middle line"; Component[0].DataType = IndComponentType.IndicatorValue; Component[0].ChartType = IndChartType.Line; Component[0].ChartColor = Color.Red; Component[0].FirstBar = iFirstBar; Component[0].Value = adTenkanSen; Component[1] = new IndicatorComp(); Component[1].CompName = "Stop-order line"; Component[1].DataType = IndComponentType.IndicatorValue; Component[1].ChartType = IndChartType.Line; Component[1].ChartColor = Color.Blue; Component[1].FirstBar = iFirstBar; Component[1].Value = adKijunSen; Component[2] = new IndicatorComp(); Component[2].CompName = "middle line"; Component[2].DataType = IndComponentType.IndicatorValue; Component[2].ChartType = IndChartType.Line; Component[2].ChartColor = Color.Green; Component[2].FirstBar = iFirstBar; Component[2].Value = adChikouSpan; Component[3] = new IndicatorComp(); Component[3].CompName = "Priority line"; Component[3].DataType = IndComponentType.IndicatorValue; Component[3].ChartType = IndChartType.CloudUp; Component[3].ChartColor = Color.SandyBrown; Component[3].FirstBar = iFirstBar; Component[3].Value = adSenkouSpanA; Component[4] = new IndicatorComp(); Component[4].CompName = "Overdue line"; Component[4].DataType = IndComponentType.IndicatorValue; Component[4].ChartType = IndChartType.CloudDown; Component[4].ChartColor = Color.Thistle; Component[4].FirstBar = iFirstBar; Component[4].Value = adSenkouSpanB; Component[5] = new IndicatorComp(); Component[5].FirstBar = iFirstBar; Component[5].Value = new double[Bars]; Component[5].DataType = IndComponentType.Other; if (slotType == SlotTypes.OpenFilter) { Component[5].CompName = "Is long entry allowed"; Component[5].DataType = IndComponentType.AllowOpenLong; Component[6] = new IndicatorComp(); Component[6].FirstBar = iFirstBar; Component[6].Value = new double[Bars]; Component[6].CompName = "Is short entry allowed"; Component[6].DataType = IndComponentType.AllowOpenShort; } /// start WTF modfication 3 version 4 // use wtf values here, then do expansion after this if clause to cover these IndicatorCrosses cases and the OscillatorLogic cases // back up Bars value, reset to hBars, for performance improvement in indicator logic function int mtfBars = Data.Bars; Data.Bars = hBars; /// end WTF modfication 3 version 4 switch (IndParam.ListParam[0].Text) { case "Enter the market at the Middle line": Component[5].CompName = "Middle line entry price"; Component[5].DataType = IndComponentType.OpenPrice; Component[5].ChartType = IndChartType.NoChart; for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadTenkanSen[iBar - iPrvs]; } break; case "Enter the market at the Stop-order line": Component[5].CompName = "Stop-order line entry price"; Component[5].DataType = IndComponentType.OpenPrice; Component[5].ChartType = IndChartType.NoChart; for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadKijunSen[iBar - iPrvs]; } break; case "Exit the market at the Middle line": Component[5].CompName = "Middle line exit price"; Component[5].DataType = IndComponentType.ClosePrice; Component[5].ChartType = IndChartType.NoChart; for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadTenkanSen[iBar - iPrvs]; } break; case "Exit the market at the Stop-order line": Component[5].CompName = "Stop-order line exit price"; Component[5].DataType = IndComponentType.ClosePrice; Component[5].ChartType = IndChartType.NoChart; for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadKijunSen[iBar - iPrvs]; } break; case "The Middle line rises": for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadTenkanSen[iBar - iPrvs] > hadTenkanSen[iBar - iPrvs - 1] + Sigma() ? 1 : 0; Component[6].Value[iBar] = hadTenkanSen[iBar - iPrvs] < hadTenkanSen[iBar - iPrvs - 1] - Sigma() ? 1 : 0; } break; case "The Middle line falls": for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadTenkanSen[iBar - iPrvs] < hadTenkanSen[iBar - iPrvs - 1] + Sigma() ? 1 : 0; Component[6].Value[iBar] = hadTenkanSen[iBar - iPrvs] > hadTenkanSen[iBar - iPrvs - 1] - Sigma() ? 1 : 0; } break; case "The Stop-order line rises": for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadKijunSen[iBar - iPrvs] > hadKijunSen[iBar - iPrvs - 1] + Sigma() ? 1 : 0; Component[6].Value[iBar] = hadKijunSen[iBar - iPrvs] < hadKijunSen[iBar - iPrvs - 1] - Sigma() ? 1 : 0; } break; case "The Stop-order line falls": for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadKijunSen[iBar - iPrvs] < hadKijunSen[iBar - iPrvs - 1] + Sigma() ? 1 : 0; Component[6].Value[iBar] = hadKijunSen[iBar - iPrvs] > hadKijunSen[iBar - iPrvs - 1] - Sigma() ? 1 : 0; } break; case "The Middle line is higher than the Stop-order line": IndicatorIsHigherThanAnotherIndicatorLogic(iFirstBar, iPrvs, hadTenkanSen, hadKijunSen, ref Component[5], ref Component[6]); break; case "The Middle line is lower than the Stop-order line": IndicatorIsLowerThanAnotherIndicatorLogic(iFirstBar, iPrvs, hadTenkanSen, hadKijunSen, ref Component[5], ref Component[6]); break; case "The Middle line crosses the Stop-order line upward": IndicatorCrossesAnotherIndicatorUpwardLogic(iFirstBar, iPrvs, hadTenkanSen, hadKijunSen, ref Component[5], ref Component[6]); break; case "The Middle line crosses the Stop-order line downward": IndicatorCrossesAnotherIndicatorDownwardLogic(iFirstBar, iPrvs, hadTenkanSen, hadKijunSen, ref Component[5], ref Component[6]); break; case "The bar opens above the Middle line": BarOpensAboveIndicatorLogic(iFirstBar, iPrvs, hadTenkanSen, ref Component[5], ref Component[6]); break; case "The bar opens below the Middle line": BarOpensBelowIndicatorLogic(iFirstBar, iPrvs, hadTenkanSen, ref Component[5], ref Component[6]); break; case "The bar opens above the Stop-order line": BarOpensAboveIndicatorLogic(iFirstBar, iPrvs, hadKijunSen, ref Component[5], ref Component[6]); break; case "The bar opens below the Stop-order line": BarOpensBelowIndicatorLogic(iFirstBar, iPrvs, hadKijunSen, ref Component[5], ref Component[6]); break; case "The Middle line is above the closing price": for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadChikouSpan[iBar - iPrvs] > hfClose[iBar - iPrvs] + Sigma() ? 1 : 0; Component[6].Value[iBar] = hadChikouSpan[iBar - iPrvs] < hfClose[iBar - iPrvs] - Sigma() ? 1 : 0; } break; case "The Middle line is below the closing price": for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadChikouSpan[iBar - iPrvs] < hfClose[iBar - iPrvs] + Sigma() ? 1 : 0; Component[6].Value[iBar] = hadChikouSpan[iBar - iPrvs] > hfClose[iBar - iPrvs] - Sigma() ? 1 : 0; } break; case "The position opens above the Priority/Overdue line": for (int iBar = iFirstBar; iBar < Bars; iBar++) { Component[5].Value[iBar] = Math.Max(hadSenkouSpanA[iBar], hadSenkouSpanB[iBar]); Component[6].Value[iBar] = Math.Min(hadSenkouSpanA[iBar], hadSenkouSpanB[iBar]); } Component[5].PosPriceDependence = PositionPriceDependence.PriceBuyHigher; Component[5].DataType = IndComponentType.Other; Component[5].UsePreviousBar = iPrvs; Component[5].ShowInDynInfo = false; Component[6].PosPriceDependence = PositionPriceDependence.PriceSellLower; Component[6].DataType = IndComponentType.Other; Component[6].UsePreviousBar = iPrvs; Component[6].ShowInDynInfo = false; break; case "The position opens inside or above the Priority/Overdue line": for (int iBar = iFirstBar; iBar < Bars; iBar++) { Component[5].Value[iBar] = Math.Min(hadSenkouSpanA[iBar], hadSenkouSpanB[iBar]); Component[6].Value[iBar] = Math.Max(hadSenkouSpanA[iBar], hadSenkouSpanB[iBar]); } Component[5].PosPriceDependence = PositionPriceDependence.PriceBuyHigher; Component[5].DataType = IndComponentType.Other; Component[5].UsePreviousBar = iPrvs; Component[5].ShowInDynInfo = false; Component[6].PosPriceDependence = PositionPriceDependence.PriceSellLower; Component[6].DataType = IndComponentType.Other; Component[6].UsePreviousBar = iPrvs; Component[6].ShowInDynInfo = false; break; case "The Middle line is above the Priority/Overdue line": for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadTenkanSen[iBar - iPrvs] > Math.Max(hadSenkouSpanA[iBar - iPrvs], hadSenkouSpanB[iBar - iPrvs]) + Sigma() ? 1 : 0; Component[6].Value[iBar] = hadTenkanSen[iBar - iPrvs] < Math.Min(hadSenkouSpanA[iBar - iPrvs], hadSenkouSpanB[iBar - iPrvs]) - Sigma() ? 1 : 0; } break; case "The Middle line is below the Priority/Overdue line": for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadTenkanSen[iBar - iPrvs] < Math.Max(hadSenkouSpanA[iBar - iPrvs], hadSenkouSpanB[iBar - iPrvs]) + Sigma() ? 1 : 0; Component[6].Value[iBar] = hadTenkanSen[iBar - iPrvs] > Math.Min(hadSenkouSpanA[iBar - iPrvs], hadSenkouSpanB[iBar - iPrvs]) - Sigma() ? 1 : 0; } break; case "The Middle line is inside or above the Priority/Overdue line": for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadTenkanSen[iBar - iPrvs] > Math.Min(hadSenkouSpanA[iBar - iPrvs], hadSenkouSpanB[iBar - iPrvs]) + Sigma() ? 1 : 0; Component[6].Value[iBar] = hadTenkanSen[iBar - iPrvs] < Math.Max(hadSenkouSpanA[iBar - iPrvs], hadSenkouSpanB[iBar - iPrvs]) - Sigma() ? 1 : 0; } break; case "The Stop-order line is above the Priority/Overdue line": for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadKijunSen[iBar - iPrvs] > Math.Max(hadSenkouSpanA[iBar - iPrvs], hadSenkouSpanB[iBar - iPrvs]) + Sigma() ? 1 : 0; Component[6].Value[iBar] = hadKijunSen[iBar - iPrvs] < Math.Min(hadSenkouSpanA[iBar - iPrvs], hadSenkouSpanB[iBar - iPrvs]) - Sigma() ? 1 : 0; } break; case "The Stop-order line is below the Priority/Overdue line": for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadKijunSen[iBar - iPrvs] < Math.Max(hadSenkouSpanA[iBar - iPrvs], hadSenkouSpanB[iBar - iPrvs]) + Sigma() ? 1 : 0; Component[6].Value[iBar] = hadKijunSen[iBar - iPrvs] > Math.Min(hadSenkouSpanA[iBar - iPrvs], hadSenkouSpanB[iBar - iPrvs]) - Sigma() ? 1 : 0; } break; case "The Stop-order line is inside or above the Priority/Overdue line": for (int iBar = iFirstBar + iPrvs; iBar < Bars; iBar++) { Component[5].Value[iBar] = hadKijunSen[iBar - iPrvs] > Math.Min(hadSenkouSpanA[iBar - iPrvs], hadSenkouSpanB[iBar - iPrvs]) + Sigma() ? 1 : 0; Component[6].Value[iBar] = hadKijunSen[iBar - iPrvs] < Math.Max(hadSenkouSpanA[iBar - iPrvs], hadSenkouSpanB[iBar - iPrvs]) - Sigma() ? 1 : 0; } break; case "The Priority line is higher than the Overdue line": IndicatorIsHigherThanAnotherIndicatorLogic(iFirstBar, iPrvs, hadSenkouSpanA, hadSenkouSpanB, ref Component[5], ref Component[6]); break; case "The Priority line is lower than the Overdue line": IndicatorIsLowerThanAnotherIndicatorLogic(iFirstBar, iPrvs, hadSenkouSpanA, hadSenkouSpanB, ref Component[5], ref Component[6]); break; case "The Priority line crosses the Overdue line upward": IndicatorCrossesAnotherIndicatorUpwardLogic(iFirstBar, iPrvs, hadSenkouSpanA, hadSenkouSpanB, ref Component[5], ref Component[6]); break; case "The Priority line crosses the Overdue line downward": IndicatorCrossesAnotherIndicatorDownwardLogic(iFirstBar, iPrvs, hadSenkouSpanA, hadSenkouSpanB, ref Component[5], ref Component[6]); break; default: break; } /// start WTF modfication 4 version 4 // resest Bars to real value Data.Bars = mtfBars; // expand component array from wtf to current time frame double[] wtfCompValue = Component[5].Value; int err8 = CurrentTimeFrame(hIndex, hBars, ref wtfCompValue); if (err8 == 1) { return; } Component[5].Value = wtfCompValue; if (slotType == SlotTypes.OpenFilter) { wtfCompValue = Component[6].Value; int err9 = CurrentTimeFrame(hIndex, hBars, ref wtfCompValue); if (err9 == 1) { return; } Component[6].Value = wtfCompValue; } /// end WTF modfication 4 version 4 return; }
/// <summary> /// Calculates the indicator's components /// </summary> public override void Calculate(SlotTypes slotType) { // Reading the parameters int iPrvs = IndParam.CheckParam[0].Checked ? 1 : 0; int RepulsePeriod2 = (int)IndParam.NumParam[0].Value; int RepulsePeriod3 = (int)IndParam.NumParam[1].Value; int RepulsePeriod1 = (int)IndParam.NumParam[2].Value; double iLevel = IndParam.NumParam[3].Value; int iFirstBar = 1 + RepulsePeriod2 + RepulsePeriod3 + RepulsePeriod1; // Convert to Higher Time Frame --------------------------------------------- DataPeriods htfPeriod = DataPeriods.week; double[] hfOpen = new double[Bars]; double[] hfClose = new double[Bars]; double[] hfHigh = new double[Bars]; double[] hfLow = new double[Bars]; double[] hfVolume = new double[Bars]; double[] hfPrice = new double[Bars]; int[] hIndex = new int[Bars]; int iFrame; int hBars; switch (IndParam.ListParam[4].Index) { case 1: htfPeriod = DataPeriods.min5; break; case 2: htfPeriod = DataPeriods.min15; break; case 3: htfPeriod = DataPeriods.min30; break; case 4: htfPeriod = DataPeriods.hour1; break; case 5: htfPeriod = DataPeriods.hour4; break; case 6: htfPeriod = DataPeriods.day; break; case 7: htfPeriod = DataPeriods.week; break; } int err1 = HigherTimeFrame(Period, htfPeriod, out hIndex, out hBars, out iFrame, out hfHigh, out hfLow, out hfOpen, out hfClose, out hfVolume); //int err2 = HigherBasePrice(basePrice, hBars, hfHigh, hfLow, hfOpen, hfClose, out hfPrice); if (err1 == 1) { return; } //------------------------------------------------------------------------ double[] PosBuffer1 = new double[Bars]; double[] NegBuffer1 = new double[Bars]; double[] PosBuffer2 = new double[Bars]; double[] NegBuffer2 = new double[Bars]; double[] PosBuffer3 = new double[Bars]; double[] NegBuffer3 = new double[Bars]; double[] RepulseBuffer1 = new double[Bars]; double[] RepulseBuffer2 = new double[Bars]; double[] RepulseBuffer3 = new double[Bars]; double[] Long = new double[Bars]; double[] Short = new double[Bars]; // Calculation // Repulse1 for (int iBar = iFirstBar; iBar < hBars; iBar++) { double high1 = double.MinValue; double low1 = double.MaxValue; for (int i = 0; i <= RepulsePeriod1; i++) { if (high1 < hfHigh[iBar - i]) { high1 = hfHigh[iBar - i]; } if (low1 > hfLow[iBar - i]) { low1 = hfLow[iBar - i]; } } PosBuffer1[iBar] = ((((3 * hfClose[iBar]) - (2 * low1) - hfOpen[iBar]) / hfClose[iBar]) * 100); NegBuffer1[iBar] = (((hfOpen[iBar] + (2 * high1) - (3 * hfClose[iBar])) / hfClose[iBar]) * 100); } double[] forceHaussiere1 = MovingAverage(RepulsePeriod1 * 5, 0, MAMethod.Exponential, PosBuffer1); double[] forceBaissiere1 = MovingAverage(RepulsePeriod1 * 5, 0, MAMethod.Exponential, NegBuffer1); for (int iBar = 1; iBar < hBars; iBar++) { RepulseBuffer1[iBar] = forceHaussiere1[iBar] - forceBaissiere1[iBar]; } // Repulse2 for (int iBar = iFirstBar; iBar < hBars; iBar++) { double high2 = double.MinValue; double low2 = double.MaxValue; for (int i = 0; i <= RepulsePeriod2; i++) { if (high2 < hfHigh[iBar - i]) { high2 = hfHigh[iBar - i]; } if (low2 > hfLow[iBar - i]) { low2 = hfLow[iBar - i]; } } PosBuffer2[iBar] = ((((3 * hfClose[iBar]) - (2 * low2) - hfOpen[iBar - RepulsePeriod2]) / hfClose[iBar]) * 100); NegBuffer2[iBar] = (((hfOpen[iBar - RepulsePeriod2] + (2 * high2) - (3 * hfClose[iBar])) / hfClose[iBar]) * 100); } double[] forceHaussiere2 = MovingAverage(RepulsePeriod2 * 5, 0, MAMethod.Exponential, PosBuffer2); double[] forceBaissiere2 = MovingAverage(RepulsePeriod2 * 5, 0, MAMethod.Exponential, NegBuffer2); for (int iBar = 1; iBar < hBars; iBar++) { RepulseBuffer2[iBar] = forceHaussiere2[iBar] - forceBaissiere2[iBar]; } // Repulse3 for (int iBar = iFirstBar; iBar < hBars; iBar++) { double high3 = double.MinValue; double low3 = double.MaxValue; for (int i = 0; i <= RepulsePeriod3; i++) { if (high3 < hfHigh[iBar - i]) { high3 = hfHigh[iBar - i]; } if (low3 > hfLow[iBar - i]) { low3 = hfLow[iBar - i]; } } PosBuffer3[iBar] = ((((3 * hfClose[iBar]) - (2 * low3) - hfOpen[iBar - RepulsePeriod3]) / hfClose[iBar]) * 100); NegBuffer3[iBar] = (((hfOpen[iBar - RepulsePeriod3] + (2 * high3) - (3 * hfClose[iBar])) / hfClose[iBar]) * 100); } double[] forceHaussiere3 = MovingAverage(RepulsePeriod3 * 5, 0, MAMethod.Exponential, PosBuffer3); double[] forceBaissiere3 = MovingAverage(RepulsePeriod3 * 5, 0, MAMethod.Exponential, NegBuffer3); for (int iBar = 2; iBar < hBars; iBar++) { RepulseBuffer3[iBar] = forceHaussiere3[iBar] - forceBaissiere3[iBar]; } // Convert to Current Time Frame ---------------------------------------------- /// start WTF modfication 2 version 4 // copy of wider time frame array of values double[] hRepulseBuffer1 = new double[Bars]; double[] hRepulseBuffer2 = new double[Bars]; double[] hRepulseBuffer3 = new double[Bars]; RepulseBuffer1.CopyTo(hRepulseBuffer1, 0); RepulseBuffer2.CopyTo(hRepulseBuffer2, 0); RepulseBuffer3.CopyTo(hRepulseBuffer3, 0); int err3 = CurrentTimeFrame(hIndex, hBars, ref RepulseBuffer1); int err4 = CurrentTimeFrame(hIndex, hBars, ref RepulseBuffer2); int err5 = CurrentTimeFrame(hIndex, hBars, ref RepulseBuffer3); // if any error, return out of calculation and indicator fails silently if (err3 == 1 || err4 == 1 || err5 == 1) { return; } /// end WTF modfication 2 version 4 //----------------------------------------------------------------------------- // Saving the components Component = new IndicatorComp[5]; Component[0] = new IndicatorComp(); Component[0].CompName = "Repulse1"; Component[0].DataType = IndComponentType.IndicatorValue; Component[0].ChartType = IndChartType.Line; Component[0].ChartColor = Color.Brown; Component[0].FirstBar = iFirstBar; Component[0].Value = RepulseBuffer1; Component[1] = new IndicatorComp(); Component[1].CompName = "Repulse3"; Component[1].DataType = IndComponentType.IndicatorValue; Component[1].ChartType = IndChartType.Line; Component[1].ChartColor = Color.Yellow; Component[1].FirstBar = iFirstBar; Component[1].Value = RepulseBuffer3; Component[2] = new IndicatorComp(); Component[2].CompName = "Repulse2"; Component[2].DataType = IndComponentType.IndicatorValue; Component[2].ChartType = IndChartType.Line; Component[2].ChartColor = Color.Blue; Component[2].FirstBar = iFirstBar; Component[2].Value = RepulseBuffer2; Component[3] = new IndicatorComp(); Component[3].ChartType = IndChartType.NoChart; Component[3].FirstBar = iFirstBar; Component[3].Value = new double[Bars]; Component[4] = new IndicatorComp(); Component[4].ChartType = IndChartType.NoChart; Component[4].FirstBar = iFirstBar; Component[4].Value = new double[Bars]; // Sets the Component's type if (slotType == SlotTypes.OpenFilter) { Component[3].DataType = IndComponentType.AllowOpenLong; Component[3].CompName = "Is long entry allowed"; Component[4].DataType = IndComponentType.AllowOpenShort; Component[4].CompName = "Is short entry allowed"; } else if (slotType == SlotTypes.CloseFilter) { Component[3].DataType = IndComponentType.ForceCloseLong; Component[3].CompName = "Close out long position"; Component[4].DataType = IndComponentType.ForceCloseShort; Component[4].CompName = "Close out short position"; } // Calculation of the logic IndicatorLogic indLogic = IndicatorLogic.It_does_not_act_as_a_filter; /// start WTF modfication 3 version 4 // use wtf values here, then do expansion after this if clause to cover these IndicatorCrosses cases and the OscillatorLogic cases // back up Bars value, reset to hBars, for performance improvement in indicator logic function int mtfBars = Data.Bars; Data.Bars = hBars; // replace very small values with 0 for performance improvement; don't know why but works for (int ctr = 0; ctr < hRepulseBuffer1.Length; ctr++) { hRepulseBuffer1[ctr] = (hRepulseBuffer1[ctr] < .000000001 && hRepulseBuffer1[ctr] > -.000000001) ? 0 : hRepulseBuffer1[ctr]; hRepulseBuffer2[ctr] = (hRepulseBuffer2[ctr] < .000000001 && hRepulseBuffer2[ctr] > -.000000001) ? 0 : hRepulseBuffer2[ctr]; hRepulseBuffer3[ctr] = (hRepulseBuffer3[ctr] < .000000001 && hRepulseBuffer3[ctr] > -.000000001) ? 0 : hRepulseBuffer3[ctr]; } if (IndParam.ListParam[0].Text == "The Repulse1 crosses the Repulse2 upward") { SpecialValues = new double[1] { 50 }; IndicatorCrossesAnotherIndicatorUpwardLogic(iFirstBar, iPrvs, hRepulseBuffer1, hRepulseBuffer2, ref Component[3], ref Component[4]); } else if (IndParam.ListParam[0].Text == "The Repulse1 crosses the Repulse2 downward") { SpecialValues = new double[1] { 50 }; IndicatorCrossesAnotherIndicatorDownwardLogic(iFirstBar, iPrvs, hRepulseBuffer1, hRepulseBuffer2, ref Component[3], ref Component[4]); } else if (IndParam.ListParam[0].Text == "The Repulse1 is higher than the Repulse2") { SpecialValues = new double[1] { 50 }; IndicatorIsHigherThanAnotherIndicatorLogic(iFirstBar, iPrvs, hRepulseBuffer1, hRepulseBuffer2, ref Component[3], ref Component[4]); } else if (IndParam.ListParam[0].Text == "The Repulse1 is lower than the Repulse2") { SpecialValues = new double[1] { 50 }; IndicatorIsLowerThanAnotherIndicatorLogic(iFirstBar, iPrvs, hRepulseBuffer1, hRepulseBuffer2, ref Component[3], ref Component[4]); } else { switch (IndParam.ListParam[0].Text) { case "The Repulse2 rises": indLogic = IndicatorLogic.The_indicator_rises; SpecialValues = new double[1] { 50 }; break; case "The Repulse2 falls": indLogic = IndicatorLogic.The_indicator_falls; SpecialValues = new double[1] { 50 }; break; case "The Repulse2 is higher than the Level line": indLogic = IndicatorLogic.The_indicator_is_higher_than_the_level_line; SpecialValues = new double[2] { iLevel, -iLevel }; break; case "The Repulse2 is lower than the Level line": indLogic = IndicatorLogic.The_indicator_is_lower_than_the_level_line; SpecialValues = new double[2] { iLevel, -iLevel }; break; case "The Repulse2 crosses the Level line upward": indLogic = IndicatorLogic.The_indicator_crosses_the_level_line_upward; SpecialValues = new double[2] { iLevel, -iLevel }; break; case "The Repulse2 crosses the Level line downward": indLogic = IndicatorLogic.The_indicator_crosses_the_level_line_downward; SpecialValues = new double[2] { iLevel, -iLevel }; break; case "The Repulse2 changes its direction upward": indLogic = IndicatorLogic.The_indicator_changes_its_direction_upward; SpecialValues = new double[1] { 50 }; break; case "The Repulse2 changes its direction downward": indLogic = IndicatorLogic.The_indicator_changes_its_direction_downward; SpecialValues = new double[1] { 50 }; break; default: break; } OscillatorLogic(iFirstBar, iPrvs, hRepulseBuffer2, iLevel, -iLevel, ref Component[3], ref Component[4], indLogic); } // resest Bars to real value Data.Bars = mtfBars; // expand component array from wtf to current time frame double[] wtfCompValue = Component[3].Value; int err6 = CurrentTimeFrame(hIndex, hBars, ref wtfCompValue); if (err6 == 1) { return; } Component[3].Value = wtfCompValue; wtfCompValue = Component[4].Value; int err7 = CurrentTimeFrame(hIndex, hBars, ref wtfCompValue); if (err7 == 1) { return; } Component[4].Value = wtfCompValue; /// end WTF modfication 3 version 4 return; }
/// <summary> /// Paints the chart /// </summary> protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; // Caption bar Data.GradientPaint(g, _rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); g.DrawString(_chartTitle, Font, new SolidBrush(LayoutColors.ColorCaptionText), _rectfCaption, _stringFormatCaption); // Border g.DrawLine(_penBorder, 1, _captionHeight, 1, ClientSize.Height); g.DrawLine(_penBorder, ClientSize.Width - Border + 1, _captionHeight, ClientSize.Width - Border + 1, ClientSize.Height); g.DrawLine(_penBorder, 0, ClientSize.Height - Border + 1, ClientSize.Width, ClientSize.Height - Border + 1); // Paints the background by gradient var rectChartField = new RectangleF(Border, _captionHeight, ClientSize.Width - 2 * Border, ClientSize.Height - _captionHeight - Border); Data.GradientPaint(g, rectChartField, LayoutColors.ColorChartBack, LayoutColors.DepthControl); if (_isNotPaint) { return; } // Grid and Price labels for (int labelPrice = _data.Minimum; labelPrice <= _data.Minimum + _countLabels * _labelStep; labelPrice += _labelStep) { var labelY = (int)(_yBottom - (labelPrice - _data.Minimum) * _yScale); g.DrawString(labelPrice.ToString(CultureInfo.InvariantCulture), Font, _brushFore, _xRight, labelY - Font.Height / 2 - 1); g.DrawLine(_penGrid, _xLeft, labelY, _xRight, labelY); } // Price close if (_showPriceLine) { g.DrawLines(new Pen(LayoutColors.ColorChartGrid), _closePricePoints); } // Equity line g.DrawLines(new Pen(LayoutColors.ColorChartEquityLine), _equityPoints); // Draw Long and Short balance if (Configs.AdditionalStatistics) { g.DrawLines(new Pen(Color.Red), _shortBalancePoints); g.DrawLines(new Pen(Color.Green), _longBalancePoints); } // Out of Sample if (IsOOS && OOSBar > 0) { g.DrawLine(new Pen(LayoutColors.ColorChartFore), _xOOSBar, _yTop, _xOOSBar, _yBottom); Brush brushOOS = new Pen(LayoutColors.ColorChartFore).Brush; g.DrawString("OOS", Font, brushOOS, _xOOSBar, _yBottom - Font.Height); float widthOOSBarDate = g.MeasureString(_data.DataTimeBarOOS.ToShortDateString(), Font).Width; g.DrawString(_data.DataTimeBarOOS.ToShortDateString(), Font, brushOOS, _xOOSBar - widthOOSBarDate, _yBottom - Font.Height); } // Draw Balance Line if (_data.MarginCallBar > 0) // In case of Margin Call { // Draw balance line up to Margin Call var balancePoints = new PointF[_data.MarginCallBar - _data.FirstBar]; for (int i = 0; i < balancePoints.Length; i++) { balancePoints[i] = _balancePoints[i]; } if (balancePoints.Length > 1) { g.DrawLines(new Pen(LayoutColors.ColorChartBalanceLine), balancePoints); } // Draw balance line after Margin Call var redBalancePoints = new PointF[_data.Bars - _data.MarginCallBar]; for (int i = 0; i < redBalancePoints.Length; i++) { redBalancePoints[i] = _balancePoints[i + _data.MarginCallBar - _data.FirstBar]; } g.DrawLines(new Pen(LayoutColors.ColorSignalRed), redBalancePoints); // Margin Call line g.DrawLine(new Pen(LayoutColors.ColorChartCross), _xMarginCallBar, _yTop, _xMarginCallBar, _yBottom); // Margin Call label float widthMarginCallLabel = g.MeasureString(Language.T("Margin Call"), Font).Width; if (_xMarginCallBar < _xRight - widthMarginCallLabel) { g.DrawString(Language.T("Margin Call"), Font, _brushFore, _xMarginCallBar, _yTop); } else if (_xMarginCallBar > Space + widthMarginCallLabel) { g.DrawString(Language.T("Margin Call"), Font, _brushFore, _xMarginCallBar - widthMarginCallLabel, _yTop); } else { g.DrawString("MC", Font, _brushFore, _xMarginCallBar, _yTop); } } else { // Draw the balance line g.DrawLines(new Pen(LayoutColors.ColorChartBalanceLine), _balancePoints); } // Scanning note var fontNote = new Font(Font.FontFamily, Font.Size - 1); if (Data.Period != DataPeriods.min1 && Configs.Autoscan && !Data.IsIntrabarData) { g.DrawString(Language.T("Load intrabar data"), fontNote, Brushes.Red, _xLeft, _captionHeight - 2); } else if (Data.Period != DataPeriods.min1 && _isScanPerformed) { g.DrawString(Language.T("Scanned") + _data.ModellingQuolity, fontNote, Brushes.LimeGreen, _xLeft, _captionHeight - 2); } // Scanned bars if (_isScanPerformed && !_isHideScanningLine && (Data.IntraBars != null && Data.IsIntrabarData || Data.Period == DataPeriods.min1 && Data.IsTickData && Configs.UseTickData)) { DataPeriods dataPeriod = Data.Period; Color color = Data.PeriodColor[Data.Period]; int fromBar = _data.FirstBar; for (int bar = _data.FirstBar; bar < _data.Bars; bar++) { if (Data.IntraBarsPeriods[bar] == dataPeriod && bar != _data.Bars - 1) { continue; } int xStart = (int)((fromBar - _data.FirstBar) * _xScale) + _xLeft; int xEnd = (int)((bar - _data.FirstBar) * _xScale) + _xLeft; fromBar = bar; dataPeriod = Data.IntraBarsPeriods[bar]; Data.GradientPaint(g, new RectangleF(xStart, _yBottom + 4, xEnd - xStart + 2, 5), color, 60); color = Data.PeriodColor[Data.IntraBarsPeriods[bar]]; } // Tick Data if (Data.IsTickData && Configs.UseTickData) { int firstBarWithTicks = -1; int lastBarWithTicks = -1; for (int b = 0; b < _data.Bars; b++) { if (firstBarWithTicks == -1 && Data.TickData[b] != null) { firstBarWithTicks = b; } if (Data.TickData[b] != null) { lastBarWithTicks = b; } } int xStart = (int)((firstBarWithTicks - _data.FirstBar) * _xScale) + _xLeft; int xEnd = (int)((lastBarWithTicks - _data.FirstBar) * _xScale) + _xLeft; Data.GradientPaint(g, new RectangleF(xStart, _yBottom + 4, xEnd - xStart + 2, 5), color, 60); var rectf = new RectangleF(xStart, _yBottom + 4, xEnd - xStart + 2, 5); Data.GradientPaint(g, rectf, Data.PeriodColor[DataPeriods.min1], 60); rectf = new RectangleF(xStart, _yBottom + 6, xEnd - xStart + 2, 1); Data.GradientPaint(g, rectf, Data.PeriodColor[DataPeriods.day], 60); } // Vertical coordinate axes g.DrawLine(new Pen(LayoutColors.ColorChartFore), _xLeft - 1, _yBottom, _xLeft - 1, _yBottom + 9); } // Coordinate axes g.DrawLine(new Pen(LayoutColors.ColorChartFore), _xLeft - 1, _yTop - Space, _xLeft - 1, _yBottom + 1); g.DrawLine(new Pen(LayoutColors.ColorChartFore), _xLeft - 1, _yBottom + 1, _xRight, _yBottom + 1); // Balance level g.DrawLine(new Pen(LayoutColors.ColorChartCross), _xLeft, _yBalance, _xRight - Space + 1, _yBalance); // Balance label var labelSize = new Size(_labelWidth + Space, Font.Height + 2); var labelPoint = new Point(_xRight - Space + 2, (int)(_yBalance - Font.Height / 2.0 - 1)); var labelRect = new Rectangle(labelPoint, labelSize); g.FillRectangle(new SolidBrush(LayoutColors.ColorLabelBack), labelRect); g.DrawRectangle(new Pen(LayoutColors.ColorChartCross), labelRect); g.DrawString((Math.Round(_data.NetBalance)).ToString(CultureInfo.InvariantCulture), Font, new SolidBrush(LayoutColors.ColorLabelText), labelRect, _stringFormatCaption); }
/// <summary> /// Saves bar data to a CSV file. /// </summary> private void SaveBars(List<Bar> barList, DataPeriods period ) { var sb = new StringBuilder(); foreach (Bar bar in barList) sb.AppendLine( String.Format("{0:D4}-{1:D2}-{2:D2}\t{3:D2}:{4:D2}\t{5}\t{6}\t{7}\t{8}\t{9}", bar.Time.Year, bar.Time.Month, bar.Time.Day, bar.Time.Hour, bar.Time.Minute, bar.Open, bar.High, bar.Low, bar.Close, bar.Volume)); string fileName = TxbSymbol.Text + (int)period + ".csv"; string path = Path.Combine(_outFolder, fileName); try { var sw = new StreamWriter(path); sw.Write(sb.ToString()); sw.Close(); SetInfoText(Language.T("Saved") + " " + Data.DataPeriodToString(period) + " " + Language.T("bars") + " - " + barList.Count + Environment.NewLine); } catch (Exception exc) { MessageBox.Show(exc.Message); } }
/// <summary> /// Loads the Intrabar data. /// </summary> private int LoadIntrabarData(DataPeriods period) { var instrument = new Instrument(Data.InstrProperties.Clone(), (int)period) { DataDir = Data.OfflineDataDir, MaxBars = Configs.MaxIntraBars }; // Loads the data int loadingResult = instrument.LoadData(); int loadedIntrabars = instrument.Bars; if (loadingResult == 0 && loadedIntrabars > 0) { if (Data.Period != DataPeriods.week) { if (instrument.DaysOff > 5) { _warningMessage += Environment.NewLine + Language.T("Data for:") + " " + Data.Symbol + " " + Data.DataPeriodToString(period) + " - " + Language.T("Maximum days off:") + " " + instrument.DaysOff; } if (Data.Update - instrument.Update > new TimeSpan(24, 0, 0)) { _warningMessage += Environment.NewLine + Language.T("Data for:") + " " + Data.Symbol + " " + Data.DataPeriodToString(period) + " - " + Language.T("Updated on:") + " " + instrument.Update.ToString(CultureInfo.InvariantCulture); } } int startBigBar; for (startBigBar = 0; startBigBar < Data.Bars; startBigBar++) { if (Data.Time[startBigBar] >= instrument.Time(0)) { break; } } int stopBigBar; for (stopBigBar = startBigBar; stopBigBar < Data.Bars; stopBigBar++) { if (Data.IntraBarsPeriods[stopBigBar] != Data.Period) { break; } } // Seek for a place to put the intrabars. int lastIntraBar = 0; for (int bar = startBigBar; bar < stopBigBar; bar++) { Data.IntraBarData[bar] = new Bar[(int)Data.Period / (int)period]; DateTime endTime = Data.Time[bar] + new TimeSpan(0, (int)Data.Period, 0); int indexBar = 0; for (int intrabar = lastIntraBar; intrabar < loadedIntrabars && instrument.Time(intrabar) < endTime; intrabar++) { if (instrument.Time(intrabar) >= Data.Time[bar]) { Data.IntraBarData[bar][indexBar].Time = instrument.Time(intrabar); Data.IntraBarData[bar][indexBar].Open = instrument.Open(intrabar); Data.IntraBarData[bar][indexBar].High = instrument.High(intrabar); Data.IntraBarData[bar][indexBar].Low = instrument.Low(intrabar); Data.IntraBarData[bar][indexBar].Close = instrument.Close(intrabar); Data.IntraBarsPeriods[bar] = period; Data.IntraBarBars[bar]++; indexBar++; lastIntraBar = intrabar; } } } } return(loadedIntrabars); }
/// <summary> /// Starts the trade. /// </summary> private void StartTrade() { _isTrading = true; // Resets trade global variables. InitTrade(); Data.SetStartTradingTime(); string message = Data.Symbol + " " + Data.PeriodMTStr + " " + Language.T("Automatic trade started."); var msg = new JournalMessage(JournalIcons.StartTrading, DateTime.Now, message); AppendJournalMessage(msg); Log(message); _symbolReconnect = Data.Symbol; _periodReconnect = Data.Period; _accountReconnect = Data.AccountNumber; _barOpenTimeForLastCloseEvent = Data.Time[Data.Bars - 1]; SetTradeStrip(); }
/// <summary> /// Saves the strategy in XML format. /// </summary> /// <param name="sFileName">The full file name.</param> /// <returns>0 - the saving is successfully; -1 - error.</returns> public int Save(string fileName) { strategyName = Path.GetFileNameWithoutExtension(fileName); symbol = Data.Symbol; period = Data.Period; // Create the XmlDocument. Strategy_XML strategyXML = new Strategy_XML(); XmlDocument xmlDocStrategy = strategyXML.CreateStrategyXmlDoc(this); try { xmlDocStrategy.Save(fileName); // Save the document to a file. } catch (Exception e) { System.Windows.Forms.MessageBox.Show(e.Message); return 1; } return 0; }
protected override void TsbtTradingClick(object sender, EventArgs e) { if (_isTrading) { StopTrade(); _symbolReconnect = ""; _periodReconnect = DataPeriods.week; _accountReconnect = 0; } else { StartTrade(); } }
/// <summary> /// Loads the Intrabar data. /// </summary> int LoadIntrabarData(DataPeriods period) { Instrument instrument = new Instrument(Data.InstrProperties.Clone(), (int)period); instrument.DataDir = Data.OfflineDataDir; instrument.FormatDate = DateFormat.Unknown; instrument.MaxBars = Configs.MAX_INTRA_BARS; // Loads the data int loadingResult = instrument.LoadData(); int loadedIntrabars = instrument.Bars; if (loadingResult == 0 && loadedIntrabars > 0) { if (Data.Period != DataPeriods.week) { if (instrument.DaysOff > 5) { warningMessage += Environment.NewLine + Language.T("Data for:") + " " + Data.Symbol + " " + Data.DataPeriodToString(period) + " - " + Language.T("Maximum days off:") + " " + instrument.DaysOff; } if (Data.Update - instrument.Update > new TimeSpan(24, 0, 0)) { warningMessage += Environment.NewLine + Language.T("Data for:") + " " + Data.Symbol + " " + Data.DataPeriodToString(period) + " - " + Language.T("Updated on:") + " " + instrument.Update.ToString(); } } int iStartBigBar = 0; for (iStartBigBar = 0; iStartBigBar < Data.Bars; iStartBigBar++) { if (Data.Time[iStartBigBar] >= instrument.Time(0)) { break; } } int iStopBigBar = 0; for (iStopBigBar = iStartBigBar; iStopBigBar < Data.Bars; iStopBigBar++) { if (Data.IntraBarsPeriods[iStopBigBar] != Data.Period) { break; } } // Seek for the place int iReachedBar = 0; for (int bar = iStartBigBar; bar < iStopBigBar; bar++) { Data.IntraBarData[bar] = new Bar[(int)Data.Period / (int)period]; DateTime endTime = Data.Time[bar] + new TimeSpan(0, (int)Data.Period, 0); int iCurrentBar = 0; for (int intrabar = iReachedBar; intrabar < loadedIntrabars && instrument.Time(intrabar) < endTime; intrabar++) { if (instrument.Time(intrabar) >= Data.Time[bar]) { Data.IntraBarData[bar][iCurrentBar].Time = instrument.Time(intrabar); Data.IntraBarData[bar][iCurrentBar].Open = instrument.Open(intrabar); Data.IntraBarData[bar][iCurrentBar].High = instrument.High(intrabar); Data.IntraBarData[bar][iCurrentBar].Low = instrument.Low(intrabar); Data.IntraBarData[bar][iCurrentBar].Close = instrument.Close(intrabar); Data.IntraBarsPeriods[bar] = period; Data.IntraBarBars[bar]++; iCurrentBar++; iReachedBar = intrabar; } } } } return(loadedIntrabars); }
/// <summary> /// Check if the incoming data is from the same chart. /// </summary> private bool IsChartChangeged(string symbol, DataPeriods period) { if (!Data.IsConnected) return true; if (Data.Symbol != symbol || Data.Period != period) return true; return false; }
/// <summary> /// Sets the market according to the strategy /// </summary> private void SetMarket(string symbol, DataPeriods dataPeriod) { Data.InstrProperties = Instruments.InstrumentList[symbol].Clone(); Data.Period = dataPeriod; IsDiscardSelectedIndexChange = true; ComboBoxSymbol.SelectedIndex = ComboBoxSymbol.Items.IndexOf(symbol); switch (dataPeriod) { case DataPeriods.min1: ComboBoxPeriod.SelectedIndex = 0; break; case DataPeriods.min5: ComboBoxPeriod.SelectedIndex = 1; break; case DataPeriods.min15: ComboBoxPeriod.SelectedIndex = 2; break; case DataPeriods.min30: ComboBoxPeriod.SelectedIndex = 3; break; case DataPeriods.hour1: ComboBoxPeriod.SelectedIndex = 4; break; case DataPeriods.hour4: ComboBoxPeriod.SelectedIndex = 5; break; case DataPeriods.day: ComboBoxPeriod.SelectedIndex = 6; break; case DataPeriods.week: ComboBoxPeriod.SelectedIndex = 7; break; } IsDiscardSelectedIndexChange = false; }
/// <summary> /// Calculates the indicator's components /// </summary> public override void Calculate(SlotTypes slotType) { // Reading the parameters MAMethod maMethod = (MAMethod )IndParam.ListParam[1].Index; BasePrice basePrice = (BasePrice)IndParam.ListParam[2].Index; int iPeriod = (int)IndParam.NumParam[0].Value; int iShift = (int)IndParam.NumParam[1].Value; int iPrvs = IndParam.CheckParam[0].Checked ? 1 : 0; // Convert to Higher Time Frame --------------------------------------------- DataPeriods htfPeriod = DataPeriods.week; double[] hfOpen = new double[Bars]; double[] hfClose = new double[Bars]; double[] hfHigh = new double[Bars]; double[] hfLow = new double[Bars]; double[] hfVolume = new double[Bars]; double[] hfPrice = new double[Bars]; int[] hIndex = new int[Bars]; int iFrame; int hBars; switch (IndParam.ListParam[4].Index) { case 0: htfPeriod = DataPeriods.hour1; break; case 1: htfPeriod = DataPeriods.min5; break; case 2: htfPeriod = DataPeriods.min15; break; case 3: htfPeriod = DataPeriods.min30; break; case 4: htfPeriod = DataPeriods.hour1; break; case 5: htfPeriod = DataPeriods.hour4; break; case 6: htfPeriod = DataPeriods.day; break; case 7: htfPeriod = DataPeriods.week; break; } int err1 = HigherTimeFrame(Period, htfPeriod, out hIndex, out hBars, out iFrame, out hfHigh, out hfLow, out hfOpen, out hfClose, out hfVolume); int err2 = HigherBasePrice(basePrice, hBars, hfHigh, hfLow, hfOpen, hfClose, out hfPrice); //------------------------------------------------------------------------ // TimeExecution if (basePrice == BasePrice.Open && iPeriod == 1 && iShift == 0) { IndParam.ExecutionTime = ExecutionTime.AtBarOpening; } // Calculation double[] adMA = MovingAverage(iPeriod, iShift, maMethod, hfPrice); // v3 -- manually shift so Position entry type logics use previous WTF value, fix bug of not using previous value if (IndParam.ListParam[0].Text == "The position opens above the Moving Average" || IndParam.ListParam[0].Text == "The position opens below the Moving Average") { adMA = MovingAverage(iPeriod, iShift + 1, maMethod, hfPrice); } else { adMA = MovingAverage(iPeriod, iShift, maMethod, hfPrice); } int iFirstBar = iPeriod + iShift + 1 + iPrvs; // Convert to Current Time Frame ---------------------------------------------- iPrvs = iPrvs * iFrame; iFirstBar = iFirstBar * iFrame; int err3 = (iFirstBar > 0.25 * Bars) ? 1 : 0; int err4 = CurrentTimeFrame(hIndex, hBars, ref adMA); // if any WTF conversion errors, return here to fail silently if (err1 == 1 || err2 == 1 || err3 == 1 || err4 == 1) { Component = new IndicatorComp[1]; Component[0] = new IndicatorComp(); Component[0].CompName = "MA Value"; Component[0].DataType = IndComponentType.IndicatorValue; Component[0].ChartType = IndChartType.Line; Component[0].FirstBar = (int)Bars / 2; Component[0].UsePreviousBar = 0; Component[0].Value = new double[Bars]; return; } //----------------------------------------------------------------------------- // Saving the components if (slotType == SlotTypes.Open || slotType == SlotTypes.Close) { Component = new IndicatorComp[2]; Component[1] = new IndicatorComp(); Component[1].FirstBar = iFirstBar; Component[1].Value = new double[Bars]; int hBar = 0; for (int iBar = 3 * iFrame; iBar < Bars; iBar++) { // Covers the cases when the price can pass through the MA without a signal /// start WTF modfication 3 beta 1 while (hIndex[hBar] <= iBar && hBar < hBars) { hBar++; } double dValue = adMA[hIndex[hBar - 2]]; // MA value from previous HTF bar double dValue1 = adMA[hIndex[hBar - 3]]; // MA value from HTF 2 bars previous /// end WTF modfication 3 beta 1 double dTempVal = dValue; if ((dValue1 > High[iBar - 1] && dValue < Low[iBar]) || // It jumps below the current bar (dValue1 <Low[iBar - 1] && dValue> High[iBar]) || // It jumps above the current bar (Close[iBar - 1] < dValue && dValue < Open[iBar]) || // Positive gap (Close[iBar - 1] > dValue && dValue > Open[iBar])) // Negative gap { dTempVal = Open[iBar]; } Component[1].Value[iBar] = dTempVal; } } else { Component = new IndicatorComp[3]; Component[1] = new IndicatorComp(); Component[1].ChartType = IndChartType.NoChart; Component[1].FirstBar = iFirstBar; Component[1].Value = new double[Bars]; Component[2] = new IndicatorComp(); Component[2].ChartType = IndChartType.NoChart; Component[2].FirstBar = iFirstBar; Component[2].Value = new double[Bars]; } Component[0] = new IndicatorComp(); Component[0].CompName = "MA Value"; Component[0].DataType = IndComponentType.IndicatorValue; Component[0].ChartType = IndChartType.Line; Component[0].ChartColor = Color.FromName(IndParam.ListParam[3].ItemList[IndParam.ListParam[3].Index]); Component[0].FirstBar = iFirstBar; Component[0].Value = adMA; if (slotType == SlotTypes.Open) { Component[1].CompName = "Position opening price"; Component[1].DataType = IndComponentType.OpenPrice; } else if (slotType == SlotTypes.OpenFilter) { Component[1].DataType = IndComponentType.AllowOpenLong; Component[1].CompName = "Is long entry allowed"; Component[2].DataType = IndComponentType.AllowOpenShort; Component[2].CompName = "Is short entry allowed"; } else if (slotType == SlotTypes.Close) { Component[1].CompName = "Position closing price"; Component[1].DataType = IndComponentType.ClosePrice; } else if (slotType == SlotTypes.CloseFilter) { Component[1].DataType = IndComponentType.ForceCloseLong; Component[1].CompName = "Close out long position"; Component[2].DataType = IndComponentType.ForceCloseShort; Component[2].CompName = "Close out short position"; } if (slotType == SlotTypes.OpenFilter || slotType == SlotTypes.CloseFilter) { switch (IndParam.ListParam[0].Text) { case "The Moving Average rises": IndicatorRisesLogic(iFirstBar, iPrvs, adMA, ref Component[1], ref Component[2]); break; case "The Moving Average falls": IndicatorFallsLogic(iFirstBar, iPrvs, adMA, ref Component[1], ref Component[2]); break; case "The bar opens above the Moving Average": BarOpensAboveIndicatorLogic(iFirstBar, iPrvs, adMA, ref Component[1], ref Component[2]); break; case "The bar opens below the Moving Average": BarOpensBelowIndicatorLogic(iFirstBar, iPrvs, adMA, ref Component[1], ref Component[2]); break; case "The bar opens above the Moving Average after opening below it": BarOpensAboveIndicatorAfterOpeningBelowLogic(iFirstBar, iPrvs, adMA, ref Component[1], ref Component[2]); break; case "The bar opens below the Moving Average after opening above it": BarOpensBelowIndicatorAfterOpeningAboveLogic(iFirstBar, iPrvs, adMA, ref Component[1], ref Component[2]); break; case "The position opens above the Moving Average": Component[0].PosPriceDependence = PositionPriceDependence.BuyHigherSellLower; Component[1].DataType = IndComponentType.Other; Component[1].ShowInDynInfo = false; Component[2].DataType = IndComponentType.Other; Component[2].ShowInDynInfo = false; break; case "The position opens below the Moving Average": Component[0].PosPriceDependence = PositionPriceDependence.BuyLowerSelHigher; Component[1].DataType = IndComponentType.Other; Component[1].ShowInDynInfo = false; Component[2].DataType = IndComponentType.Other; Component[2].ShowInDynInfo = false; break; case "The bar closes below the Moving Average": BarClosesBelowIndicatorLogic(iFirstBar, iPrvs, adMA, ref Component[1], ref Component[2]); break; case "The bar closes above the Moving Average": BarClosesAboveIndicatorLogic(iFirstBar, iPrvs, adMA, ref Component[1], ref Component[2]); break; case "Draw only, no entry or exit": Component[1].CompName = "Visual Only"; Component[1].DataType = IndComponentType.NotDefined; Component[2].CompName = "Visual Only"; Component[2].DataType = IndComponentType.NotDefined; break; default: break; } } return; }
/// <summary> /// Loads the data file /// </summary> /// <returns>0 - success</returns> public int LoadResourceData(string data, DataPeriods period) { var dataParser = new DataParser(); int respond = -1; int parsedBars = dataParser.Parse(data, (int) period); if (parsedBars > 0) { _aBar = dataParser.Bar.ToArray(); Bars = parsedBars; RefineData(); DataHorizon(); CheckMarketData(); SetDataStats(); Update = _aBar[Bars - 1].Time; respond = 0; } return respond; }
/// <summary> /// Sets the instrument's properties after connecting; /// </summary> bool UpdateDataFeedInfo(DateTime time, string symbol, DataPeriods period) { lock (lockerDataFeed) { Data.ResetBidAsk(); Data.ResetAccountStats(); Data.ResetPositionStats(); Data.ResetBarStats(); Data.ResetTicks(); // Reads market info from the chart MT4Bridge.MarketInfo marketInfo = bridge.GetMarketInfoAll(symbol); if (marketInfo == null) { if (JournalShowSystemMessages) { JournalMessage jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (MT4Bridge.PeriodType)(int) period + " " + Language.T("Cannot update market info.")); AppendJournalMessage(jmsgsys); } return(false); } // Sets instrument properties Data.Period = period; Data.InstrProperties.Symbol = symbol; Data.InstrProperties.LotSize = (int)marketInfo.ModeLotSize; Data.InstrProperties.MinLot = marketInfo.ModeMinLot; Data.InstrProperties.MaxLot = marketInfo.ModeMaxLot; Data.InstrProperties.LotStep = marketInfo.ModeLotStep; Data.InstrProperties.Digits = (int)marketInfo.ModeDigits; Data.InstrProperties.Spread = marketInfo.ModeSpread; Data.InstrProperties.SwapLong = marketInfo.ModeSwapLong; Data.InstrProperties.SwapShort = marketInfo.ModeSwapShort; Data.InstrProperties.TickValue = marketInfo.ModeTickValue; Data.InstrProperties.StopLevel = marketInfo.ModeStopLevel; Data.InstrProperties.MarginRequired = marketInfo.ModeMarginRequired; SetNumUpDownLots(marketInfo.ModeMinLot, marketInfo.ModeLotStep, marketInfo.ModeMaxLot); // Sets Market Info string[] values = new string[] { symbol, Data.DataPeriodToString(period), marketInfo.ModeLotSize.ToString(), marketInfo.ModePoint.ToString("F" + marketInfo.ModeDigits.ToString()), marketInfo.ModeSpread.ToString(), marketInfo.ModeSwapLong.ToString(), marketInfo.ModeSwapShort.ToString() }; UpdateStatusPageMarketInfo(values); MT4Bridge.Bars bars = bridge.GetBars(symbol, (MT4Bridge.PeriodType)(int) period); if (bars == null) { if (JournalShowSystemMessages) { Data.SoundError.Play(); JournalMessage jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (MT4Bridge.PeriodType)(int) period + " " + Language.T("Cannot receive bars!")); AppendJournalMessage(jmsgsys); } return(false); } if (bars.Count < MaxBarsCount((int)period)) { if (JournalShowSystemMessages) { Data.SoundError.Play(); JournalMessage jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, symbol + " " + (MT4Bridge.PeriodType)(int) period + " " + Language.T("Cannot receive enough bars!")); AppendJournalMessage(jmsg); } return(false); } if (JournalShowSystemMessages) { JournalMessage jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (MT4Bridge.PeriodType)(int) period + " " + Language.T("Market data updated, bars downloaded.")); AppendJournalMessage(jmsgsys); } // Account Information. MT4Bridge.AccountInfo account = bridge.GetAccountInfo(); if (account == null) { if (JournalShowSystemMessages) { Data.SoundError.Play(); JournalMessage jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, symbol + " " + (MT4Bridge.PeriodType)(int) period + " " + Language.T("Cannot receive account information!")); AppendJournalMessage(jmsg); } return(false); } if (JournalShowSystemMessages) { JournalMessage jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (MT4Bridge.PeriodType)(int) period + " " + Language.T("Account information received.")); AppendJournalMessage(jmsgsys); } Data.AccountName = account.Name; Data.IsDemoAccount = account.IsDemo; Data.AccountCurrency = account.Currency; Data.SetCurrentAccount(time, account.Balance, account.Equity, account.Profit, account.FreeMargin); UpdateBalanceChart(Data.BalanceData, Data.BalanceDataPoints); SetTradeStrip(); SetLblSymbolText(symbol); } return(true); }
/// <summary> /// Calculates the indicator's components /// </summary> public override void Calculate(SlotTypes slotType) { // Reading the parameters BasePrice basePrice = (BasePrice)IndParam.ListParam[1].Index; MAMethod fastMAMethod = (MAMethod )IndParam.ListParam[3].Index; MAMethod slowMAMethod = (MAMethod )IndParam.ListParam[4].Index; int iNFastMA = (int)IndParam.NumParam[0].Value; int iNSlowMA = (int)IndParam.NumParam[1].Value; int iSFastMA = (int)IndParam.NumParam[2].Value; int iSSlowMA = (int)IndParam.NumParam[3].Value; int iPrvs = IndParam.CheckParam[0].Checked ? 1 : 0; string[] saColors = new string[] { "Blue", "Black", "Red", "Green", "Yellow", "Orange" }; string sFastColor = saColors[(int)IndParam.NumParam[4].Value]; string sSlowColor = saColors[(int)IndParam.NumParam[5].Value]; // Convert to Higher Time Frame --------------------------------------------- DataPeriods htfPeriod = DataPeriods.week; double[] hfOpen = new double[Bars]; double[] hfClose = new double[Bars]; double[] hfHigh = new double[Bars]; double[] hfLow = new double[Bars]; double[] hfVolume = new double[Bars]; double[] hfPrice = new double[Bars]; int[] hIndex = new int[Bars]; int iFrame; int hBars; switch (IndParam.ListParam[2].Index) { case 1: htfPeriod = DataPeriods.min5; break; case 2: htfPeriod = DataPeriods.min15; break; case 3: htfPeriod = DataPeriods.min30; break; case 4: htfPeriod = DataPeriods.hour1; break; case 5: htfPeriod = DataPeriods.hour4; break; case 6: htfPeriod = DataPeriods.day; break; case 7: htfPeriod = DataPeriods.week; break; } int err1 = HigherTimeFrame(Period, htfPeriod, out hIndex, out hBars, out iFrame, out hfHigh, out hfLow, out hfOpen, out hfClose, out hfVolume); int err2 = HigherBasePrice(basePrice, hBars, hfHigh, hfLow, hfOpen, hfClose, out hfPrice); if (err1 == 1) { return; } //----------------------------------------------------------------------- // Calculation int iFirstBar = (int)Math.Max(iNFastMA + iSFastMA, iNSlowMA + iSSlowMA) + 2; double[] adMAFast = MovingAverage(iNFastMA, iSFastMA, fastMAMethod, hfPrice); double[] adMASlow = MovingAverage(iNSlowMA, iSSlowMA, slowMAMethod, hfPrice); double[] adMAOscillator = new double[Bars]; for (int iBar = iFirstBar; iBar < Bars; iBar++) { adMAOscillator[iBar] = adMAFast[iBar] - adMASlow[iBar]; } // Convert to Current Time Frame ---------------------------------------------- /// start WTF modfication 2 version 4 // do in 3 blocks for adMAFast, adMASlow, to draw on chart, and adMAOscillator for signals // copy of wider time frame array of values double[] hadMAFast = new double[Bars]; adMAFast.CopyTo(hadMAFast, 0); int err3 = CurrentTimeFrame(hIndex, hBars, ref adMAFast); // if any error, return out of calculation and indicator fails silently if (err3 == 1) { return; } // copy of wider time frame array of values double[] hadMASlow = new double[Bars]; adMASlow.CopyTo(hadMASlow, 0); err3 = CurrentTimeFrame(hIndex, hBars, ref adMASlow); // if any error, return out of calculation and indicator fails silently if (err3 == 1) { return; } // copy of wider time frame array of values double[] hadMAOscillator = new double[Bars]; adMAOscillator.CopyTo(hadMAOscillator, 0); err3 = CurrentTimeFrame(hIndex, hBars, ref adMAOscillator); // if any error, return out of calculation and indicator fails silently if (err3 == 1) { return; } /// end WTF modfication 2 version 4 //----------------------------------------------------------------------------- // Saving the components Component = new IndicatorComp[4]; Component[0] = new IndicatorComp(); Component[0].CompName = "Fast Moving Average"; Component[0].ChartColor = Color.FromName(sFastColor); Component[0].DataType = IndComponentType.IndicatorValue; Component[0].ChartType = IndChartType.Line; Component[0].FirstBar = iFirstBar; Component[0].Value = adMAFast; Component[1] = new IndicatorComp(); Component[1].CompName = "Slow Moving Average"; Component[1].ChartColor = Color.FromName(sSlowColor); Component[1].DataType = IndComponentType.IndicatorValue; Component[1].ChartType = IndChartType.Line; Component[1].FirstBar = iFirstBar; Component[1].Value = adMASlow; Component[2] = new IndicatorComp(); Component[2].ChartType = IndChartType.NoChart; Component[2].FirstBar = iFirstBar; Component[2].Value = new double[Bars]; Component[3] = new IndicatorComp(); Component[3].ChartType = IndChartType.NoChart; Component[3].FirstBar = iFirstBar; Component[3].Value = new double[Bars]; // Sets the Component's type if (slotType == SlotTypes.OpenFilter) { Component[2].DataType = IndComponentType.AllowOpenLong; Component[2].CompName = "Is long entry allowed"; Component[3].DataType = IndComponentType.AllowOpenShort; Component[3].CompName = "Is short entry allowed"; } else if (slotType == SlotTypes.CloseFilter) { Component[2].DataType = IndComponentType.ForceCloseLong; Component[2].CompName = "Close out long position"; Component[3].DataType = IndComponentType.ForceCloseShort; Component[3].CompName = "Close out short position"; } // Calculation of the logic IndicatorLogic indLogic = IndicatorLogic.It_does_not_act_as_a_filter; switch (IndParam.ListParam[0].Text) { case "The Fast MA crosses the Slow MA upward": indLogic = IndicatorLogic.The_indicator_crosses_the_level_line_upward; break; case "The Fast MA crosses the Slow MA downward": indLogic = IndicatorLogic.The_indicator_crosses_the_level_line_downward; break; case "The Fast MA is higher than the Slow MA": indLogic = IndicatorLogic.The_indicator_is_higher_than_the_level_line; break; case "The Fast MA is lower than the Slow MA": indLogic = IndicatorLogic.The_indicator_is_lower_than_the_level_line; break; case "Draw only, no entry or exit signals": Component[2].CompName = "Visual Only"; Component[2].DataType = IndComponentType.NotDefined; Component[3].CompName = "Visual Only"; Component[3].DataType = IndComponentType.NotDefined; break; default: break; } /// start WTF modfication 3 version 4 // back up Bars value, reset to hBars, for performance improvement in indicator logic function int mtfBars = Data.Bars; Data.Bars = hBars; // replace very small values with 0 for performance improvement; don't know why but works for (int ctr = 0; ctr < hadMAOscillator.Length; ctr++) { hadMAOscillator[ctr] = (hadMAOscillator[ctr] < .000000001 && hadMAOscillator[ctr] > -.000000001) ? 0 : hadMAOscillator[ctr]; } OscillatorLogic(iFirstBar, iPrvs, hadMAOscillator, 0, 0, ref Component[2], ref Component[3], indLogic); // resest Bars to real value Data.Bars = mtfBars; // expand component array from wtf to current time frame double[] wtfCompValue = Component[2].Value; int err4 = CurrentTimeFrame(hIndex, hBars, ref wtfCompValue); if (err4 == 1) { return; } Component[2].Value = wtfCompValue; wtfCompValue = Component[3].Value; int err5 = CurrentTimeFrame(hIndex, hBars, ref wtfCompValue); if (err5 == 1) { return; } Component[3].Value = wtfCompValue; /// end WTF modfication 3 version 4 return; }
/// <summary> /// Calculates the indicator's components /// </summary> public override void Calculate(SlotTypes slotType) { // Reading the parameters BasePrice basePrice = (BasePrice)IndParam.ListParam[2].Index; int n = (int)IndParam.NumParam[0].Value; double dLevel = IndParam.NumParam[1].Value; int iPrvs = IndParam.CheckParam[0].Checked ? 1 : 0; // Convert to Higher Time Frame --------------------------------------------- DataPeriods htfPeriod = DataPeriods.week; double[] hfOpen = new double[Bars]; double[] hfClose = new double[Bars]; double[] hfHigh = new double[Bars]; double[] hfLow = new double[Bars]; double[] hfVolume = new double[Bars]; double[] hfPrice = new double[Bars]; int[] hIndex = new int[Bars]; int iFrame; int hBars; switch (IndParam.ListParam[4].Index) { case 1: htfPeriod = DataPeriods.min5; break; case 2: htfPeriod = DataPeriods.min15; break; case 3: htfPeriod = DataPeriods.min30; break; case 4: htfPeriod = DataPeriods.hour1; break; case 5: htfPeriod = DataPeriods.hour4; break; case 6: htfPeriod = DataPeriods.day; break; case 7: htfPeriod = DataPeriods.week; break; } int err1 = HigherTimeFrame(Period, htfPeriod, out hIndex, out hBars, out iFrame, out hfHigh, out hfLow, out hfOpen, out hfClose, out hfVolume); int err2 = HigherBasePrice(basePrice, hBars, hfHigh, hfLow, hfOpen, hfClose, out hfPrice); if (err1 == 1) { return; } // Calculation int iFirstBar = n + 1; double[] adRegr = new double[Bars]; double[] adRSquared = new double[Bars]; double rsquared; for (int period = iFirstBar; period < Bars; period++) { double x = 0; double xx = 0; double xy = 0; double y = 0; double b = 0; double a = 0; double sumY2 = 0; for (int i = 0; i < n; i++) { int ii = i + 1; double source = hfPrice[period - (n - i)]; // source = xVal x = x + ii; // x = xSum xx = xx + (ii * ii); // xx = sumX2 xy = xy + (ii * source); // xy = sumXY y = y + source; // y = ySum sumY2 += (source * source); } // adapting eSignal code from Tech S&C article Dec 2007 p. 74 // article gets r-squared, matching lines from FXCM code to article's code // see Regression .lua or .cs for orignal regression code // (nLRlen * sumXY) - (xSum * ySum) b = (n * xy) - (x * y); double line1 = b; // (nLRlen * sumX2 - (xSum*xSum)) double line2 = n * xx - (x * x); if (Math.Abs(line2) < 1e-10) { b = 0; } else { b = b / (line2); a = y - (b * x); a = a / n; } // nLRlen * sumY2 - (ySum * ySum) double line3 = n * sumY2 - (y * y); rsquared = Math.Pow(line1 / Math.Sqrt(line2 * line3), 2); adRSquared[period] = rsquared; } // Convert to Current Time Frame ---------------------------------------------- /// start WTF modfication 2 version 4 // copy of wider time frame array of values double[] hadRSquared = new double[Bars]; adRSquared.CopyTo(hadRSquared, 0); int err3 = CurrentTimeFrame(hIndex, hBars, ref adRSquared); // if any error, return out of calculation and indicator fails silently if (err3 == 1) { return; } /// end WTF modfication 2 version 4 //----------------------------------------------------------------------------- // Saving the components Component = new IndicatorComp[3]; Component[0] = new IndicatorComp(); Component[0].CompName = "R Squared"; Component[0].DataType = IndComponentType.IndicatorValue; Component[0].ChartType = IndChartType.Histogram; Component[0].FirstBar = iFirstBar; Component[0].Value = adRSquared; Component[1] = new IndicatorComp(); Component[1].ChartType = IndChartType.NoChart; Component[1].FirstBar = iFirstBar; Component[1].Value = new double[Bars]; Component[2] = new IndicatorComp(); Component[2].ChartType = IndChartType.NoChart; Component[2].FirstBar = iFirstBar; Component[2].Value = new double[Bars]; // Sets the Component's type if (slotType == SlotTypes.OpenFilter) { Component[1].DataType = IndComponentType.AllowOpenLong; Component[1].CompName = "Is long entry allowed"; Component[2].DataType = IndComponentType.AllowOpenShort; Component[2].CompName = "Is short entry allowed"; } else if (slotType == SlotTypes.CloseFilter) { Component[1].DataType = IndComponentType.ForceCloseLong; Component[1].CompName = "Close out long position"; Component[2].DataType = IndComponentType.ForceCloseShort; Component[2].CompName = "Close out short position"; } // Calculation of the logic IndicatorLogic indLogic = IndicatorLogic.It_does_not_act_as_a_filter; switch (IndParam.ListParam[0].Text) { case "The R Squared Line rises": indLogic = IndicatorLogic.The_indicator_rises; break; case "The R Squared Line falls": indLogic = IndicatorLogic.The_indicator_falls; break; case "The R Squared Line is higher than the Level line": indLogic = IndicatorLogic.The_indicator_is_higher_than_the_level_line; SpecialValues = new double[1] { dLevel }; break; case "The R Squared Line is lower than the Level line": indLogic = IndicatorLogic.The_indicator_is_lower_than_the_level_line; SpecialValues = new double[1] { dLevel }; break; case "The R Squared Line crosses the Level line upward": indLogic = IndicatorLogic.The_indicator_crosses_the_level_line_upward; SpecialValues = new double[1] { dLevel }; break; case "The R Squared Line crosses the Level line downward": indLogic = IndicatorLogic.The_indicator_crosses_the_level_line_downward; SpecialValues = new double[1] { dLevel }; break; case "The R Squared Line changes its direction upward": indLogic = IndicatorLogic.The_indicator_changes_its_direction_upward; break; case "The R Squared Line changes its direction downward": indLogic = IndicatorLogic.The_indicator_changes_its_direction_downward; break; default: break; } /// start WTF modfication 3 version 4 // back up Bars value, reset to hBars, for performance improvement in indicator logic function int mtfBars = Data.Bars; Data.Bars = hBars; // replace very small values with 0 for performance improvement; don't know why but works for (int ctr = 0; ctr < hadRSquared.Length; ctr++) { hadRSquared[ctr] = (hadRSquared[ctr] < .000000001 && hadRSquared[ctr] > -.000000001) ? 0 : hadRSquared[ctr]; } NoDirectionOscillatorLogic(iFirstBar, iPrvs, hadRSquared, dLevel, ref Component[1], indLogic); // resest Bars to real value Data.Bars = mtfBars; // expand component array from wtf to current time frame double[] wtfCompValue = Component[1].Value; int err4 = CurrentTimeFrame(hIndex, hBars, ref wtfCompValue); if (err4 == 1) { return; } Component[1].Value = Component[2].Value = wtfCompValue; /// end WTF modfication 3 version 4 return; }
/// <summary> /// Calculates the indicator's components /// </summary> public override void Calculate(SlotTypes slotType) { // Reading the parameters MAMethod maMethod = (MAMethod )IndParam.ListParam[1].Index; BasePrice basePrice = (BasePrice)IndParam.ListParam[2].Index; int iMAPeriod = (int)IndParam.NumParam[0].Value; int iLRLength = (int)IndParam.NumParam[1].Value; double dLevel = IndParam.NumParam[2].Value; int iPrvs = IndParam.CheckParam[0].Checked ? 1 : 0; double[] dX = new double[Bars]; double[] dY = new double[Bars]; double dSigX; double dSigY; double dSigXY; double dSigXX; double[] adLRSlope = new double[Bars]; // Convert to Higher Time Frame --------------------------------------------- DataPeriods htfPeriod = DataPeriods.week; double[] hfOpen = new double[Bars]; double[] hfClose = new double[Bars]; double[] hfHigh = new double[Bars]; double[] hfLow = new double[Bars]; double[] hfVolume = new double[Bars]; double[] hfPrice = new double[Bars]; int[] hIndex = new int[Bars]; int iFrame; int hBars; switch (IndParam.ListParam[4].Index) { case 1: htfPeriod = DataPeriods.min5; break; case 2: htfPeriod = DataPeriods.min15; break; case 3: htfPeriod = DataPeriods.min30; break; case 4: htfPeriod = DataPeriods.hour1; break; case 5: htfPeriod = DataPeriods.hour4; break; case 6: htfPeriod = DataPeriods.day; break; case 7: htfPeriod = DataPeriods.week; break; } int err1 = HigherTimeFrame(Period, htfPeriod, out hIndex, out hBars, out iFrame, out hfHigh, out hfLow, out hfOpen, out hfClose, out hfVolume); int err2 = HigherBasePrice(basePrice, hBars, hfHigh, hfLow, hfOpen, hfClose, out hfPrice); if (err1 == 1) { return; } //------------------------------------------------------------------------ int iFirstBar = iMAPeriod + iLRLength + 2; double[] adMAPrice = MovingAverage(iMAPeriod, 0, maMethod, hfPrice); for (int iBar = iFirstBar; iBar < hBars; iBar++) { dSigX = 0; dSigY = 0; dSigXX = 0; dSigXY = 0; for (int index = 0; index < iLRLength; index++) { dSigX = dSigX + index; dSigY = dSigY + adMAPrice[iBar - index]; dSigXY = dSigXY + index * adMAPrice[iBar - index]; dSigXX = dSigXX + index * index; } adLRSlope[iBar] = -(iLRLength * dSigXY - dSigX * dSigY) / (iLRLength * dSigXX - dSigX * dSigX); } // Convert to Current Time Frame ---------------------------------------------- /// start WTF modfication 2 version 4 // copy of wider time frame array of values double[] hadLRSlope = new double[Bars]; adLRSlope.CopyTo(hadLRSlope, 0); int err3 = CurrentTimeFrame(hIndex, hBars, ref adLRSlope); // if any error, return out of calculation and indicator fails silently if (err3 == 1) { return; } /// end WTF modfication 2 version 4 //----------------------------------------------------------------------------- // Saving the components Component = new IndicatorComp[3]; Component[0] = new IndicatorComp(); Component[0].CompName = "LR Slope"; Component[0].DataType = IndComponentType.IndicatorValue; Component[0].ChartType = IndChartType.Histogram; Component[0].FirstBar = iFirstBar; Component[0].Value = adLRSlope; Component[1] = new IndicatorComp(); Component[1].ChartType = IndChartType.NoChart; Component[1].FirstBar = iFirstBar; Component[1].Value = new double[Bars]; Component[2] = new IndicatorComp(); Component[2].ChartType = IndChartType.NoChart; Component[2].FirstBar = iFirstBar; Component[2].Value = new double[Bars]; // Sets the Component's type if (slotType == SlotTypes.OpenFilter) { Component[1].DataType = IndComponentType.AllowOpenLong; Component[1].CompName = "Is long entry allowed"; Component[2].DataType = IndComponentType.AllowOpenShort; Component[2].CompName = "Is short entry allowed"; } else if (slotType == SlotTypes.CloseFilter) { Component[1].DataType = IndComponentType.ForceCloseLong; Component[1].CompName = "Close out long position"; Component[2].DataType = IndComponentType.ForceCloseShort; Component[2].CompName = "Close out short position"; } // Calculation of the logic IndicatorLogic indLogic = IndicatorLogic.It_does_not_act_as_a_filter; switch (IndParam.ListParam[0].Text) { case "The LR Slope rises": indLogic = IndicatorLogic.The_indicator_rises; SpecialValues = new double[1] { 0 }; break; case "The LR Slope falls": indLogic = IndicatorLogic.The_indicator_falls; SpecialValues = new double[1] { 0 }; break; case "The LR Slope is higher than the Level line": indLogic = IndicatorLogic.The_indicator_is_higher_than_the_level_line; SpecialValues = new double[2] { dLevel, -dLevel }; break; case "The LR Slope is lower than the Level line": indLogic = IndicatorLogic.The_indicator_is_lower_than_the_level_line; SpecialValues = new double[2] { dLevel, -dLevel }; break; case "The LR Slope crosses the Level line upward": indLogic = IndicatorLogic.The_indicator_crosses_the_level_line_upward; SpecialValues = new double[2] { dLevel, -dLevel }; break; case "The LR Slope crosses the Level line downward": indLogic = IndicatorLogic.The_indicator_crosses_the_level_line_downward; SpecialValues = new double[2] { dLevel, -dLevel }; break; case "The LR Slope changes its direction upward": indLogic = IndicatorLogic.The_indicator_changes_its_direction_upward; SpecialValues = new double[1] { 0 }; break; case "The LR Slope changes its direction downward": indLogic = IndicatorLogic.The_indicator_changes_its_direction_downward; SpecialValues = new double[1] { 0 }; break; default: break; } /// start WTF modfication 3 version 4 // back up Bars value, reset to hBars, for performance improvement in indicator logic function int mtfBars = Data.Bars; Data.Bars = hBars; // replace very small values with 0 for performance improvement; don't know why but works for (int ctr = 0; ctr < hadLRSlope.Length; ctr++) { hadLRSlope[ctr] = (hadLRSlope[ctr] < .000000001 && hadLRSlope[ctr] > -.000000001) ? 0 : hadLRSlope[ctr]; } OscillatorLogic(iFirstBar, iPrvs, hadLRSlope, dLevel, -dLevel, ref Component[1], ref Component[2], indLogic); // resest Bars to real value Data.Bars = mtfBars; // expand component array from wtf to current time frame double[] wtfCompValue = Component[1].Value; int err4 = CurrentTimeFrame(hIndex, hBars, ref wtfCompValue); if (err4 == 1) { return; } Component[1].Value = wtfCompValue; wtfCompValue = Component[2].Value; int err5 = CurrentTimeFrame(hIndex, hBars, ref wtfCompValue); if (err5 == 1) { return; } Component[2].Value = wtfCompValue; /// end WTF modfication 3 version 4 return; }
/// <summary> /// Repaint the panel Info /// </summary> void PnlInfo_Paint(object sender, PaintEventArgs e) { // +------------------------------------------------------+ // | Data | // |------------------- ----------------------------------+ // | Period | Bars | From | Until | Cover | % | Label | // |------------------------------------------------------+ //xp0 xp1 xp2 xp3 xp4 xp5 xp6 xp7 Graphics g = e.Graphics; g.Clear(LayoutColors.ColorControlBack); if (!Data.IsData || !Data.IsResult) { return; } Panel pnl = (Panel)sender; string FF = Data.FF; // Format modifier to print the numbers int border = 2; int xp0 = border; int xp1 = 80; int xp2 = 140; int xp3 = 200; int xp4 = 260; int xp5 = 320; int xp6 = 370; int xp7 = pnl.ClientSize.Width - border; Size size = new Size(xp7 - xp0, infoRowHeight); StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Near; // Caption background PointF pntStart = new PointF(0, 0); SizeF szfCaption = new Size(pnl.ClientSize.Width - 0, 2 * infoRowHeight); RectangleF rectfCaption = new RectangleF(pntStart, szfCaption); Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); // Caption Text StringFormat stringFormatCaption = new StringFormat(); stringFormatCaption.LineAlignment = StringAlignment.Center; stringFormatCaption.Trimming = StringTrimming.EllipsisCharacter; stringFormatCaption.FormatFlags = StringFormatFlags.NoWrap; stringFormatCaption.Alignment = StringAlignment.Near; string stringCaptionText = Language.T("Intrabar Data"); float captionWidth = Math.Min(pnlInfo.ClientSize.Width, xp7 - xp0); float captionTextWidth = g.MeasureString(stringCaptionText, fontInfo).Width; float captionTextX = Math.Max((captionWidth - captionTextWidth) / 2f, 0); PointF pfCaptionText = new PointF(captionTextX, 0); SizeF sfCaptionText = new SizeF(captionWidth - captionTextX, infoRowHeight); rectfCaption = new RectangleF(pfCaptionText, sfCaptionText); Brush brush = new SolidBrush(LayoutColors.ColorCaptionText); // First caption row g.DrawString(stringCaptionText, fontInfo, brush, rectfCaption, stringFormatCaption); // Second title row g.DrawString(Language.T("Period"), fontInfo, brush, (xp1 + xp0) / 2, infoRowHeight, sf); g.DrawString(Language.T("Bars"), fontInfo, brush, (xp2 + xp1) / 2, infoRowHeight, sf); g.DrawString(Language.T("From"), fontInfo, brush, (xp3 + xp2) / 2, infoRowHeight, sf); g.DrawString(Language.T("Until"), fontInfo, brush, (xp4 + xp3) / 2, infoRowHeight, sf); g.DrawString(Language.T("Coverage"), fontInfo, brush, (xp5 + xp4) / 2, infoRowHeight, sf); g.DrawString("%", fontInfo, brush, (xp6 + xp5) / 2, infoRowHeight, sf); g.DrawString(Language.T("Label"), fontInfo, brush, (xp7 + xp6) / 2, infoRowHeight, sf); brush = new SolidBrush(LayoutColors.ColorControlText); int allPeriods = Enum.GetValues(typeof(DataPeriods)).Length; for (int iPeriod = 0; iPeriod <= allPeriods; iPeriod++) { int y = (iPeriod + 2) * infoRowHeight; Point point = new Point(xp0, y); if (iPeriod % 2f != 0) { g.FillRectangle(new SolidBrush(LayoutColors.ColorEvenRowBack), new Rectangle(point, size)); } } // Tick statistics if (isTickDataFile) { g.DrawString(Language.T("Tick"), fontInfo, brush, (xp1 + xp0) / 2, 2 * infoRowHeight, sf); if (Data.IsTickData && Configs.UseTickData) { int firstBarWithTicks = -1; int lastBarWithTicks = -1; int tickBars = 0; for (int b = 0; b < Data.Bars; b++) { if (firstBarWithTicks == -1 && Data.TickData[b] != null) { firstBarWithTicks = b; } if (Data.TickData[b] != null) { lastBarWithTicks = b; tickBars++; } } double percentage = 100d * tickBars / Data.Bars; int y = 2 * infoRowHeight; string ticks = (Data.Ticks > 999999) ? (Data.Ticks / 1000).ToString() + "K" : Data.Ticks.ToString(); g.DrawString(ticks, fontInfo, brush, (xp2 + xp1) / 2, y, sf); g.DrawString((firstBarWithTicks + 1).ToString(), fontInfo, brush, (xp3 + xp2) / 2, y, sf); g.DrawString((lastBarWithTicks + 1).ToString(), fontInfo, brush, (xp4 + xp3) / 2, y, sf); g.DrawString(tickBars.ToString(), fontInfo, brush, (xp5 + xp4) / 2, y, sf); g.DrawString(percentage.ToString("F2"), fontInfo, brush, (xp6 + xp5) / 2, y, sf); RectangleF rectf = new RectangleF(xp6 + 10, y + 4, xp7 - xp6 - 20, 9); Data.GradientPaint(g, rectf, Data.PeriodColor[DataPeriods.min1], 60); rectf = new RectangleF(xp6 + 10, y + 7, xp7 - xp6 - 20, 3); Data.GradientPaint(g, rectf, Data.PeriodColor[DataPeriods.day], 60); } } for (int iPeriod = 0; iPeriod < allPeriods; iPeriod++) { int startY = isTickDataFile ? 3 : 2; int y = (iPeriod + startY) * infoRowHeight; Point point = new Point(xp0, y); DataPeriods period = (DataPeriods)Enum.GetValues(typeof(DataPeriods)).GetValue(iPeriod); int intraBars = Data.IntraBars == null || !Data.IsIntrabarData ? 0 : Data.IntraBars[iPeriod]; int fromBar = 0; int untilBar = 0; int coveredBars = 0; double percentage = 0; bool isMultyAreas = false; if (intraBars > 0) { bool isFromBarFound = false; bool isUntilBarFound = false; untilBar = Data.Bars; for (int bar = 0; bar < Data.Bars; bar++) { if (!isFromBarFound && Data.IntraBarsPeriods[bar] == period) { fromBar = bar; isFromBarFound = true; } if (isFromBarFound && !isUntilBarFound && (Data.IntraBarsPeriods[bar] != period || bar == Data.Bars - 1)) { if (bar < Data.Bars - 1) { isUntilBarFound = true; untilBar = bar; } else { untilBar = Data.Bars; } coveredBars = untilBar - fromBar; } if (isFromBarFound && isUntilBarFound && Data.IntraBarsPeriods[bar] == period) { isMultyAreas = true; coveredBars++; } } if (isFromBarFound) { percentage = 100d * coveredBars / Data.Bars; fromBar++; } else { fromBar = 0; untilBar = 0; coveredBars = 0; percentage = 0; } } else if (period == Data.Period) { intraBars = Data.Bars; fromBar = 1; untilBar = Data.Bars; coveredBars = Data.Bars; percentage = 100; } g.DrawString(Data.DataPeriodToString(period), fontInfo, brush, (xp1 + xp0) / 2, y, sf); if (coveredBars > 0 || period == Data.Period) { g.DrawString(intraBars.ToString(), fontInfo, brush, (xp2 + xp1) / 2, y, sf); g.DrawString(fromBar.ToString(), fontInfo, brush, (xp3 + xp2) / 2, y, sf); g.DrawString(untilBar.ToString(), fontInfo, brush, (xp4 + xp3) / 2, y, sf); g.DrawString(coveredBars.ToString() + (isMultyAreas ? "*" : ""), fontInfo, brush, (xp5 + xp4) / 2, y, sf); g.DrawString(percentage.ToString("F2"), fontInfo, brush, (xp6 + xp5) / 2, y, sf); RectangleF rectf = new RectangleF(xp6 + 10, y + 4, xp7 - xp6 - 20, 9); Data.GradientPaint(g, rectf, Data.PeriodColor[period], 60); } } Pen penLine = new Pen(LayoutColors.ColorJournalLines); g.DrawLine(penLine, xp1, 2 * infoRowHeight, xp1, pnl.ClientSize.Height); g.DrawLine(penLine, xp2, 2 * infoRowHeight, xp2, pnl.ClientSize.Height); g.DrawLine(penLine, xp3, 2 * infoRowHeight, xp3, pnl.ClientSize.Height); g.DrawLine(penLine, xp4, 2 * infoRowHeight, xp4, pnl.ClientSize.Height); g.DrawLine(penLine, xp5, 2 * infoRowHeight, xp5, pnl.ClientSize.Height); g.DrawLine(penLine, xp6, 2 * infoRowHeight, xp6, pnl.ClientSize.Height); // Border Pen penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); g.DrawLine(penBorder, 1, 2 * infoRowHeight, 1, pnl.ClientSize.Height); g.DrawLine(penBorder, pnl.ClientSize.Width - border + 1, 2 * infoRowHeight, pnl.ClientSize.Width - border + 1, pnl.ClientSize.Height); g.DrawLine(penBorder, 0, pnl.ClientSize.Height - border + 1, pnl.ClientSize.Width, pnl.ClientSize.Height - border + 1); return; }
/// <summary> /// Calculates the indicator's components /// </summary> public override void Calculate(SlotTypes slotType) { // Reading the parameters bool T3Original = IndParam.ListParam[1].Text == "True"; bool T3Average = IndParam.ListParam[2].Text == "True"; MAMethod maMethod = (MAMethod)IndParam.ListParam[4].Index; int MaPeriod = (int)IndParam.NumParam[0].Value; double Step = IndParam.NumParam[1].Value; double T3Hot = IndParam.NumParam[2].Value; bool BetterFormula = IndParam.NumParam[3].Value == 1; int iPrvs = IndParam.CheckParam[0].Checked ? 1 : 0; // Convert to Higher Time Frame --------------------------------------------- DataPeriods htfPeriod = DataPeriods.week; double[] hfOpen = new double[Bars]; double[] hfClose = new double[Bars]; double[] hfHigh = new double[Bars]; double[] hfLow = new double[Bars]; double[] hfVolume = new double[Bars]; double[] hfPrice = new double[Bars]; int[] hIndex = new int[Bars]; int iFrame; int hBars; switch (IndParam.ListParam[3].Index) { case 1: htfPeriod = DataPeriods.min5; break; case 2: htfPeriod = DataPeriods.min15; break; case 3: htfPeriod = DataPeriods.min30; break; case 4: htfPeriod = DataPeriods.hour1; break; case 5: htfPeriod = DataPeriods.hour4; break; case 6: htfPeriod = DataPeriods.day; break; case 7: htfPeriod = DataPeriods.week; break; } int err1 = HigherTimeFrame(Period, htfPeriod, out hIndex, out hBars, out iFrame, out hfHigh, out hfLow, out hfOpen, out hfClose, out hfVolume); // int err2 = HigherBasePrice(basePrice, hBars, hfHigh, hfLow, hfOpen, hfClose, out hfPrice); if (err1 == 1) { return; } //----------------------------------------------------------------------- double[] ExtMapBuffer1 = new double[Bars]; double[] ExtMapBuffer2 = new double[Bars]; double[] ExtMapBuffer3 = new double[Bars]; double[] ExtMapBuffer4 = new double[Bars]; double[] allowlong = new double[Bars]; double[] allowshort = new double[Bars]; double[] adDisplay = new double[Bars]; double maOpen, maClose, maLow, maHigh; double[] maOpen1 = new double[Bars]; double[] maClose1 = new double[Bars]; double[] maLow1 = new double[Bars]; double[] maHigh1 = new double[Bars]; double[] trace = new double[Bars]; double haOpen, haClose, haLow, haHigh; int pointModifier; if (Digits == 3 || Digits == 5) { pointModifier = 10; } else { pointModifier = 1; } double alpha; double c1; double c2; double c3; double c4; double a = T3Hot; c1 = -a * a * a; c2 = 3 * (a * a + a * a * a); c3 = -3 * (2 * a * a + a + a * a * a); c4 = 1 + 3 * a + a * a * a + 3 * a * a; if (T3Original) { alpha = 2.0 / (1.0 + MaPeriod); } else { alpha = 2.0 / (2.0 + (MaPeriod - 1.0) / 2.0); } double[,] emas = new double[Bars, 24]; int iFirstBar = 1 + iPrvs + MaPeriod; // WTF -- change from Price data to hfPrice data maOpen1 = MovingAverage(MaPeriod, 0, maMethod, hfOpen); maClose1 = MovingAverage(MaPeriod, 0, maMethod, hfClose); maLow1 = MovingAverage(MaPeriod, 0, maMethod, hfLow); maHigh1 = MovingAverage(MaPeriod, 0, maMethod, hfHigh); int L = 0; int S = 0; // WTF -- iterate up to hBars instead of Bars for (int iBar = 2; iBar < hBars; iBar++) { if (T3Average) { // WTF -- change from Price data to hfPrice data maOpen = iT3(hfOpen[iBar], iBar, 0, alpha, c1, c2, c3, c4, emas); maClose = iT3(hfClose[iBar], iBar, 6, alpha, c1, c2, c3, c4, emas); maLow = iT3(hfLow[iBar], iBar, 12, alpha, c1, c2, c3, c4, emas); maHigh = iT3(hfHigh[iBar], iBar, 18, alpha, c1, c2, c3, c4, emas); } else { maOpen = maOpen1[iBar]; maClose = maClose1[iBar]; maLow = maLow1[iBar]; maHigh = maHigh1[iBar]; } trace[iBar] = maOpen; if (BetterFormula) { if (maHigh != maLow) { haClose = (maOpen + maClose) / 2 + (((maClose - maOpen) / (maHigh - maLow)) * Math.Abs((maClose - maOpen) / 2)); } else { haClose = (maOpen + maClose) / 2; } } else { haClose = (maOpen + maHigh + maLow + maClose) / 4; } haOpen = (ExtMapBuffer3[iBar - 1] + ExtMapBuffer4[iBar - 1]) / 2; haHigh = Math.Max(maHigh, Math.Max(haOpen, haClose)); haLow = Math.Min(maLow, Math.Min(haOpen, haClose)); if (haOpen < haClose) { ExtMapBuffer1[iBar] = haLow; ExtMapBuffer2[iBar] = haHigh; } else { ExtMapBuffer1[iBar] = haHigh; ExtMapBuffer2[iBar] = haLow; } ExtMapBuffer3[iBar] = haOpen; ExtMapBuffer4[iBar] = haClose; if (Step > 0) { if (Math.Abs(ExtMapBuffer1[iBar] - ExtMapBuffer1[iBar - 1]) < Step * pointModifier * Point) { ExtMapBuffer1[iBar] = ExtMapBuffer1[iBar - 1]; } if (Math.Abs(ExtMapBuffer2[iBar] - ExtMapBuffer2[iBar - 1]) < Step * pointModifier * Point) { ExtMapBuffer2[iBar] = ExtMapBuffer2[iBar - 1]; } if (Math.Abs(ExtMapBuffer3[iBar] - ExtMapBuffer3[iBar - 1]) < Step * pointModifier * Point) { ExtMapBuffer3[iBar] = ExtMapBuffer3[iBar - 1]; } if (Math.Abs(ExtMapBuffer4[iBar] - ExtMapBuffer4[iBar - 1]) < Step * pointModifier * Point) { ExtMapBuffer4[iBar] = ExtMapBuffer4[iBar - 1]; } } // WTF -- subtract iPrvs here to move WTF signals to match ending time of WTF bar if (ExtMapBuffer3[iBar - 1 - iPrvs] < ExtMapBuffer4[iBar - 1 - iPrvs] && ExtMapBuffer4[iBar - 2 - iPrvs] < ExtMapBuffer3[iBar - 2 - iPrvs]) { if (L == 0) { allowlong[iBar] = 1; allowshort[iBar] = 0; adDisplay[iBar] = 1; L = 1; S = 0; } } if (ExtMapBuffer3[iBar - 1 - iPrvs] > ExtMapBuffer4[iBar - 1 - iPrvs] && ExtMapBuffer4[iBar - 2 - iPrvs] > ExtMapBuffer3[iBar - 2 - iPrvs]) { if (S == 0) { allowlong[iBar] = 0; allowshort[iBar] = 1; adDisplay[iBar] = -1; L = 0; S = 1; } } } // Convert to Current Time Frame ---------------------------------------------- /// WTF modification 2 -- copy of wider time frame array of values -- not used in this indicator because no need for IndicatorLogic step due to allowlong/short being 1 and 0 already // only expand from WTF to current time frame int err3 = CurrentTimeFrame(hIndex, hBars, ref allowlong); int err4 = CurrentTimeFrame(hIndex, hBars, ref allowshort); int err5 = CurrentTimeFrame(hIndex, hBars, ref adDisplay); // if any error, return out of calculation and indicator fails silently if (err3 == 1 || err4 == 1 | err5 == 1) { return; } /// end WTF modfication 2 version 4 //----------------------------------------------------------------------------- // Saving the components Component = new IndicatorComp[3]; Component[0] = new IndicatorComp(); Component[0].CompName = "Allow long entry"; Component[0].DataType = IndComponentType.AllowOpenLong; Component[0].ChartType = IndChartType.NoChart; Component[0].FirstBar = iFirstBar; Component[0].Value = allowlong; Component[1] = new IndicatorComp(); Component[1].CompName = "Allow short entry"; Component[1].DataType = IndComponentType.AllowOpenShort; Component[1].ChartType = IndChartType.NoChart; Component[1].FirstBar = iFirstBar; Component[1].Value = allowshort; Component[2] = new IndicatorComp(); Component[2].CompName = "Signal Display"; Component[2].DataType = IndComponentType.IndicatorValue; Component[2].ChartType = IndChartType.Histogram; Component[2].FirstBar = iFirstBar; Component[2].Value = adDisplay; /// start WTF modfication 3 version 4 // not used in this indicator because the IndicatorLogic function is not used /// end WTF modfication 3 version 4 return; }
private List<Bar> CompileBars(IEnumerable<Bar> minuteBarList, DataPeriods period) { var barList = new List<Bar>(); var lastBarEndTime = new DateTime(); foreach (var bar in minuteBarList) { if (bar.Time >= lastBarEndTime) { DateTime lastBarStartTime = GetBarStartTime(bar.Time, (int) period); lastBarEndTime = lastBarStartTime.AddMinutes((int) period); Bar newBar = bar; newBar.Time = lastBarStartTime; barList.Add(newBar); continue; } Bar lastBar = barList[barList.Count - 1]; if (lastBar.High < bar.High) lastBar.High = bar.High; if (lastBar.Low > bar.Low) lastBar.Low = bar.Low; lastBar.Close = bar.Close; lastBar.Volume += bar.Volume; barList[barList.Count - 1] = lastBar; } return barList; }
/// <summary> /// Loads the Intrabar data. /// </summary> int LoadIntrabarData(DataPeriods period) { Instrument instrument = new Instrument(Data.InstrProperties.Clone(), (int)period); instrument.DataDir = Data.OfflineDataDir; instrument.FormatDate = DateFormat.Unknown; instrument.MaxBars = Configs.MAX_INTRA_BARS; // Loads the data int loadingResult = instrument.LoadData(); int loadedIntrabars = instrument.Bars; if (loadingResult == 0 && loadedIntrabars > 0) { if (Data.Period != DataPeriods.week) { if (instrument.DaysOff > 5) warningMessage += Environment.NewLine + Language.T("Data for:") + " " + Data.Symbol + " " + Data.DataPeriodToString(period) + " - " + Language.T("Maximum days off:") + " " + instrument.DaysOff; if (Data.Update - instrument.Update > new TimeSpan(24, 0, 0)) warningMessage += Environment.NewLine + Language.T("Data for:") + " " + Data.Symbol + " " + Data.DataPeriodToString(period) + " - " + Language.T("Updated on:") + " " + instrument.Update.ToString(); } int iStartBigBar = 0; for (iStartBigBar = 0; iStartBigBar < Data.Bars; iStartBigBar++) if (Data.Time[iStartBigBar] >= instrument.Time(0)) break; int iStopBigBar = 0; for (iStopBigBar = iStartBigBar; iStopBigBar < Data.Bars; iStopBigBar++) if (Data.IntraBarsPeriods[iStopBigBar] != Data.Period) break; // Seek for the place int iReachedBar = 0; for (int bar = iStartBigBar; bar < iStopBigBar; bar++) { Data.IntraBarData[bar] = new Bar[(int)Data.Period/(int)period]; DateTime endTime = Data.Time[bar] + new TimeSpan(0, (int)Data.Period, 0); int iCurrentBar = 0; for (int intrabar = iReachedBar; intrabar < loadedIntrabars && instrument.Time(intrabar) < endTime; intrabar++) { if (instrument.Time(intrabar) >= Data.Time[bar]) { Data.IntraBarData[bar][iCurrentBar].Time = instrument.Time(intrabar); Data.IntraBarData[bar][iCurrentBar].Open = instrument.Open(intrabar); Data.IntraBarData[bar][iCurrentBar].High = instrument.High(intrabar); Data.IntraBarData[bar][iCurrentBar].Low = instrument.Low(intrabar); Data.IntraBarData[bar][iCurrentBar].Close = instrument.Close(intrabar); Data.IntraBarsPeriods[bar] = period; Data.IntraBarBars[bar]++; iCurrentBar++; iReachedBar = intrabar; } } } } return loadedIntrabars; }
private void GenerateDataFile() { symbol = "GBPUSD"; instrProperties = new InstrumentProperties(symbol, InstrumetType.Forex) { Commission = 0, CommissionScope = CommissionScope.deal, CommissionTime = CommissionTime.openclose, Digits = 5, LotSize = 10000, RateToEUR = 2.3456, RateToUSD = 2.3456, Slippage = 1, Spread = 6, SwapLong = 0.25, SwapShort = 0.25, SwapType = CommissionType.pips }; int maxBars = 2*Configs.MaxBars; var sb = new StringBuilder(maxBars); var time = new DateTime(2000, 1, 1, 0, 0, 0); double open = 1.12345; int volume = 300; period = DataPeriods.hour4; for (int i = 0; i < maxBars; i++) { time = time.AddMinutes((int) DataPeriods.hour1); int multiplier = (time.DayOfYear%2 == 0) ? 1 : -1; open = open + multiplier*0.00005; double high = open + 0.00025; double low = open - 0.00025; double close = open + 0.00005; volume = volume + multiplier*5; sb.AppendLine(string.Format("{0} {1} {2} {3} {4} {5}", time.ToString("yyyy-MM-dd HH:mm:ss"), open.ToString("F5"), high.ToString("F5"), low.ToString("F5"), close.ToString("F5"), volume)); } dataFile = sb.ToString(); }
/// <summary> /// Convert current time frame to higher time frame /// </summary> /// start WTF modfication 4 version 4 protected static int HigherTimeFrame(DataPeriods currentTF, DataPeriods higherTF, out int[] hIndex, out int hBars, out int iFrame, out double[] hfHigh, out double[] hfLow, out double[] hfOpen, out double[] hfClose, out double[] hfVolume) { hfOpen = new double[Bars]; hfClose = new double[Bars]; hfHigh = new double[Bars]; hfLow = new double[Bars]; hfVolume = new double[Bars]; hIndex = new int[Bars]; hBars = 0; iFrame = 1; // verify user input, if higher TF is not greater than current TF then return to exit function if ((int)higherTF <= (int)currentTF) { return(1); } // Frame Calculation if (higherTF > currentTF) { iFrame = (int)((int)higherTF / (int)currentTF); } else { iFrame = 1; } if (higherTF == DataPeriods.week && currentTF == DataPeriods.day) { iFrame = 5; } TimeSpan tsCurrent = new TimeSpan(); switch (currentTF) { case DataPeriods.min1: tsCurrent = TimeSpan.FromMinutes(1); break; case DataPeriods.min5: tsCurrent = TimeSpan.FromMinutes(5); break; case DataPeriods.min15: tsCurrent = TimeSpan.FromMinutes(15); break; case DataPeriods.min30: tsCurrent = TimeSpan.FromMinutes(30); break; case DataPeriods.hour1: tsCurrent = TimeSpan.FromHours(1); break; case DataPeriods.hour4: tsCurrent = TimeSpan.FromHours(4); break; } TimeSpan tsHTF = new TimeSpan(); switch (higherTF) { case DataPeriods.min5: tsHTF = TimeSpan.FromMinutes(5); break; case DataPeriods.min15: tsHTF = TimeSpan.FromMinutes(15); break; case DataPeriods.min30: tsHTF = TimeSpan.FromMinutes(30); break; case DataPeriods.hour1: tsHTF = TimeSpan.FromHours(1); break; case DataPeriods.hour4: tsHTF = TimeSpan.FromHours(4); break; case DataPeriods.day: tsHTF = TimeSpan.FromDays(1); break; case DataPeriods.week: tsHTF = TimeSpan.FromDays(7); break; } // set all HTFs to start from first modulo period in data series and cut off earlier data // set iStartBar back one so htf close is written on last lower time frame bar of interval (eg, htf = 1 hour, write close on 1:55, 2:55, 3:55 bar instead of on 2:00, 3:00, 4:00 bar) // if htf is week, sync to close on Fridays int iStartBar = 0; DateTime dtStart = new DateTime(Date[0].Year, Date[0].Month, Date[0].Day, 0, 0, 0); if (higherTF == DataPeriods.week) { while (dtStart.DayOfWeek != DayOfWeek.Friday) { dtStart = dtStart.AddDays(-1); } } for (int iBar = 1; iBar < Bars; iBar++) { if ((Date[iBar] - dtStart).Ticks % tsHTF.Ticks == 0) { iStartBar = iBar; iBar = Bars; } } // loop through bars, figure difference between this bar time and period starting bar time // if difference equals time span, means new htf bar open // if greater than time span, resync the cycle, in case of crossing weekend or holidays, or a few lost bars // hIndex[hBar] -- to keep track of where HTF values change when going to LTF, which has a lot more bars; should be first LTF bar of the LTF bars that are in the HTF bar int hBar = 0; int iStartHTFBar = iStartBar; for (int iBar = iStartBar; iBar < Bars; iBar++) { // new higher time frame bar, initialize with values if ((Date[iBar] - Date[iStartHTFBar]).Ticks % tsHTF.Ticks == 0) { hBar++; iStartHTFBar = iBar; hfOpen[hBar] = Open[iBar]; hfClose[hBar] = Close[iBar]; hfHigh[hBar] = High[iBar]; hfLow[hBar] = Low[iBar]; hfVolume[hBar] = Volume[iBar]; hIndex[hBar] = iBar; } // progressing through higher time frame bar or at end, update High, Low, Close and Volume else if (Date[iBar] - Date[iStartHTFBar] < tsHTF) { hfClose[hBar] = Close[iBar]; if (High[iBar] > hfHigh[hBar]) { hfHigh[hBar] = High[iBar]; } if (Low[iBar] < hfLow[hBar]) { hfLow[hBar] = Low[iBar]; } hfVolume[hBar] += Volume[iBar]; } // must have lost some bars, so get back in sync, add values for closing of partial but completed htf bar else if (Date[iBar] - Date[iStartHTFBar] > tsHTF) { // set this bar as opening HTF bar, initialize hBar++; hfOpen[hBar] = Open[iBar]; hfClose[hBar] = Close[iBar]; hfHigh[hBar] = High[iBar]; hfLow[hBar] = Low[iBar]; hfVolume[hBar] = Volume[iBar]; hIndex[hBar] = iBar; for (int iSyncBar = iBar; iSyncBar < Bars; iSyncBar++) { // check if have found next HTF bar against last known HTF start bar if ((Date[iSyncBar] - Date[iStartHTFBar]).Ticks % tsHTF.Ticks == 0) { //have found next HTF bar, initialize hBar++; iStartHTFBar = iSyncBar; iBar = iSyncBar; hfOpen[hBar] = Open[iSyncBar]; hfClose[hBar] = Close[iSyncBar]; hfHigh[hBar] = High[iSyncBar]; hfLow[hBar] = Low[iSyncBar]; hfVolume[hBar] = Volume[iSyncBar]; hIndex[hBar] = iSyncBar; iSyncBar = Bars; } else // not found yet, only update { hfClose[hBar] = Close[iSyncBar]; if (High[iSyncBar] > hfHigh[hBar]) { hfHigh[hBar] = High[iSyncBar]; } if (Low[iSyncBar] < hfLow[hBar]) { hfLow[hBar] = Low[iSyncBar]; } hfVolume[hBar] += Volume[iSyncBar]; } } } } hBars = hBar + 1; return(0); }
/// <summary> /// Paints the charts /// </summary> private void PnlChartPaint(object sender, PaintEventArgs e) { var pnl = (Panel)sender; Graphics g = e.Graphics; const int space = 5; const int border = 2; // Chart Title string unit = " [" + (Configs.AccountInMoney ? Configs.AccountCurrency : Language.T("pips")) + "]"; string str = Language.T("Balance Chart") + unit; var font = new Font(Font.FontFamily, 9); var fCaptionHeight = (float)Math.Max(font.Height, 18); var rectfCaption = new RectangleF(0, 0, pnl.ClientSize.Width, fCaptionHeight); var stringFormatCaption = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); g.DrawString(str, Font, new SolidBrush(LayoutColors.ColorCaptionText), rectfCaption, stringFormatCaption); // Paint the panel background var rectClient = new RectangleF(border, fCaptionHeight, pnl.ClientSize.Width - 2 * border, pnl.Height - fCaptionHeight - border); Data.GradientPaint(g, rectClient, LayoutColors.ColorChartBack, LayoutColors.DepthControl); var penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); g.DrawLine(penBorder, 1, fCaptionHeight, 1, pnl.ClientSize.Height); g.DrawLine(penBorder, pnl.ClientSize.Width - border + 1, fCaptionHeight, pnl.ClientSize.Width - border + 1, pnl.ClientSize.Height); g.DrawLine(penBorder, 0, pnl.ClientSize.Height - border + 1, pnl.ClientSize.Width, pnl.ClientSize.Height - border + 1); if (!_isPaintChart) { if (Backtester.AmbiguousBars == 0) { string sNote = Language.T("The Comparator is useful when the backtest shows ambiguous bars!"); var rectfNote = new RectangleF(0, 30, pnl.ClientSize.Width, Font.Height); g.DrawString(sNote, Font, new SolidBrush(LayoutColors.ColorChartFore), rectfNote, stringFormatCaption); } return; } int bars = Data.Bars - Data.FirstBar; int max = (int)Math.Max(_maximum, _maximumRandom) + 1; int min = (int)Math.Min(_minimum, _minimumRandom) - 1; min = (int)Math.Floor(min / 10f) * 10; int yTop = (int)fCaptionHeight + 2 * space + 1; int yBottom = (pnl.ClientSize.Height - 2 * space - border); var labelWidth = (int) Math.Max(g.MeasureString(min.ToString(CultureInfo.InvariantCulture), Font).Width, g.MeasureString(max.ToString(CultureInfo.InvariantCulture), Font).Width); labelWidth = Math.Max(labelWidth, 30); int xRight = pnl.ClientSize.Width - border - space - labelWidth; // // Grid // int cntLabels = Math.Max((yBottom - yTop) / 20, 1); var delta = (float)Math.Max(Math.Round((max - min) / (float)cntLabels), 10); int step = (int)Math.Ceiling(delta / 10) * 10; cntLabels = (int)Math.Ceiling((max - min) / (float)step); max = min + cntLabels * step; float scaleY = (yBottom - yTop) / (cntLabels * (float)step); Brush brushFore = new SolidBrush(LayoutColors.ColorChartFore); var penGrid = new Pen(LayoutColors.ColorChartGrid) { DashStyle = DashStyle.Dash, DashPattern = new float[] { 4, 2 } }; // Price labels for (int label = min; label <= max; label += step) { var labelY = (int)(yBottom - (label - min) * scaleY); g.DrawString(label.ToString(CultureInfo.InvariantCulture), Font, brushFore, xRight, labelY - Font.Height / 2 - 1); g.DrawLine(penGrid, border + space, labelY, xRight, labelY); } float fScaleX = (xRight - 2 * space - border) / (float)bars; if (_isRandom) { // Draws the random area and Min Max lines var apntMinRandom = new PointF[bars]; var apntMaxRandom = new PointF[bars]; for (int iBar = 0; iBar < bars; iBar++) { apntMinRandom[iBar].X = border + space + iBar * fScaleX; apntMinRandom[iBar].Y = yBottom - (_afMinRandom[iBar] - min) * scaleY; apntMaxRandom[iBar].X = border + space + iBar * fScaleX; apntMaxRandom[iBar].Y = yBottom - (_afMaxRandom[iBar] - min) * scaleY; } apntMinRandom[0].Y = apntMaxRandom[0].Y; var path = new GraphicsPath(); path.AddLines(apntMinRandom); path.AddLine(apntMinRandom[bars - 1], apntMaxRandom[bars - 1]); path.AddLines(apntMaxRandom); var region = new Region(path); g.FillRegion(_brushRandArea, region); g.DrawLines(_penRandBands, apntMinRandom); g.DrawLines(_penRandBands, apntMaxRandom); } // Draws the lines for (int m = 0; m < _countMethods; m++) { if (!AchboxMethods[m].Checked) { continue; } var apntLines = new PointF[bars]; for (int iBar = 0; iBar < bars; iBar++) { apntLines[iBar].X = border + space + iBar * fScaleX; apntLines[iBar].Y = yBottom - (_afMethods[m, iBar] - min) * scaleY; } var pen = new Pen(LayoutColors.ColorSignalRed); switch ((InterpolationMethod)AchboxMethods[m].Tag) { case InterpolationMethod.Pessimistic: pen = _penPessimistic; break; case InterpolationMethod.Shortest: pen = _penShortest; break; case InterpolationMethod.Nearest: pen = _penNearest; break; case InterpolationMethod.Optimistic: pen = _penOptimistic; break; case InterpolationMethod.Random: pen = _penRandom; break; } g.DrawLines(pen, apntLines); } // Draws the average balance var apntBalance = new PointF[bars]; for (int bar = 0; bar < bars; bar++) { apntBalance[bar].X = border + space + bar * fScaleX; apntBalance[bar].Y = yBottom - (_afBalance[bar] - min) * scaleY; } g.DrawLines(_penBalance, apntBalance); // Coordinate axes g.DrawLine(new Pen(LayoutColors.ColorChartFore), border + space - 1, yTop - space, border + space - 1, yBottom); g.DrawLine(new Pen(LayoutColors.ColorChartFore), border + space, yBottom, xRight, yBottom); // Balance label float fBalanceY = yBottom - (_afBalance[bars - 1] - min) * scaleY; g.DrawLine(new Pen(LayoutColors.ColorChartCross), border + space, fBalanceY, xRight - space, fBalanceY); var szBalance = new Size(labelWidth + space, Font.Height + 2); var point = new Point(xRight - space + 2, (int)(fBalanceY - Font.Height / 2.0 - 1)); var rec = new Rectangle(point, szBalance); string sBalance = ((int)_afBalance[bars - 1]).ToString(CultureInfo.InvariantCulture); g.FillRectangle(new SolidBrush(LayoutColors.ColorLabelBack), rec); g.DrawRectangle(new Pen(LayoutColors.ColorChartCross), rec); g.DrawString(sBalance, Font, new SolidBrush(LayoutColors.ColorLabelText), rec, stringFormatCaption); // Scanning note var fontNote = new Font(Font.FontFamily, Font.Size - 1); if (Configs.Autoscan && !Data.IsIntrabarData) { g.DrawString(Language.T("Load intrabar data"), fontNote, Brushes.Red, border + space, fCaptionHeight - 2); } else if (Backtester.IsScanPerformed) { g.DrawString(Language.T("Scanned") + " MQ " + Data.ModellingQuality.ToString("N2") + "%", fontNote, Brushes.LimeGreen, border + space, fCaptionHeight - 2); } // Scanned bars if (Data.IntraBars != null && Data.IsIntrabarData && Backtester.IsScanPerformed) { g.DrawLine(new Pen(LayoutColors.ColorChartFore), border + space - 1, yBottom, border + space - 1, yBottom + 8); DataPeriods dataPeriod = Data.Period; Color color = Data.PeriodColor[Data.Period]; int iFromBar = Data.FirstBar; for (int bar = Data.FirstBar; bar < Data.Bars; bar++) { if (Data.IntraBarsPeriods[bar] != dataPeriod || bar == Data.Bars - 1) { int xStart = (int)((iFromBar - Data.FirstBar) * fScaleX) + border + space; int xEnd = (int)((bar - Data.FirstBar) * fScaleX) + border + space; iFromBar = bar; dataPeriod = Data.IntraBarsPeriods[bar]; Data.GradientPaint(g, new RectangleF(xStart, yBottom + 3, xEnd - xStart + 2, 5), color, 60); color = Data.PeriodColor[Data.IntraBarsPeriods[bar]]; } } } }
/// <summary> /// Calculates the indicator's components /// </summary> public override void Calculate(SlotTypes slotType) { double dAFMin = IndParam.NumParam[0].Value; double dAFInc = IndParam.NumParam[1].Value; double dAFMax = IndParam.NumParam[2].Value; // Reading the parameters int intDirNew; double dAF; double dPExtr; double dPSARNew = 0; int[] aiDir = new int[Bars]; double[] adPSAR = new double[Bars]; // Convert to Higher Time Frame --------------------------------------------- DataPeriods htfPeriod = DataPeriods.week; double[] hfOpen = new double[Bars]; double[] hfClose = new double[Bars]; double[] hfHigh = new double[Bars]; double[] hfLow = new double[Bars]; double[] hfVolume = new double[Bars]; double[] hfPrice = new double[Bars]; int[] hIndex = new int[Bars]; int iFrame; int hBars; switch (IndParam.ListParam[1].Index) { case 1: htfPeriod = DataPeriods.min5; break; case 2: htfPeriod = DataPeriods.min15; break; case 3: htfPeriod = DataPeriods.min30; break; case 4: htfPeriod = DataPeriods.hour1; break; case 5: htfPeriod = DataPeriods.hour4; break; case 6: htfPeriod = DataPeriods.day; break; case 7: htfPeriod = DataPeriods.week; break; } int err1 = HigherTimeFrame(Period, htfPeriod, out hIndex, out hBars, out iFrame, out hfHigh, out hfLow, out hfOpen, out hfClose, out hfVolume); if (err1 == 1) { return; } //------------------------------------------------------------------------ //---- Calculating the initial values // ---- for WTF version: change Open-High-Low-Close to hfOpen-hfHigh-hfLow-hfClose adPSAR[0] = 0; dAF = dAFMin; intDirNew = 0; int iFirstBar = 0; // get first non-zero value -- first bars could be 0's from WTF conversion while (hfOpen[iFirstBar] == 0) { iFirstBar++; } if (hfClose[iFirstBar + 1] > hfOpen[iFirstBar]) { aiDir[iFirstBar] = 1; aiDir[iFirstBar + 1] = 1; dPExtr = Math.Max(hfHigh[iFirstBar], hfHigh[iFirstBar + 1]); adPSAR[iFirstBar + 1] = Math.Min(hfLow[iFirstBar], hfLow[iFirstBar + 1]); } else { aiDir[iFirstBar] = -1; aiDir[iFirstBar + 1] = -1; dPExtr = Math.Min(hfLow[iFirstBar], hfLow[iFirstBar + 1]); adPSAR[iFirstBar + 1] = Math.Max(hfHigh[iFirstBar], hfHigh[iFirstBar + 1]); } iFirstBar += 2; // set max to hBars, no need to iterate through extra empty values for (int iBar = iFirstBar; iBar < hBars; iBar++) { //---- PSAR for the current period if (intDirNew != 0) { // The direction was changed during the last period aiDir[iBar] = intDirNew; intDirNew = 0; adPSAR[iBar] = dPSARNew + dAF * (dPExtr - dPSARNew); } else { aiDir[iBar] = aiDir[iBar - 1]; adPSAR[iBar] = adPSAR[iBar - 1] + dAF * (dPExtr - adPSAR[iBar - 1]); } // PSAR has to be out of the previous two bars limits if (aiDir[iBar] > 0 && adPSAR[iBar] > Math.Min(hfLow[iBar - 1], hfLow[iBar - 2])) { adPSAR[iBar] = Math.Min(hfLow[iBar - 1], hfLow[iBar - 2]); } else if (aiDir[iBar] < 0 && adPSAR[iBar] < Math.Max(hfHigh[iBar - 1], hfHigh[iBar - 2])) { adPSAR[iBar] = Math.Max(hfHigh[iBar - 1], hfHigh[iBar - 2]); } //---- PSAR for the next period // Calculation of the new values of flPExtr and flAF // if there is a new extreme price in the PSAR direction if (aiDir[iBar] > 0 && hfHigh[iBar] > dPExtr) { dPExtr = hfHigh[iBar]; dAF = Math.Min(dAF + dAFInc, dAFMax); } if (aiDir[iBar] < 0 && hfLow[iBar] < dPExtr) { dPExtr = hfLow[iBar]; dAF = Math.Min(dAF + dAFInc, dAFMax); } // Wheather the price reaches PSAR if (hfLow[iBar] <= adPSAR[iBar] && adPSAR[iBar] <= hfHigh[iBar]) { intDirNew = -aiDir[iBar]; dPSARNew = dPExtr; dAF = dAFMin; if (intDirNew > 0) { dPExtr = hfHigh[iBar]; } else { dPExtr = hfLow[iBar]; } } } // Convert to Current Time Frame ---------------------------------------------- /// start WTF modfication 2 beta 2 iFirstBar = iFirstBar * iFrame; if (iFirstBar > 0.25 * Bars) { return; } int err3 = CurrentTimeFrame(hIndex, hBars, ref adPSAR); /// end WTF modfication 2 beta 2 // Saving the components Component = new IndicatorComp[1]; Component[0] = new IndicatorComp(); Component[0].CompName = "PSAR value (WTF)"; if (IndParam.ListParam[0].Text == "Draw only, no entry or exit") { Component[0].DataType = IndComponentType.NotDefined; } else if (slotType == SlotTypes.Close) { Component[0].DataType = IndComponentType.ClosePrice; } else if (slotType == SlotTypes.OpenFilter) { Component[0].DataType = IndComponentType.IndicatorValue; Component[0].PosPriceDependence = PositionPriceDependence.BuyHigherSellLower; } Component[0].ChartType = IndChartType.Dot; Component[0].ChartColor = Color.FromName(IndParam.ListParam[2].ItemList[IndParam.ListParam[2].Index]); Component[0].FirstBar = iFirstBar; Component[0].Value = adPSAR; /// start WTF modfication 3 beta 2 // this wtf block not needed since not separated chart, does not have binary allow/disallow component value // including comment so numbering remains in order /// end WTF modfication 3 beta 2 return; }
/// <summary> /// Loads the Intrabar data. /// </summary> private int LoadIntrabarData(DataPeriods period) { var instrument = new Instrument(Data.InstrProperties.Clone(), (int) period) { DataDir = Data.OfflineDataDir, MaxBars = Configs.MaxIntraBars }; // Loads the data int loadingResult = instrument.LoadData(); int loadedIntrabars = instrument.Bars; if (loadingResult == 0 && loadedIntrabars > 0) { if (Data.Period != DataPeriods.week) { if (instrument.DaysOff > 5) _warningMessage += Environment.NewLine + Language.T("Data for:") + " " + Data.Symbol + " " + Data.DataPeriodToString(period) + " - " + Language.T("Maximum days off:") + " " + instrument.DaysOff; if (Data.Update - instrument.Update > new TimeSpan(24, 0, 0)) _warningMessage += Environment.NewLine + Language.T("Data for:") + " " + Data.Symbol + " " + Data.DataPeriodToString(period) + " - " + Language.T("Updated on:") + " " + instrument.Update.ToString(CultureInfo.InvariantCulture); } int startBigBar; for (startBigBar = 0; startBigBar < Data.Bars; startBigBar++) if (Data.Time[startBigBar] >= instrument.Time(0)) break; int stopBigBar; for (stopBigBar = startBigBar; stopBigBar < Data.Bars; stopBigBar++) if (Data.IntraBarsPeriods[stopBigBar] != Data.Period) break; // Seek for a place to put the intrabars. int lastIntraBar = 0; for (int bar = startBigBar; bar < stopBigBar; bar++) { Data.IntraBarData[bar] = new Bar[(int) Data.Period/(int) period]; DateTime endTime = Data.Time[bar] + new TimeSpan(0, (int) Data.Period, 0); int indexBar = 0; for (int intrabar = lastIntraBar; intrabar < loadedIntrabars && instrument.Time(intrabar) < endTime; intrabar++) { if (instrument.Time(intrabar) >= Data.Time[bar]) { Data.IntraBarData[bar][indexBar].Time = instrument.Time(intrabar); Data.IntraBarData[bar][indexBar].Open = instrument.Open(intrabar); Data.IntraBarData[bar][indexBar].High = instrument.High(intrabar); Data.IntraBarData[bar][indexBar].Low = instrument.Low(intrabar); Data.IntraBarData[bar][indexBar].Close = instrument.Close(intrabar); Data.IntraBarsPeriods[bar] = period; Data.IntraBarBars[bar]++; indexBar++; lastIntraBar = intrabar; } } } } return loadedIntrabars; }