BoJ Set For Hawkish Hold With A December Hike In Play
/*jshint esversion: 6 */
var socket;
var assigned_server = 3001;
var distributor_server = 3010;
var publisher_channel = '';
var broadcaster_channel = '';
var remote_ip = '';
var session_info = {};
var logging_interval;
var logging_interval_time = 120000;
var socket_emits = 0;
var session_start_time;
var reconnectionDelayGrowFactor = 1.2;
var reconnection_delay = 1000;
var playing = false;
var connected_to_assigned = false;
var socket_close_timeout;
var player_disconnected_annoucement_play_delay = 1500;
var player_disconnected_annoucement_play_timeout = null;
const TOKEN_ENDPOINT = "https://www.livesquawk.com/api/get_token.php";
self.onmessage = function (msg) {
switch(msg.data.action) {
case 'Reactivate': reactivate(); break;
case 'ConnectDistributor': connect_to_distributor(msg); break;
case 'SessionStaticInfo': session_static_info(msg); break;
case 'SessionInfo': update_session_info(msg.data); break;
case 'PauseLogging': clearTimeout(logging_interval); break;
case 'RestartLogging': postMessage({action: 'RequestSessionStaticInfo' }); break;
case 'JoinPublisherChannel': join_publisher_channel(msg.data); break;
case 'JoinPlayerChannel': join_player_channel(msg.data); break;
case 'CheckChannelStatus': check_channel_status(msg.data); break;
case 'PlayerLogResponse': player_log_response(msg.data); break;
case 'CloseSocket': close_socket(); break;
case 'RequestMessageSearch': request_message_search(msg.data); break;
case 'RequestMoreMessages': request_more_messages(msg.data); break;
case 'PlayerDisconnectedAnnoucementTimeoutStart': player_disconnected_annoucement_timeout_start(); break;
case 'PlayerDisconnectedAnnoucementTimeoutClear': player_disconnected_annoucement_timeout_clear(); break;
case 'GetConnectionState': checkSocketConnectionState(); break;
}
};
function player_disconnected_annoucement_timeout_clear() {
clearTimeout(player_disconnected_annoucement_play_timeout);
player_disconnected_annoucement_play_timeout = null;
}
function player_disconnected_annoucement_timeout_start() {
player_disconnected_annoucement_play_timeout = setTimeout(function() { send_play_disconnect_annoucement(); }, player_disconnected_annoucement_play_delay );
}
function send_play_disconnect_annoucement() {
postMessage({action: "PlayDisconnectAnnoucement"});
}
function reactivate() {
playing = false;
connect_to_assigned_server();
}
function player_log_response(data) {
var data_array = {};
data_array.type = 'PlayerLogResponse';
data_array.respond_to_socket_final = data.respond_to_socket_final;
data_array.respond_to_socket = data.respond_to_socket;
data_array.player_socket_id = data.player_socket_id;
data_array.logs = data.logs;
var msg_string = JSON.stringify(data_array);
if (socket.readyState == 1) { socket.send(msg_string); }
}
function request_message_search(data) {
var data_array = {};
data_array.type = 'request_message_search';
data_array.publisher_channel = data.publisher_channel;
data_array.search_term = data.search_term;
var msg_string = JSON.stringify(data_array);
if (socket.readyState == 1) { socket.send(msg_string); }
}
function request_more_messages(data) {
var data_array = {};
data_array.type = 'request_more_messages';
data_array.publisher_channel = data.publisher_channel;
data_array.last_record_id = data.last_record_id;
var msg_string = JSON.stringify(data_array);
if (socket.readyState == 1) { socket.send(msg_string); }
}
function check_channel_status(data) {
var data_array = {};
data_array.type = 'check_channel_status';
data_array.app_name = data.app_name;
var msg_string = JSON.stringify(data_array);
if (socket.readyState == 1 && connected_to_assigned) { socket.send(msg_string); }
else { setTimeout(function() { check_channel_status(data); },500); }
}
function check_channel_status_response(data) {
postMessage({ action: 'CheckChannelStatusReponse', stream_status: data.stream_status.status, onair: data.stream_status.onair, connected: data.stream_status.connected });
}
async function join_publisher_channel(data) {
if (typeof data.jwt_token === 'string' && data.jwt_token !== '') {
if (!socket || socket.readyState !== WebSocket.OPEN) {
console.warn("[Page worker] JWT join skipped: socket not open");
return;
}
socket.send(JSON.stringify({
type: "join_publisher_channel",
jwt_token: data.jwt_token,
publisher_channel: data.publisher_channel,
username: data.username,
subscriber_group: data.subscriber_group,
display_name: data.display_name,
single_sign_on: data.single_sign_on,
remote_ip: data.remote_ip,
http_referrer: data.http_referrer,
current_page: data.current_page,
php_session_id: data.php_session_id,
from_react: data.from_react,
...(typeof data.api_key === "string" && data.api_key.trim() !== "" ? { api_key: data.api_key } : {}),
}));
console.log("[Page worker] Sent supplied JWT join");
postMessage({ action: 'PublisherChannelJoined' });
return;
}
const joinSocket = socket; if (!joinSocket || joinSocket.readyState !== WebSocket.OPEN) { return; }
const apiKey = typeof data.api_key === "string" ? data.api_key.trim() : "";
const partnerName = partnerFromCurrentPage(data.current_page);
let tokenBody;
if (apiKey !== "") { tokenBody = { api_key: apiKey }; }
else if (partnerName) { tokenBody = { partner_name: partnerName }; }
else { tokenBody = { username: data.username || "", publisher_channel: data.publisher_channel || "", }; }
let jwtToken = null;
try {
const requestStartedAt = Date.now();
const response = await fetch(TOKEN_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(tokenBody),
credentials: "same-origin",
cache: "no-store",
});
if (!response.ok) {
throw new Error(`token endpoint returned ${response.status}`);
}
const tokenData = await response.json();
if ( !tokenData || typeof tokenData.token !== "string" || tokenData.token === "" ) {
throw new Error("token endpoint returned no token");
}
const expiresIn = Number(tokenData.expires_in);
if (!Number.isFinite(expiresIn) || expiresIn <= 0) {
throw new Error("token endpoint returned an invalid lifetime");
}
const expiresAt = requestStartedAt + (expiresIn * 1000);
if (expiresAt <= Date.now() + 30000) {
throw new Error("token response has insufficient remaining lifetime");
}
jwtToken = tokenData.token;
}
catch (error) {
console.warn("[Page worker] Token request failed", error);
// API-key requests must not silently bypass token authentication.
if (apiKey !== "") { postMessage({ action: "auth_failed" }); return; }
}
// A reconnect during the fetch makes this join attempt obsolete.
if ( socket !== joinSocket || joinSocket.readyState !== WebSocket.OPEN ) { return; }
const payload = {
type: "join_publisher_channel",
publisher_channel: data.publisher_channel,
username: data.username,
subscriber_group: data.subscriber_group,
display_name: data.display_name,
single_sign_on: data.single_sign_on,
remote_ip: data.remote_ip,
http_referrer: data.http_referrer,
current_page: data.current_page,
php_session_id: data.php_session_id,
from_react: data.from_react,
};
if (apiKey !== "") { payload.api_key = apiKey; }
if (jwtToken) { payload.jwt_token = jwtToken; }
console.log( jwtToken ? "[Page worker] Sending fetched JWT with legacy details" : "[Page worker] Sending legacy join without JWT" );
joinSocket.send(JSON.stringify(payload));
postMessage({ action: "PublisherChannelJoined" });
}
function partnerFromCurrentPage(current_page) {
try {
if (!current_page) return '';
const fullUrl = current_page.startsWith('http') ? current_page : `https://${current_page}`;
return new URL(fullUrl).searchParams.get('partner_name') || '';
} catch (e) { return ''; }
}
function session_static_info(msg) {
set_static_session_info(msg.data);
start_log();
}
function connect_to_distributor(msg) {
publisher_channel = msg.data.publisher_channel;
remote_ip = msg.data.remote_ip;
socket = new WebSocket("wss://ws.livesquawk.com/ws"+distributor_server);
socket.onopen = function(event) { request_server_assignment(); };
socket.onmessage = function(event) {
var msg_string = event.data.toString();
var data = JSON.parse(msg_string);
switch(data.type) {
case 'server_assignment_response': server_assignment_response(data); break;
}
};
}
function session_info_interval() {
postMessage({action: 'RequestSessionInfo' });
logging_interval = setTimeout(session_info_interval,logging_interval_time);
}
function server_assignment_response(data) {
assigned_server = data.selected_server;
socket.close();
connect_to_assigned_server();
}
function request_server_assignment() {
var data_array = {};
data_array.type = 'request_server_assignment';
var msg_string = JSON.stringify(data_array);
if (socket.readyState == 1) { socket.send(msg_string); }
}
function connect_to_assigned_server() {
socket = new WebSocket("wss://ws.livesquawk.com/ws"+assigned_server);
socket.onopen = function(event) {
postMessage({ action: 'VisibleConsole',console_string: "Connected to server "+assigned_server });
console.log("Connected to server "+assigned_server);
postMessage({ action: 'ConnectedToAssigned' });
connected_to_assigned = true;
if (playing) {
postMessage({ action: 'RejoinPlayerChannel' });
}
};
socket.onmessage = function(event) {
var msg_string = event.data.toString();
var data = JSON.parse(msg_string);
if (data.type != 'server_ping') { /* console.log(data.type); */ }
switch(data.type) {
case 'reconnect': postMessage({ action: 'VisibleConsole',console_string: "Reconnected" }); break;
case 'reload': postMessage({ action: 'Reload' }); break;
case 'start_log_response': start_log_response(data); break;
case 'application_refresh_start': application_refresh_start(data); break;
case 'application_refresh_stop': application_refresh_stop(data); break;
case 'player_log_request':
case 'check_channel_status_response': check_channel_status_response(data); break;
case 'PlayerLogRequest':
case 'new_tweet':
case 'new_latest_news':
case 'delete_report':
case 'add_report':
case 'add_ref_doc':
case 'calendar_change':
case 'calendar_insert':
case 'calendar_delete':
case 'new_note':
case 'AppStart':
case 'AppStop':
case 'BroadcasterStarted':
case 'BroadcasterStopped':
case 'added_cme_report':
case 'updated_cme_report':
case 'added_cme_commentary':
case 'updated_cme_commentary':
case 'server_assignment_response':
case 'initial_messages':
case 'message_categories':
case 'more_messages':
case 'matched_messages':
pass_straight_to_post_message(data);
break;
case 'output':
case 'server_ping':
case 'reconnect':
case 'disconnect':
break;
}
};
socket.onerror = function(event) {
postMessage({ action: 'VisibleConsole',console_string: "LS Socket Error" + event.type });
console.log(event);
postMessage({ action: 'LSSocketConnectionError' });
};
socket.onclose = function(event) {
console.log('Socket is closed. Reconnect will be attempted in 1 second.', event.reason);
socket_close_timeout = setTimeout(connect_to_assigned_server, reconnection_delay);
reconnection_delay = reconnection_delay*reconnectionDelayGrowFactor;
connected_to_assigned = false;
};
}
function checkSocketConnectionState() {
postMessage({ action: 'SocketConnectionState', connected: Boolean(socket && socket.readyState === WebSocket.OPEN && connected_to_assigned ), });
}
function close_socket() {
clearTimeout(socket_close_timeout);
socket_close_timeout = null;
socket.onclose = function(event) {};
socket.onmessage = function(event) {};
socket.onerror = function(event) {};
socket.close(1000);
console.log('Socket Closed');
}
function pass_straight_to_post_message(data) {
data.action = data.type;
postMessage(data);
}
function join_player_channel(data) {
var data_array = {};
data_array.type = 'join_player_channel';
data_array.player_channel = data.player_channel;
data_array.remote_ip = data.remote_ip;
data_array.username = data.username;
data_array.app_name = data.app_name;
data_array.onair_status = data.onair_status;
data_array.http_referrer = data.http_referrer;
data_array.current_page = data.current_page;
data_array.php_session_id = data.php_session_id;
var msg_string = JSON.stringify(data_array);
if (socket.readyState == 1) { socket.send(msg_string); }
postMessage({action: 'PlayerChannelJoined' });
playing = true;
}
function start_log_response(data) {
session_info.session_id = data.log_record_id;
session_info_interval();
}
function application_refresh_start(data) {
if (data.app_name == session_info.application_name) { postMessage({action: 'ApplicationRefreshStart' }); }
}
function application_refresh_stop(data) {
if (data.app_name == session_info.application_name) { postMessage({action: 'ApplicationRefreshStop' }); }
}
function set_static_session_info(data) {
session_info.browser_codename = data.browser_codename;
session_info.browser_name = data.browser_name;
session_info.user_agent = data.user_agent;
session_info.browser_version = data.browser_version;
session_info.cookies_enabled = data.cookies_enabled;
session_info.platform = data.platform;
session_info.player_version = data.player_version;
session_info.stream = data.stream;
session_info.connection_protocol = data.protocol;
session_info.delay_target = data.delay_target;
session_info.session_email = data.session_email;
session_info.remote_ip = data.remote_ip;
session_info.php_session_id = data.php_session_id;
session_info.application_name = data.application_name;
session_info.http_referrer = data.http_referrer;
}
function start_log() {
var session_start_date = new Date();
session_start_time = session_start_date.getTime();
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var session_start_date_string = session_start_date.getDate() + " " + months[session_start_date.getMonth()] + " " + session_start_date.getFullYear();
var data_array = {};
data_array.type = 'webrtc_start_log';
data_array.remote_ip = session_info.remote_ip;
data_array.username = session_info.session_email;
data_array.php_session_id = session_info.php_session_id;
data_array.webrtc_protocol = '';
data_array.session_start_time = (session_start_time/1000).toFixed(0);
data_array.stream_name = session_info.stream;
data_array.session_start_date = session_start_date_string;
var msg_string = JSON.stringify(data_array);
if (socket.readyState == 1) { socket.send(msg_string); }
}
function update_session_info(data) {
var data_array = {};
var msg_string = '';
var current_date = new Date();
var current_time = current_date.getTime();
session_info.protocol = data.protocol;
session_info.curr_delay = (data.effective_latency / 1000).toFixed(2);
session_info.session_length = current_time - session_start_time;
session_info.ping_time = data.ping_time;
session_info.jitter = data.jitter;
session_info.packet_loss = data.packet_loss;
session_info.effective_latency = data.effective_latency;
session_info.mean_opinion_score = data.mean_opinion_score;
session_info.restarts = data.restarts;
if (socket_emits == 0) {
data_array = {};
data_array.type = 'webrtc_log_data_full';
data_array.connection_protocol = session_info.protocol;
data_array.threshold = 0;
data_array.curr_delay = session_info.curr_delay;
data_array.session_length = session_info.session_length;
data_array.date = current_time;
data_array.browser_codename = session_info.browser_codename;
data_array.browser_name = session_info.browser_name;
data_array.user_agent = session_info.user_agent;
data_array.browser_version = session_info.browser_version;
data_array.cookies_enabled = session_info.cookies_enabled;
data_array.platform = session_info.platform;
data_array.player_version = session_info.player_version;
data_array.stream = session_info.stream;
data_array.restarts = session_info.restarts;
data_array.delay_target = 0;
data_array.op_sys = '';
data_array.flash_version = '';
data_array.remote_ip = session_info.remote_ip;
data_array.http_referrer = session_info.http_referrer;
data_array.php_session_id = session_info.php_session_id;
data_array.user_email = session_info.session_email;
data_array.webrtc_protocol = session_info.protocol;
data_array.ping_time = session_info.ping_time;
data_array.jitter = session_info.jitter;
data_array.packet_loss = session_info.packet_loss;
data_array.effective_latency = session_info.effective_latency;
data_array.mean_opinion_score = session_info.mean_opinion_score;
data_array.session_id = session_info.session_id;
msg_string = JSON.stringify(data_array);
if (socket.readyState == 1) { socket.send(msg_string); }
}
else {
data_array = {};
data_array.type = 'webrtc_log_data';
data_array.session_id = session_info.session_id;
data_array.php_session_id = session_info.php_session_id;
data_array.connection_protocol = session_info.protocol;
data_array.restarts = session_info.restarts;
data_array.threshold = 0;
data_array.curr_delay = session_info.curr_delay;
data_array.session_length = session_info.session_length;
data_array.date = current_time;
data_array.webrtc_protocol = session_info.protocol;
data_array.ping_time = session_info.ping_time;
data_array.jitter = session_info.jitter;
data_array.packet_loss = session_info.packet_loss;
data_array.effective_latency = session_info.effective_latency;
data_array.mean_opinion_score = session_info.mean_opinion_score;
data_array.stream = session_info.stream;
msg_string = JSON.stringify(data_array);
if (socket.readyState == 1) { socket.send(msg_string); }
}
socket_emits++;
if (socket_emits == 100) { socket_emits = 0; }
}
- Inflation back above target as yen weakness adds pressure
- Wage gains support further tightening despite weak spending
- Ueda's guidance and updated forecasts take centre stage
- Markets favour December hike as BoJ weighs next move
- Rate decision due between approximately 03:00-05:00 GMT
- Press conference scheduled for 06:30 GMT
By Harry Daniels
LiveSquawk News
@HarryDaniels71
20:00 GMT | 29 October 2026
The idea that the Bank of Japan would enact a second hike in as many meetings has been given short shrift by central bank watchers. Nonetheless, experts expect a hawkish hold when the bank announces its decision on Friday.
The BoJ’s Policy Board is widely expected to leave its main interest rate unchanged at 1.25%, although persistent inflation and yen weakness have strengthened the case for further tightening.
Barclays expects an 8–1 vote, with board member Hajime Takata favouring a hike. The bank's economists believe policymakers may acknowledge that underlying inflation has broadly reached the BoJ's 2% target, while stressing the need to assess the impact of September's rate increase.
Wage growth and stronger business confidence support the case for tightening, although subdued consumption and capital expenditure warrant acknowledgement.
The Summary of Opinions from the September meeting noted a moderately recovering economy, supported by government measures and AI-related demand. It also estimated that underlying CPI inflation was gradually increasing and was expected to reach around 2% between the second half of fiscal 2026 and fiscal 2027, supported by rising wages and prices.
The national core CPI gauge accelerated to 2.1% y/y in September, exceeding the BoJ's 2% target for the first time in nine months. Underlying inflation excluding fresh food and energy rose to 2.4%.
There was an eighth consecutive rise in monthly real earnings in August, albeit the annual rate moderated. Regular pay rose 3.8% y/y, underpinning confidence in wage-driven inflation.
Strengthening wage growth, viewed alongside 8-year highs for business confidence, further bolstered those policymakers urging bolder action.
Bank staff are set to update economic projections, with Barclays expecting only modest revisions to the BoJ's quarterly projections, with FY2026 inflation revised lower and FY2027 higher.
Communication since the last meeting reinforces the bank’s hawkish tone.
Speaking on 6 October, Governor Kazuo Ueda stated that anchoring underlying inflation around the 2% target had become increasingly important. He cautioned that higher raw material costs were feeding through to consumer prices, while longer-term inflation expectations continued to rise.
ING’s global head of markets, Chris Turner, noted that investors have priced in an 80% chance of a 25-basis-point rate hike in December, followed by another 50 bps by next September.
“While government representatives may well want the BoJ to go slow with its tightening, the case against the BoJ taking rates up to the 1.75-2.00% area is a weak one. Here the BoJ remains concerned with a weak yen, broadening AI demand and elevated energy prices.”