# NEOTICKER DATA BEGIN ScriptType=Indicator Description=Time Distribution Analysis Name=TimeDistribution Language=DelphiScript Links=1 MinBars=0 TimerInterval=100 MetaStyle=Normal ValueRange=Same as Source Placement=Smart Multiplot_num_plots=1 Multiplot_color_0=255 Multiplot_style_0=Line Multiplot_width_0=1 Multiplot_enabled_0=1 Multiplot_breakstyle_0=0 UpdateByTick=0 TradingSystemUI=0 PrimaryLinkOnly=0 NotifyOnRemoval=0 Param_count=6 Param_name_0=Setup Condition Param_inuse_0=1 Param_type_0=formula Param_default_0=h > prevDHigh (data1) Param_name_1=Target Condition Param_inuse_1=1 Param_type_1=formula Param_default_1=h > prevDHigh (data1) + 2 Param_name_2=Intraday Only Param_inuse_2=1 Param_type_2=string Param_default_2=Y|N Param_name_3=Max Slots Param_inuse_3=1 Param_type_3=integer.gt.0 Param_default_3=100 Param_name_4=Bars Per Slot Param_inuse_4=1 Param_type_4=integer.gt.1 Param_default_4=5 Param_name_5=Report Window Param_inuse_5=1 Param_type_5=string Explanation_Lines=0 # NEOTICKER DATA END { Time Distribution Analysis written by Lawrence Chan Copyright (c) 2006 TickQuest Inc. All Rights Reserved Links 1 - price series A demonstration of - using the Heap object - using the Report object - using NTLib.format method - how to execute a part of the indicator only once, at the end of recalculation } const heap_items = 6; heap_intraday = 0; heap_setup_ready = 1; heap_done_for_day = 2; heap_report_done = 3; heap_setup_count = 4; heap_days_count = 5; ind_setup = 'setup'; ind_target = 'target'; function TimeDistribution : double; var setup_fml, target_fml; slots, slot_intraday, slot_setupready, slot_doneforday, slot_reportdone, slot_setupcount, slot_dayscount : integer; slots_since_ready, total_occurrence, total_target, slot_count, bars_since_ready : integer; table_name, s, u : string; i, j : integer; current_pct, total_pct : double; begin // generate the nested indicators with itself do begin setup_fml := updateindicator (ind_setup); if setup_fml = nil then setup_fml := makeindicator (ind_setup, 'fml', ['1'], [param1.str]); target_fml := updateindicator (ind_target); if target_fml = nil then target_fml := makeindicator (ind_target, 'fml', ['1'], [param2.str]); end; // give names to the heap slots so that we can work with them easier slots := param4.int; slot_intraday := slots + heap_intraday; slot_setupready := slots + heap_setup_ready; slot_doneforday := slots + heap_done_for_day; slot_reportdone := slots + heap_report_done; slot_setupcount := slots + heap_setup_count; slot_dayscount := slots + heap_days_count; // initialize the heap if necessary if heap.size = 0 then begin heap.allocate (slots + heap_items); heap.fill (0, slots + heap_items - 1, 0); if param3.str = 'Y' then heap.value [slot_intraday] := 1; // when we start the calculation, that is the first day heap.value [slot_dayscount] := 1; end; // special intraday consideration // it has to be done here, before we shortcut the indicator if data1.date [0] <> data1.date [1] then // reset intraday flag on a new day begin heap.value [slot_doneforday] := 0; // start fresh on data collection if heap.value [slot_intraday] <> 0 then // if we are collecting intraday stat heap.value [slot_setupready] := 0; // lets wait for a new signal heap.inc (slot_dayscount); // update # of days encountered end; // shortcut the indicator if our data is not a valid bar if not data1.valid [0] then begin itself.success := false; exit; end; // normally we return the close of the bar as our indicator value result := Data1.Value [0]; // if we have done the reporting once, we will skip the data // collection process if heap.value [slot_reportdone] <> 0 then exit; // if we are working with intraday data collection, we will // stop data collection when we have already collected the information if (heap.value [slot_intraday] <> 0) and (heap.value [slot_doneforday] <> 0) then exit; // collect statistic here if heap.value [slot_setupready] = 0 then // if we have not encounter our setup signal begin if setup_fml.value [0] > 0 then // check if we encounter one now begin heap.value [slot_setupready] := data1.barsnum [0]; // save the bar # heap.inc (slot_setupcount); // keep track of the # of setup encountered end; end else if target_fml.value [0] > 0 then // when we finally fulfill the target criteria begin bars_since_ready := data1.barsnum [0] - heap.value [slot_setupready]; slots_since_ready := NTLib.round (bars_since_ready / param5.int); if slots_since_ready < slots then heap.inc (slots_since_ready) else heap.inc (slots - 1); if heap.value [slot_intraday] = 0 then // daily - reset for next pattern heap.value [slot_setupready] := 0 else heap.value [slot_doneforday] := 1; // we will stop data collection and wait for next day end; // the condition data1.islastbar is true when an indicator is working on // its last bar of recalculation, or, when it is updated by tick in real-time. // in our case here, it is always encountered in the last bar of recalc // because we use heap.value [slot_reportdone] to control the // flow of the script if data1.islastbar then begin heap.value [slot_reportdone] := 1; // output table table_name := param6.str; total_target := heap.sum (0, slots - 1); // add up the values in slot 0 to slots - 1 total_occurrence := heap.value [slot_setupcount]; report.addline (table_name, 'Time Distribution Analysis'); report.addline (table_name, 'Symbol - ' + Data1.Symbol); report.addline (table_name, 'Setup - ' + param1.str); report.addline (table_name, 'Target - ' + param2.str); report.addline (table_name, 'Days - ' + NTLib.integer2str (heap.value [slot_dayscount])); report.addline (table_name, 'Total - ' + NTLib.integer2str (total_target) + ' / ' + NTLib.integer2str (total_occurrence) + NTLib.Format (' (%6.1f%%)', [total_target / total_occurrence * 100])); // column headings report.addline (table_name, ''); report.addline (table_name, NTLib.format ('%6s (%7s) (%7s) %s', ['Bars', 'Pct', 'AccPct', 'Histogram'])); total_pct := 0; for i := 0 to slots - 1 do begin slot_count := heap.value [i]; current_pct := slot_count / total_occurrence * 100; total_pct := total_pct + current_pct; s := NTLib.format ( '%6d (%6.1f%%) (%6.1f%%) ', [(i + 1)* param5.int, current_pct, total_pct]); u := ''; for j := 0 to slot_count do u := u + '*'; report.addline (table_name, s + u); end; end; end;