Heartbeat Pricing with 24 Hour In-Record Tracking

A randomized process adjusts pricing for a list of items, while maintaining a previous 24 hour Price Tracking log directly in each record.   The 24 Hour Price Tracking column for the current hour UTC is highlighted in green.   The column highlighted in red represents the trailing edge of the previous 24 hours, and holds the value that is used to calculate the 24 Hour % Change.   Any column highlighted in yellow represents the last recorded Heartbeat Pricing Change hour, only when it doesn't overlap with the other highlighted columns.  

This page uses Conditional Range Loops to implement the following Gap Correction logic:  When the last recorded Heartbeat Pricing Change was not done in the current hour, or the hour directly before the current hour, the price recorded for that last change will be applied to every hour up until the current hour.  

Item Name Current Price 24 Hour % Change 24 Hour Price Tracking
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Item 1 24.04 - 0.58 % 24.18 24.18 24.18 24.18 24.18 24.18 24.18 24.18 24.18 24.18 24.18 24.18 24.18 24.16 24.16 24.16 24.16 24.16 24.16 24.16 24.16 24.04 24.18 24.18
Item 2 24.74 + 0.18 % 24.70 24.70 24.70 24.70 24.70 24.70 24.70 24.70 24.70 24.70 24.70 24.70 24.70 24.72 24.72 24.72 24.72 24.72 24.72 24.72 24.72 24.74 24.70 24.70
Item 3 26.11 - 0.10 % 26.14 26.14 26.14 26.14 26.14 26.14 26.14 26.14 26.14 26.14 26.14 26.14 26.14 26.17 26.14 26.14 26.14 26.14 26.14 26.14 26.14 26.11 26.14 26.14
Item 4 26.52 + 0.23 % 26.46 26.46 26.46 26.46 26.46 26.46 26.46 26.46 26.46 26.46 26.46 26.46 26.46 26.49 26.52 26.52 26.52 26.52 26.52 26.52 26.52 26.52 26.46 26.46
Item 5 27.45 + 0.91 % 27.20 27.20 27.20 27.20 27.20 27.20 27.20 27.20 27.20 27.20 27.20 27.20 27.20 27.17 27.31 27.31 27.31 27.31 27.31 27.31 27.31 27.45 27.20 27.20
Item 6 28.88 + 0.49 % 28.74 28.74 28.74 28.74 28.74 28.74 28.74 28.74 28.74 28.74 28.74 28.74 28.74 28.77 28.91 28.91 28.91 28.91 28.91 28.91 28.91 28.88 28.74 28.74
Item 7 30.11 + 0.10 % 30.08 30.08 30.08 30.08 30.08 30.08 30.08 30.08 30.08 30.08 30.08 30.08 30.08 30.11 30.11 30.11 30.11 30.11 30.11 30.11 30.11 30.11 30.08 30.08
Item 9 31.36 - 0.50 % 31.52 31.52 31.52 31.52 31.52 31.52 31.52 31.52 31.52 31.52 31.52 31.52 31.52 31.49 31.33 31.33 31.33 31.33 31.33 31.33 31.33 31.36 31.52 31.52
Item 8 31.85 + 0.09 % 31.82 31.82 31.82 31.82 31.82 31.82 31.82 31.82 31.82 31.82 31.82 31.82 31.82 31.85 31.85 31.85 31.85 31.85 31.85 31.85 31.85 31.85 31.82 31.82
Item 10 32.54 + 0.25 % 32.46 32.46 32.46 32.46 32.46 32.46 32.46 32.46 32.46 32.46 32.46 32.46 32.46 32.43 32.51 32.51 32.51 32.51 32.51 32.51 32.51 32.54 32.46 32.46

Processed this Hashtag Markup:
<#
// load the last record for Heartbeat Time, then apply any overrides
apply heartbeat_time as "heartbeat" or redirect to "/heartbeat/purge";
if("<#[url.override_hour]#>"!="") {
	set heartbeat.hour to "<#[url.override_hour as integer]#>";
}
if("<#[url.override_date]#>"!="") {
	set heartbeat.date to "<#[url.override_date as date "Y-M-D"]#>";
}
// set time based values for % Change calculations and Gap Correction
set this_hour to <#[system.timestamp as date "H"]#>;
set prev_hour to (<#[this_hour]#> - 1) % 24; 
set next_hour to (<#[this_hour]#> + 1) % 24; 
set gap_days to <#[system.date as timestamp]#> - <#[heartbeat.date as timestamp]#> as timespan "d";
// set classes for highlighted columns
set hour_<#[heartbeat.hour]#>_background to "bg-warning";
set hour_<#[this_hour]#>_background to "bg-success";
set hour_<#[next_hour]#>_background to "bg-danger";
// process all Heartbeat Items to update all pricing values
start list for heartbeat_items;
	sort by price as numeric;
#>

<# start header #>
<div class="table-responsive">
<table class="table table-hover table-striped table-condensed small" id="heartbeat">
	<thead>
	<tr>
		<th rowspan="2">Item Name</th>
		<th rowspan="2" class="text-right">Current Price</th>
		<th rowspan="2" class="text-center">24 Hour <span class="text-nowrap">% Change</span></th>
		<th colspan="24">24 Hour Price Tracking</th>
	</tr>
	<tr>
		<th class="text-right <#[hour_0_background]#>">0</th>
		<th class="text-right <#[hour_1_background]#>">1</th>
		<th class="text-right <#[hour_2_background]#>">2</th>
		<th class="text-right <#[hour_3_background]#>">3</th>
		<th class="text-right <#[hour_4_background]#>">4</th>
		<th class="text-right <#[hour_5_background]#>">5</th>
		<th class="text-right <#[hour_6_background]#>">6</th>
		<th class="text-right <#[hour_7_background]#>">7</th>
		<th class="text-right <#[hour_8_background]#>">8</th>
		<th class="text-right <#[hour_9_background]#>">9</th>
		<th class="text-right <#[hour_10_background]#>">10</th>
		<th class="text-right <#[hour_11_background]#>">11</th>
		<th class="text-right <#[hour_12_background]#>">12</th>
		<th class="text-right <#[hour_13_background]#>">13</th>
		<th class="text-right <#[hour_14_background]#>">14</th>
		<th class="text-right <#[hour_15_background]#>">15</th>
		<th class="text-right <#[hour_16_background]#>">16</th>
		<th class="text-right <#[hour_17_background]#>">17</th>
		<th class="text-right <#[hour_18_background]#>">18</th>
		<th class="text-right <#[hour_19_background]#>">19</th>
		<th class="text-right <#[hour_20_background]#>">20</th>
		<th class="text-right <#[hour_21_background]#>">21</th>
		<th class="text-right <#[hour_22_background]#>">22</th>
		<th class="text-right <#[hour_23_background]#>">23</th>
	</tr>
	</thead>
	<tbody>
<# end header #>

<# start row #>
	<#: Gap Correction Logic :#>
	<# if "<#[gap_days]#>"="0" and "<#[heartbeat.hour]#>" < "<#[prev_hour]#>" #>
		<# start loop <#[heartbeat.hour]#>+1..<#[prev_hour]#>; #>
			<# update record for "<# id #>"; 
				set hour_<#value#>_price to "<# hour_<#[heartbeat.hour]#>_price #>";
			#>
		<# end loop #>
	<# elseif "<#[gap_days]#>"="1" and not("<#[heartbeat.hour]#>"="23" and "<#[this_hour]#>"="0") #>
		<# start loop <#[heartbeat.hour]#>+1..23; #>
			<# update record for "<# id #>"; 
				set hour_<#value#>_price to "<# hour_<#[heartbeat.hour]#>_price #>";
			#>
		<# end loop #>
		<# start loop 0..<#[prev_hour]#>; #>
			<# update record for "<# id #>"; 
				set hour_<#value#>_price to "<# hour_<#[heartbeat.hour]#>_price #>";
			#>
		<# end loop #>
	<# elseif "<#[gap_days]#>" > "1" #>
		<# start loop <#[next_hour]#>..23; #>
			<# update record for "<# id #>"; 
				set hour_<#value#>_price to "<# hour_<#[heartbeat.hour]#>_price #>";
			#>
		<# end loop #>
		<# start loop 0..<#[prev_hour]#>; #>
			<# update record for "<# id #>"; 
				set hour_<#value#>_price to "<# hour_<#[heartbeat.hour]#>_price #>";
			#>
		<# end loop #>
	<# end if #>

	<#
	// randomly adjust pricing
	set new_price to "<# price #>";
	set change to random 0..100;
	if("<# change #>" < "3") {
		increment new_price by <# new_price #> * (.5 / 100);
	} elseif("<# change #>" < "6") {
		decrement new_price by <# new_price #> * (.5 / 100);
	} elseif("<# change #>" < "15") {
		increment new_price by <# new_price #> * (.25 / 100);
	} elseif("<# change #>" < "24") {
		decrement new_price by <# new_price #> * (.25 / 100);
	} elseif("<# change #>" < "49") {
		increment new_price by <# new_price #> * (.1 / 100);
	} elseif("<# change #>" < "74") {
		decrement new_price by <# new_price #> * (.1 / 100);
	}
	// never allow zero pricing
	if("<# new_price as cents #>"="0.00") {
		set new_price to "0.01";
	}
	// save new pricing
	update record for "<# id #>"; 
		set price to "<# new_price as cents #>";
		set hour_<#[this_hour]#>_price to "<# new_price as cents #>";
		set price_percent_change to (
			  (<#new_price#> - <#hour_<#[next_hour]#>_price#>) / <#hour_<#[next_hour]#>_price#>
			) * 100 as cents;
	#>
	<tr>
		<td class="text-nowrap"><# name as html #></td>
		<td class="text-right"><# price as cents #></td>
		<td class="text-nowrap"><# price_percent_change as changepercent #></td>
		<td class="text-right <#[hour_0_background]#>"><# hour_0_price #></td>
		<td class="text-right <#[hour_1_background]#>"><# hour_1_price #></td>
		<td class="text-right <#[hour_2_background]#>"><# hour_2_price #></td>
		<td class="text-right <#[hour_3_background]#>"><# hour_3_price #></td>
		<td class="text-right <#[hour_4_background]#>"><# hour_4_price #></td>
		<td class="text-right <#[hour_5_background]#>"><# hour_5_price #></td>
		<td class="text-right <#[hour_6_background]#>"><# hour_6_price #></td>
		<td class="text-right <#[hour_7_background]#>"><# hour_7_price #></td>
		<td class="text-right <#[hour_8_background]#>"><# hour_8_price #></td>
		<td class="text-right <#[hour_9_background]#>"><# hour_9_price #></td>
		<td class="text-right <#[hour_10_background]#>"><# hour_10_price #></td>
		<td class="text-right <#[hour_11_background]#>"><# hour_11_price #></td>
		<td class="text-right <#[hour_12_background]#>"><# hour_12_price #></td>
		<td class="text-right <#[hour_13_background]#>"><# hour_13_price #></td>
		<td class="text-right <#[hour_14_background]#>"><# hour_14_price #></td>
		<td class="text-right <#[hour_15_background]#>"><# hour_15_price #></td>
		<td class="text-right <#[hour_16_background]#>"><# hour_16_price #></td>
		<td class="text-right <#[hour_17_background]#>"><# hour_17_price #></td>
		<td class="text-right <#[hour_18_background]#>"><# hour_18_price #></td>
		<td class="text-right <#[hour_19_background]#>"><# hour_19_price #></td>
		<td class="text-right <#[hour_20_background]#>"><# hour_20_price #></td>
		<td class="text-right <#[hour_21_background]#>"><# hour_21_price #></td>
		<td class="text-right <#[hour_22_background]#>"><# hour_22_price #></td>
		<td class="text-right <#[hour_23_background]#>"><# hour_23_price #></td>
	</tr>
<# end row #>
	
<# start footer #>
	</tbody>
</table>
</div>
<# update record for "heartbeat_time.<#[heartbeat.id]#>"; 
	set hour to "<#[this_hour]#>";
	set date to "<#[system.date]#>";
#>
<# end footer #>

<# end list #>

Note:This process could be implemented in a much more normalized way by relating item records to intraday pricing records for every hour.   However, this page serves to demonstrate a solution using only a single Hashtag Markup List without related records.   To achieve this, many methods are demonstrated to dynamically inject Variable values into Hashtag Markup.   These techniques can be useful, however, Variable Buckets and Row Loops often provide more efficient solutions.  

This Form is provided to override the latest Pricing Change Heartbeat Time, allowing testing of the Gap Correction Logic.  

Override Heartbeat Time



The Heartbeat Pricing Mini-App demonstrates many methods of dynamically processing data using Hashtag Markup.

All records are stored in an SQL Database.