22/12/2023

[Google Sheets] Import data from Yahoo Finance

DISCLAIMER: This is not a stock picking recommendation, the tickers shown are used as example and not provided as financial or investment advice.

Google Sheets offers the GOOGLEFINANCE function which can be used to import market data.

Usage is simple, for example to get the price of a stock, first search for it on Google Finance, then look at the quote URL it generates and copy the exchange:ticker value into the function.

In this example we try to get the quote for A200 ETF traded on the Australian ASX exchange. The URL shows ASX:A200 after the quote part, therefore we should use:

=GOOGLEFINANCE("ASX:A200")

So far, so good. Sometimes however Google does not show data for a particular ticker, or it shows data only in another currency or from another exchange. 
For example, another ETF XESC shows quotes from many exchanges but is also traded on the German XETRA (XESC.DE), which is not sourced by Google. Or the CHSPI ETF traded on the Swiss Six exchange (CHSPI.SW) is simply not found at all.

09/11/2023

[Windows 11] Default show more options explorer right click menu (old UI behavior)

One change with Windows 11 is that the right click menu in Explorer was replaced with some condensed version where the old behavior is hidden behind a "Show more options" entry. This makes some actions slower to find and quite annoying, for example 7-zip or Notepad++

To revert it to the nicer old UI you can delete the value of this registry key (for example via regedit):

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InProcServer32

Key (Default)(its old value should be C:\Windows\System32\Windows.UI.FileExplorer.dll, just remove it)

You then need to restart explorer process or logout and login again or reboot the computer for this change to be applied.

06/11/2023

[Tampermonkey] Disable Bing Chat search integrations

When using Bing search there are multiple places that integrate the Chat functionality with the ChatGPT AI. Some of these integrations are annoying and can be easily disabled by installing the Tampermonkey browser extension then adding a couple scripts to modify the displayed webpage and its behavior.

 // ==UserScript==  
 // @name    Disable Bing Search Engine Scroll  
 // @namespace  your-namespace  
 // @description Disables scrolling on the Bing search engine page to prevent accidental scrolling into the Bing chat feature.  
 // @match   https://www.bing.com/*  
 // @version   1  
 // @grant    none  
 // ==/UserScript==  
   
 window.addEventListener("wheel", e=>{  
 if(e.target.className.includes("cib-serp-main")) e.stopPropagation();  
 });  

  • Disable sidebar Chat autosearch functionality when disaplying search results:
 // ==UserScript==  
 // @name    Disable Bing Chat autosearch  
 // @namespace  your-namespace  
 // @description Disables the Bing Chat autosearch functionality on the right side of results when doing a search.  
 // @match   https://www.bing.com/*  
 // @version   1  
 // @grant    none  
 // ==/UserScript==  
   
 const element = document.getElementById("sydwrap_wrapper");  
 element.remove();  
 const element1 = document.getElementById("b_sydTigerCont");
 element1.remove();

Remember that of course these scripts might stop working one day if Microsoft decides to change something on their side, when that happens they will simply need to be updated.

23/09/2023

[Kodi] 5.1 audio output

Kodi is possibly the greatest home media center project ever, and here I just want to point out this page for audio setup which I think has not enough evidence judging by how many people seek help on how to output 5.1 audio using various home setups.

The simplest way is to configure in Kodi the number of audio channels as 2.0 and enable passthrough. Then enable all the formats supported by your receiver eg Dolby Digital, DTS, etc. 

However quite certainly your setup will be something like a PC HDMI connected to a TV or sound system which is then connected to a sound system (HDMI/SPDIF) or TV (HDMI). If the TV is your middle component you must ensure it is also configured to allow passthrough OR it supports the stream it's receiving and can decode and send it down uncompressed.

Lastly, the HDMI ARC connection is not really relevant unless you really really need to pass the audio stream as is through the components (eg from first to last whatever your setup is), but nowadays any component in your setup should be able to decode the stream and pass it down at least as PCM.

30/08/2023

[Spring] Synchronized methods and separate transactions

When marking a method as synchronized, it's important to remember that synchronization does NOT change the transactionality settings of the current operation.

For example the following parallel execution:

methodA() calls syncMethod() then calls somethingElse()
methodB() calls syncMethod() then calls somethingElse()

What happens:
  1. methodA opens Transaction A enters syncMethod
  2. methodB opens Transaction B waits on syncMethod
  3. methodA exits syncMethod, starts executing somethingElse
  4. methodB enters syncMethod while methodA completes somethingElse and commits Transaction A
  5. methodB exits syncMethod, starts executing somethingElse
  6. methodB completes somethingElse and commits Transaction B

Now the important part is points 4. If the syncMethod requires fresh data from other executions, methodB will NOT see that data when it enters syncMethod since Transaction A has NOT yet been commited.

The synchronization is only blocking a thread from entering the protected code block, but as soon as the resource is free, the next waiting thread will enter immediately.

This means that to allow other methods to read latest data while in the protected section, any operation done in the synchronized method must be executed in a separate transaction, for example using the TransactionHandler helper.

09/08/2023

[Spring] Execute method in separate transaction

In Spring annotating a method as requiring a new transaction will not work if the caller of the method is in the same class.

We can easily work around this issue by creating a new class that will execute a given method in a new transaction:

 import org.springframework.stereotype.Service;  
 import org.springframework.transaction.annotation.Propagation;  
 import org.springframework.transaction.annotation.Transactional;  
   
 import java.util.function.Supplier;  
   
 /**  
  * Since spring ignores transaction settings for methods within the same class, we need a separate service  
  * to run isolated transactions which can be called from anywhere simply by supplying the method to execute  
  */  
 @Service  
 public class TransactionHandlerService {  
   
   /**  
    * Runs the given method in a the same transaction as the caller  
    *  
    * @param supplier the method to execute  
    * @param <T>  
    * @return the result of the invoked method  
    */  
   @Transactional(propagation = Propagation.REQUIRED)  
   public <T> T runInSameTransaction(Supplier<T> supplier) {  
     return supplier.get();  
   }  
   
   /**  
    * Runs the given method in a separate transaction  
    *  
    * @param supplier the method to execute  
    * @param <T>  
    * @return the result of the invoked method  
    */  
   @Transactional(propagation = Propagation.REQUIRES_NEW)  
   public <T> T runInNewTransaction(Supplier<T> supplier) {  
     return supplier.get();  
   }  
 }  

Then ensure the callers are annotated as @Transactional and simply pass the method to execute as input to our, for example:

transactionHandlerService.runInNewTransaction(() -> myMethod(someInput));