Commodities | 10:32 AM
Coronavirus has implications across resources markets, including iron ore, crude oil, base metals & molybdenum.
-Investor views on the outlook for iron ore in 2020 polarised by coronavirus
-Oil prices likely to struggle until outbreak stabilises
-Slump in metal prices for major Chinese imports expected to reverse strongly
-More molybdenum supply from Rio Tinto, Freeport-McMoran cuts
By Eva Brocklehurst
Iron Ore
The price of iron ore has felt the impact of the appearance of coronavirus, dropping to US$83/t, as China absorbs around 75% of the seaborne trade in iron ore. Moreover, this risk came at a time when supply was seasonally tight and the outlook was becoming increasingly bullish.
As a result, Morgan Stanley observes investor views have polarised. Immediate concerns stem from logistics, as demand for steel is always low around Chinese New Year.
The broker’s economists consider the virus will cause near-term pressure on growth but it will be transitory, with a recovery beyond the March quarter. Depending on when the virus peaks, the start of the construction season, usually underway by mid-March may be delayed.
Countering the impact on demand, shipments from Australia and Brazil are affected by seasonal disruptions. Australian shipments fell sharply in the second week of January and have only modestly recovered, while heavy rainfall in Brazil – not causing any major disruptions as yet – highlights elevated risks.
Morgan Stanley expects prices to remain volatile and acknowledges significant downside risks to a US$93/t forecast for iron ore in the first quarter.
Macquarie remains confident in the fundamentals for 2020. Coronavirus aside, bullish elements have emerged in the market, mainly centred around Brazilian supply. In the context of a tightening physical market as a result of pronounced slump in shipments from Vale, the risk created by coronavirus may present opportunities for investors, given strong market fundamentals.
Improving Chinese steel margins continue to drive positive sentiment for iron ore, the broker adds. In recent weeks, the rebar margin has contracted and the hot rolled coil margin is now around US$6/t above the rebar margin.
Macquarie suspects ongoing investigations on dam safety are causing Vale to be particularly careful with water management during the rainy season, affecting material movements at its mines. The high rainfall, forecast to continue, could potentially hinder logistics and impact around 130mtpa of iron ore capacity.
Crude Oil
JPMorgan notes prices for Brent crude dipped below US$60/bbl for the first time since early November amid fears coronavirus was spreading rapidly. The market appears to be pricing in a demand shock equivalent to the SARS outbreak in 2003.
Morgan Stanley also envisages further downside for oil, depending on how soon the coronavirus peaks. Oil prices may struggle to find sustained support until the situation becomes more stable.
The broker emphasises concerns are not unfounded as an increasing number of flights to China have been cancelled and travel restrictions are in place across many cities. The downward shift in oil prices across the forward curve follows six months of relatively stable prices.
Meanwhile, US crude production reached another record high in November at 12.88m barrels/day and imports were the lowest since 1992, amid falling volumes from OPEC.
Production growth from the ‘shale states ‘had reached a new record high, driven by Texas and New Mexico with 470,000 b/d and 270,000 b/d respectively. Offshore output was up 45,000 b/d year-on-year.
Morgan Stanley believes 2020 will be a big year for capital expenditure in the Australian oil industry and that could lead to a change in performance across its coverage, particularly given demand concerns regarding oil and the outbreak of coronavirus.
Beach Energy ((BPT)) has outperformed but the broker suggests this will be more difficult in 2020 and downgrades to Underweight. Investment will also rise meaningfully and reserve life and production growth likely lag for both Oil Search ((OSH)) and Woodside Petroleum ((WPL)).
However, the broker upgrades Senex Energy ((SXY)) to Overweight, as the stock has underperformed for a number of years and should experience progress with its gas assets.
Metals
Citi continues to urge caution be applied across the entire metals complex in the near term, given the outbreak of coronavirus and the related shock to Chinese demand. This is because when net imports from the world’s largest consumer fall, commodity markets still have to clear stock and speculative appetite is unlikely to stockpile physical metal or buy futures.
Of interest, the degree to which commodities have sold off (excluding rhodium and gold) following the coronavirus outbreak is correlated with the degree to which China is a net importer and include iron ore, nickel and copper.
The full story is for FNArena subscribers only. To read the full story plus enjoy a free two-week trial to our service SIGN UP HERE
If you already had your free trial, why not join as a paying subscriber? CLICK HERE
var fn_do_fb_login; var fn_check_login_state; var fn_get_fb_login_button; var fn_remove_fb_loading_btn; var fn_status_change_callback;
jQuery(document).ready(function(e){
window.fbAsyncInit = function() { FB.init({ appId : '2003222569780759', // dev version: 500318794096450 cookie : true, // Enable cookies to allow the server to access the session. xfbml : true, // Parse social plugins on this webpage. version : 'v4.0' // Use this Graph API version for this call. });
//check if all fb elements done rendering //========== fn_get_fb_login_button();
FB.Event.subscribe('xfbml.render', function(response) { fn_remove_fb_loading_btn(); }); //==========
FB.getLoginStatus(function(response) { // Called after the JS SDK has been initialized.
var fb_r = response;
if (fb_r && fb_r.status === 'connected') {
get_detail_data(fb_r.authResponse.userID); // Returns the login status.
// logout function // FB.logout(function(response) { // console.log('do logout'); // }); } }); };
(function(d, s, id){ var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) {return;} js = d.createElement(s); js.id = id; js.src = "https://connect.facebook.net/en_US/sdk.js"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk'));
//fb functionality //======================================================= fn_check_login_state = function check_login_state() { // Called when a person is finished with the Login Button.
//everytime event login triggered, reset the form fn_reset_form();
FB.getLoginStatus(function(response) {
var status_change_callback = fn_status_change_callback(response);
if (status_change_callback) {
FB.api('/me', function(response) {
console.log(response);
});
}
});
}
//new function to do fb login - since might need a separate function //between checking and login fn_do_fb_login = function do_fb_login() { // Called when a person is finished with the Login Button.
//everytime event login triggered, reset the form fn_reset_form();
FB.getLoginStatus(function(response) {
e('.form_loading').show();
var status_change_callback = fn_status_change_callback(response);
if (status_change_callback) {
FB.api('/me', function(response) {
console.log(response); set_detail_data_to_form_and_submit(response.id);
});
} else {
FB.login(function(fb_l_r) {
if (fb_l_r.authResponse && fb_l_r.status == 'connected') {
console.log(fb_l_r.authResponse.userID); set_detail_data_to_form_and_submit(fb_l_r.authResponse.userID);
} else { e('.form_loading').hide(); }
});
}
});
}
fn_status_change_callback = function status_change_callback(response) { // Called with the results from FB.getLoginStatus().
var check_status;
console.log('status_change_callback'); console.log(response); // The current login status of the person.
if (response.status === 'connected') { // Logged into your webpage and Facebook.
get_detail_data(response.id); check_status = true;
} else { // Not logged into your webpage or we are unable to tell.
console.log('facebook is not logged in'); check_status = false;
}
return check_status;
}
function get_detail_data(fb_id) {
FB.api( '/'+fb_id+'/', {fields: 'id,first_name,last_name,email'}, function (fb_r) {
var fb_data_json = JSON.stringify(fb_r);
if (fb_r && !fb_r.error) {
e('#fb_data').html(fb_data_json);
}
} );
}
//it's kinda silly, but since fb is an async, cannot use passing parameter on a function like jquery //so instead put it on FB.api function set_detail_data_to_form_and_submit(fb_id) {
e('.form_loading').show();
FB.api( '/'+fb_id+'/', {fields: 'id,first_name,last_name,email'}, function (fb_r) {
var fb_data_json = JSON.stringify(fb_r);
if (fb_r && !fb_r.error) {
var fb_id = fb_r.id; var fb_firstname = fb_r.first_name; var fb_lastname = fb_r.last_name; var fb_email = fb_r.email;
e('.sns_facebook').val(1); e('.sns_facebook_id').val(fb_id);
e('#fb_data').html(fb_data_json); do_submit_form();
//no form_loading hide - we gonna lock the form IF it's success
} else {
e('.form_loading').hide();
}
} );
}
fn_get_fb_login_button = function get_fb_login_button() {
var html = ''+ ''; e('.fb_button_placeholder').html(html);
}
fn_remove_fb_loading_btn = function remove_fb_loading_btn() {
e('.fb_loading_btn').hide(); e('.fb_login_wrapper').show();
}
fn_reset_form = function reset_form() {
e('.sns_facebook').val(''); e('.sns_facebook_id').val(''); e('.form_loading').hide();
}
function do_submit_form() {
var the_form = e('.formLogin:visible');
if (the_form.length) {
var target_form = the_form[0]; target_form.submit();
} else {
console.log('form not exist');
}
} //=======================================================
//initialize fn_reset_form();
});

