Multi Time Frame Indicators

I am trying to create multi time frame indicators.

My results do not look correct.

Printout in debugView is rather strange. After the initial step before any timeframe compression the value for Close and MACD are correct. After the first compression values for Close and MACD seem strange. Value for close is essentially a constant. The resulting indicator therefor is almost identical for all symbols.

Attached my code and Debug View printout for 1st symbol. Other symbols have the same pattern of a constant value for Close.

Appriciate all help.

If anyone is using this technique for trading, I would like to communicate with you for strategies.

//File: Create MT Indicators
//
//version 1.0
//June 3, 2025
//
//
Pgm_name	= "MTF Composite Indicators";
//
//This program reads the components of of a given list and generates MTF MACD and saves it in ATC
//As a second step, It combines all the individual MTF MACD equity indicators for all the symbols in the index
// -------------------------------------------------------------------------------------------------------------------------------------
//
// Source List:
// - Multiple - See list below
//
//Target ATCs:
// - Indivudual symbols: "~MT_MACD"  + symbol","C")
// - Composite Indicator:"~SMT_MACD" + WL Name", "C") 
//
//
//
// ===================================================================================================================================
// ===================================================================================================================================
//
//
//
//
#pragma maxthreads 1    // May be necessary to limit threads so AB sends data to Debug View at a slower pace.
/*
AB = CreateObject("Broker.Application");
doc = AB.ActiveDocument;
doc.Interval = in1minute; 
*/
//
bi					= BarIndex();
ai					= bi - bi[0];
//
//
//
//
// ========================================================================================================================================
// ========================================================================================================================================
//                                    Process Data from All Markets List and add to the various target Lists
// ========================================================================================================================================
// ========================================================================================================================================
//
// Process program
_trace( "MTF-A1 symbol - Start program");
        // The loop identifies Watch List number, adds symbol to list.
    


   
    SourceListName 	= "AK-HighPriced-Issues";										// Watclist 
    SourceListNum  	= CategoryFind( SourceListName, CategoryWatchlist );			// Get List Number
    SourceList		= CategoryGetSymbols( Categorywatchlist, SourceListNum, 0 ) ;	// Source List of symbols
    Num_Symbols		=  StrCount( sourceList, "," ) + 1;
    _trace( "MTF-B1 status " + writeval(status("action"),1.0) +  "  List_Num  " + Writeval( SourceListNum, 1.0 )  + "  Source_Name  "
            + SourceListName  + "  numsymbols " + Writeval( Num_Symbols, 1.0 ) + "  Source_List  " + StrLeft(SourceList,50));

    // Extraxt symbol and process in multi Time Frame
    for( j = 0; ( sym = StrExtract( SourceList, j ) ) != ""; j++ )
    {
        //
        _trace( "MTF-B2 - j " + writeval(j,1.0) + "  symbol " + sym);
        // Control Time Frame - Loop through chosen time frames
        MDresult	= 0;
        MDCount		= 0;
        SymMD		= 0;
        SetForeign( sym );
         _trace( "MTF-B3 status " + writeval(status("action"),1.0) + "  - symbol " + sym + "  close " + writeval( lastvalue(close), 1.2));
        //
		// Calculate MACD at multiple time Frames
        for( jj = 1; jj <= 301; jj = jj + 5 )
        //for( jj = 1; jj <= 301; jj++ )
        {
            TimeFrameSet( jj * in1Minute );
            // MACD Parameters
            Close_val= Close;					// Placed here as a diagnostic
            MACD1	= MACD( 12, 26 );
            _trace( "MTF-B41 status " + writeval(status("action"),1.0) + "  - symbol " + sym + "  jj " + writeval( jj, 1, 0 )+ "  close " + writeval( lastvalue(Close_val), 1.2) + "  MACD1 " + writeval( lastvalue(MACD1), 1.2));
            Timeframerestore();
            //
            _trace( "MTF-B42 - status " + writeval(status("action"),1.0) + "  symbol " + sym + "  jj " + writeval( jj, 1, 0 )+ "  close " + writeval( lastvalue(Close_val), 1.2) + "  MACD1 " + writeval( lastvalue(MACD1), 1.2));
            // 
            X = IIf( TimeFrameExpand( MACD1, jj * in1Minute ) > 0, 1, -1 ); 
            CV= TimeFrameExpand( Close, jj * in1Minute );							// Used as a diagnostic
			MDresult = MDresult + X; 
			MDCount++; 
            //            
            _trace( "MTF-B43 - status " + writeval(status("action"),1.0) + "  symbol " + sym + "  jj " + writeval( jj, 1, 0 )  + "  close " + writeval( lastvalue(CV), 1.1)   + "  MACD1 " + writeval( lastvalue(MACD1), 1.2) + "  MD Count " 
				+ writeval( MDcount, 1.2) + "  MDresult " + writeval( MDresult, 1.2 )+ "  MTMACD " + writeval( MDresult / MDcount, 1.2 ));
            //
            //
        } // end jj loop
        //
        RestorePriceArrays();
        //
        _trace( "MTF-B5 - status " + writeval(status("action"),1.0) + "  symbol " + sym + "  j " + writeval( j, 1, 0 )  + "  Count " + writeval( lastvalue(MDcount), 1.2 ) 
				+ "  Result " + writeval( lastvalue(MDresult), 1.2 ) + "  MACD Composit " + writeval( lastvalue(MDresult / MDcount), 1.2 ));
        // Single Issue MT-MACD
        AddtoComposite( MDresult / MDcount, "~MTMACD-" + sym, "C", atcFlagDefaults );
        //AddtoComposite( MDresult / MDcount, "~MTMACD-" + sym, "C", atcFlagDefaults );
      //  
      // Create sum of single issue MTMAACD to create multi Issue MT-MACD (SMTMACD)
        //SymMD	= SymMD + MDresult;
      // 
    } // end j loop
    //
    // Multiple Issue STMACD for ETFs
    SymMD	= SymMD + MDresult;
    AddtoComposite( SymMD / Num_Symbols, "~SMTMACD-" + SourceListName, "C", atcFlagDefaults );
    //
	_trace( "MTF-B6 - end list " + SourceListName  + "  SymMD " + writeval( lastvalue(SymMD), 1.0 ) + "  Num symbols " + writeval( Num_Symbols, 1.0 ));
  // ===================================================================================================================" );
//
    Buy = Sell = 0;
//

Your trace statements all use LastValue(), so it stands to reason that the value of "close" would not change. But you don't just use the built-in Close variable, you also use Close_val which is assigned inside a TimeFrameSet()/TimeFrameRestore() block and at B43 you print CV, which is an expanded version of the Close array, but since you're already back in your base timeframe at that point in the code, you probably shouldn't be using TimeFrameExpand() on a built-in price variable like Close.

You might find it helpful to output your intermediate data as an Exploration instead of trying to use _Trace. That way you could see the values on each bar. Alternatively, become familiar with the interactive debugger so that you can look at the contents of arrays as the code executes.

mradtke, thanks for your response

I do understand that because I am using last values, all the last values could be the same, since the last value does not change.

What does not make sense to me is why the first set of values of B41 and B42 (Base time frame of 1 minute, so no real compression) the values of close_val are correct at 294.78. The value of B43, after expanding array was incorrect at 205.1. I corrected the B43 print such that CV = last value of expanded Clase_Val (was close before and B43 now print almost same value as B41 and B42 (reasonable number after expansion)

Still, I do not understand when the compressed and expanded values after compression factor is greater than 1, (every other set of B41, B42 and B43) do not have similar values as the original base time frame of 1 minute, since I am using Last Values for all situations.

I am obviously missing something, but can not see what.

It seems like the time frame compression and expansion should not change the last value of the array, at least not significantly.

It depends on compression/expansion mode. For example if default expandLast is used then week "last" close is available starting from Friday, not from monday, to avoid future leaks. This Friday close is kept for next Monday to Thursday . This way the "last" value of the week is not the "last" value of daily array.

To get better understanding of what is happening in your code and how functions work, use advice given here: How do I debug my formula?

And @mradtke is right, after TimeFrameRestore OHLC arrays are already expanded and doing expand again is a mistake and error, so this line is wrong:

CV= TimeFrameExpand( Close, jj * in1Minute );		 // WRONG must not expand Close after TimeFrameRestore

Another thing is described in the Knowledge base.

In short, if you want to compress data from foreign symbol you must do TWO things in sequence:

  1. SetForeign()
  2. TimeFrameSet()

ALWAYS.

You need to understand that TimeFrameRestore is a SYNONYM (essentially the same function) as RestorePriceArrays and RESTORES BOTH original symbol and original timeframe.

So you have to do do ALWAYS BOTH SetForeign and TimeFrameSet to access timeframe data
of foreign symbol after you did RestorePriceArrays or TimeFrameRestore.

1 Like

Problem solved

I had to reposition the SetForegn() inside the loop and TimeFrameRestore() command to end of loop.