Friday, December 31, 2021

CompileTimeWeaver.Fody 3.3.3

 

Compile Time Weaver for AOP implementation

1. Introduce

DotNet Platform: NetStandard 2.0
Installation: 

PM> Install-Package CompileTimeWeaver.Fody

Different from runtime interception with dynamic proxy, this tool rewrites assembly at compile time, so that your code get these achievements that dynamic proxy based enhancement cannot give:
  • Much better performance, no dynamic proxy, no thread block or reflection at run time.
  • Directly instantiate your weaved classes with C# "new" operator
  • weave virtual methods/properties
  • weave static methods/properties
  • weave  extension methods
  • weave constructors
  • Add property changed notification to auto-properties

    2. Advice Based Programming Model

    Start with version 2, this tool support advice based programming model. Advice based programming model has these superiorities comparing to the old decorator based programing model in version 1:
    • Easy to intercept async method without thread blocking
    • Simple to control the flow and add “before”, “after”, “around” and “exception” advices
    • Allow to advise methods with parameters of reference type, value type and generic type, ref parameters and out parameters are allowed, too.

    2.1. Step-by-step Instruction

    Step 1) Create a C# project with VisualStudio.Net
    Step 2) Install nuget package CompileTimeWeaver.Fody

    Install NuGet package from https://www.nuget.org/packages/CompileTimeWeaver.Fody, you will see a FodyWeavers.xml file is added into project. The FodyWeavers.xml file content should have "CompileTimeWeaver" node as below, add it manually if the CompileTimeWeaver node is missing.
    <?xml version="1.0" encoding="utf-8"?>
    <Weavers>
      <CompileTimeWeaver />
    </Weavers>
    Step 3) Add MyAdvice class as below
    using CompileTimeWeaver;
    public class MyAdvice : AdviceAttribute
    {
        public override object Advise(IInvocation invocation)
        {
            // do something before target method is Called
            // ...
            Trace.WriteLine("Entering " + invocation.Method.Name);
    
            try
            {
                return invocation.Proceed();    // call the next advice in the "chain" of advice pipeline, or call target method
            }
            catch (Exception e)
            {
                // do something when target method throws exception
                // ...
                Trace.WriteLine("MyAdvice catches an exception: " + e.Message);
                throw;
            }
            finally
            {
                // do something after target method is Called
                // ...
                Trace.WriteLine("Leaving " + invocation.Method.Name);
            }
        }
    
        public override async Task<object> AdviseAsync(IInvocation invocation)
        {
            // do something before target method is Called
            // ...
            Trace.WriteLine("Entering async " + invocation.Method.Name);
    
            try
            {
                return await invocation.ProceedAsync(); // asynchroniously call the next advice in the "chain" of advice pipeline, or call target method
            }
            catch (Exception e)
            {
                // do something when target method throws exception
                // ...
                Trace.WriteLine("MyAdvice catches an exception: " + e.Message);
                throw;
            }
            finally
            {
                // do something after target method is Called
                // ...
                Trace.WriteLine("Leaving async " + invocation.Method.Name);
            }
        }
    }
    

    Step 4) Add [MyAdvice] to any of your class on class level or method level. 
    In the example below, [MyAdvice] is applied on MyClass class, and MyAdvice and MyClass can be in different assemblies.

    [MyAdvice]
    public class MyClass
    {
        public int Add(int x, int y)
        {
            return x + y;
        }
    
        public Task<int> AddAsync(int x, int y)
        {
            await Task.Delay(1000);
            return x + y;
        }
    }
    That is it. You don't need dynamic proxy such as Castle DynamicProxy, directly use you class as usual in C#, for example:
    var obj = new MyClass();
    int z = obj.Add(1, 2);
    z = await obj.AddAsync(1,2);
    The first time when you compile your project, FodyWeavers.xml and FodyWeavers.xsd are generated if they do not exist yet. The FodyWeavers.xml file content should have "CompileTimeWeaver" node as below, add it manually if the CompileTimeWeaver node is missing.
    <?xml version="1.0" encoding="utf-8"?>
    <Weavers>
      <CompileTimeWeaver />
    </Weavers>

    Debug your code, you will see your Add() method and AddAsync() method have been magically rewritten, and the output is as below:

    Entering .ctor...
    Leaving .ctor...
    Entering Add...
    Leaving Add...
    Entering AddAsync...
    Leaving AddAsync...

    2.2. Advice class specification

    • Inherits AdviceAttribute class, or
    • Inherits Attribute class and implements IAdvice interface

    2.3. Rules

    • When multiple advices are applied to a method, the advices are invoked as a pipe line, the Advise() or AdviseAsync() of the first advice is called first.
    • When an advice is applied to class level, it is identical to this advice is added on each constructor and each method.
    • Class level advices appears before all constructor/method level advices
    • Each advice is assigned an Order, it is the sequence number of the appearance in the type group.
    • Each advice on a recursive method is invoked only when the method was entered at the very first time, re-entrances don’t invoke the advice again, for performance reason.

    3. Built-in advices

    There are some built-in advices that you can immediately take advantage in your code, they are listed here.

    3.1. NotifyPropertyChangedAttribute

    When NotifyPropertyChangedAttribute is applied to a class, the class automatically implements INotifyPropertyChanged interface (if it is not implemented) and the setters of auto properties fire PropertyChanged event when the property values change.

    If you do not want a specific setter to fire event, just apply IgnoreNotifyPropertyChangedAttribute to the property, and the setter will not be rewritten.

    [NotifyPropertyChanged]
    public class MyClass //: INotifyPropertyChanged - optional
    {
        //public event PropertyChangedEventHandler PropertyChanged; - optional
    
        public string Name { get; set; }
        public int Age { get; set; }
    
        [IgnoreNotifyPropertyChanged]
        public string Password { get; set; }
    }
    One property change may cause the other property changes, DeterminedByPropertiesAttribute is to define dependancy relations between properties. In the code below, the change of property A fires property change events for property A, C and D, too.
    [NotifyPropertyChanged]
    public class MyClass //: INotifyPropertyChanged - optional
    {
        public int A { get; set; }
        public int B { get; set; }
    
        [DeterminedByProperties("A")]
        public int C => A + 1;
    
        [DeterminedByProperties("B","C")]
        public int D => B + C;
    }

    3.2. LoggingAttribute

    When LoggingAttribute is applied to a class or a method, the parameters of the constructor and methods are written into NLog, Log4Net or Serilog, depending on what logging package is enabled. [IgnoreLogging] is used to disable sensitive parameter logging. For example:

    [Logging]
    public class ClassWithLog
    {
        public static void MethodWithLog(
    		string userName,
    		[IgnoreLogging]string password,
    		int x,
    		int y)
        {
            ...
        }
    
        [IgnoreLogging]
        public static int MethodWithoutLog(int x, int y)
        {
            ...
        }
    }
    
    //The example application using Serilog calls ClassWithLog
    using Serilog;
        
    class Program
    {
        static void Main(string[] args)
        {
            Serilog.Log.Logger = new Serilog.LoggerConfiguration()
                                    .MinimumLevel.Debug()
                                    .Enrich.FromLogContext()
                                    .WriteTo.Console()
                                    .CreateLogger();
    
            ClassWithLog.MethodWithLog("Simon", "fdhasdewjsdfsdfe", 1, 2);
            ClassWithLog.MethodWithoutLog(1, 2);
    
            Serilog.Log.CloseAndFlush();
        }
    }

    When ClassWithLog.MethodWithLog method is called, you will see log messages as below, parameter values in log are from their ToString() method, and password parameter is not logged because of [IgnoreLogging] on it.

    MethodWithLog...
            userName: Simon
            x: 1
            y: 2
    MethodWithLog completed in 5 milliseconds.

    When ClassWithLog.MethodWithoutLog method is called, nothing is logged because it is decorated with [IgnoreLogging].

    3.3. ExceptionHandlerAttribute

    ExceptionHandler Attribute is an advice to consolidate exception handling logic into specific classes according to the exception types. In the example code below, the ApplicationExceptionHandler class defines ApplicationException handling logic and the IOExceptionHandler class defines IOException hanlding logic, you simply add ExceptionHandler decorations on the methods (HelloAsync as example below) to intercept the exceptions.

    public class MyClass
    {
        [ExceptionHandler(typeof(ApplicationException), typeof(ApplicationExceptionHandler))]
        [ExceptionHandler(typeof(IOException), typeof(IOExceptionHandler))]
        public async Task<int> HelloAsync()
        {
            await Task.Delay(1).ConfigureAwait(false);
            ...
            throw new ApplicationException();
            ...
            throw new IOException();
        }
    }
    
    internal class ApplicationExceptionHandler : IExceptionHandler
    {
        public bool HandleException(Exception e)
        {
            Trace.WriteLine(e.GetType() + " is caught");
            return false;
        }
    }
    
    internal class IOExceptionHandler : IExceptionHandler
    {
        public bool HandleException(Exception e)
        {
            Trace.WriteLine(e.GetType() + " is caught");
            return false;
        }
    }


    Thursday, October 7, 2021

    Option Calculator 3.0.0

    Share is care!

    Option Calculator 3.0.0 is shared with all my friends today after a long time waiting.

    1. Release Notes

    • Improved IV calculation algorithm.
    • Added strike predication trend chart.
    • Changed put/call skew calculation algorithm to be similar to that on fdscanner.com (see explanation below).
    • Added PCR trend chart (see explanation below).
    • Added correlation to inverted-UVXY
    • Bug fixes

    2. Installation

    The App doesn't need installation, just click App on google drive, and download the correct file for your specific platform, save it on your local drive, double click it to start up.

    If it is the first time you start up the app, it will ask you to download and install DotNet 5.0 Desktop Runtime from Microsoft website if it has not been installed yet.

    3. Analysis Screen

    Select a ticker that is exactly the same as it on yahoo finance, or enter the ticker and hit Enter key,
    you will see the analysis screen as below. You can adjust sigma scale to see different sigma values.

    Notes: 
    • App only accept Yahoo Finance tickers, for example, "^SPX" rather than "SPX".
    • EM means Expected Movement, it is expected market price change when sigma scale is one.
    • The chart is spitted into 3 different areas by three X-axes: date, probability and premium.
      • Candlesticks area
    use mouse to drag and move the candlestick chart
    scroll mouse wheel to zoom chart.
      • Probability area 
    shows the probabilities of call/put on each point, you can move mouse to the point to display the probability the market hits it.
      • Premium area
    shows the theoretical price of your option at each point, you can move mouse to it to display the premium.
    • Solid horizontal line is the current market price.
    • Thick green horizontal line is the call strike at 2 sigma.
    • Thick red horizontal line is the put strike at 2 sigma.
    • Thin green horizontal line is the call strike at 1 sigma.
    • Thin red horizontal line the put strike at 1 sigma
    • Blue horizontal line is the max pain point.
    Analysis Screen

    4. Let App Monitor Your Options for You.

    You don't need to set it up if you don't want to receive alarms from this app, if you do want it to warn you by sending emails so that your phone can pop up alerts while you are playing golf, click the Setup button.

    In the Setup button, you can input your own email address as sender and receiver so that you send alerts from yourself to yourself. Only Hotmail, Gmail and yahoo mail are supported so far.

    Add the tickers you want the app to monitor for you, enter sigma scale and midpoint limit, etc., and click Save button.

    Alarm Setup Screen
    Notes:
    • Midpoint is the point where the market has 50% chance to hit. You are suggested to set the midpoint limit to be your option strike, so that you will receive alert once the possibility of win or lose is break even.
    • You can disable monitoring an option by set its midpoint limit to zero.
    • If you leave midpoint empty (zero is not empty), app will automatically set midpoint to 2-sigma strike price when you click Save button.
    • You can select the expiration date of the option you want it to monitor, empty expiration means the nearest valid expiry.

    5. IV Trend

    Implied volatility (IV) is denoted by the symbol σ (sigma). It can often be thought to be a proxy of market risk, it is expressed using percentages and standard deviations over a specified time horizon. My app calculates IV with Black-Scholes option model.

    Trend Charts Screen

    6. What is Put/Call Skew?

    On fdscanner.com, put/call skew is defined as the price of 10% OTM puts/10% OTM calls on option expiry. A put skew of 2.1 means the 10% OTM put is 2.1x the price of 10% OTM call. There are often underlying reasons worth researching before entering option position for stocks with high/low skew.

    Theoretically, an equally OTM put and call trades at the same price after accounting for cost of carry, dividends and shorting costs. However, the real world doesn't always follow theory. Demand supply imbalances do happen and below are some possible reasons.

    • Institutions using the Collar strategy, buying puts and selling calls to limit downside at the cost of upside.
    • High demand/Low supply for puts, driving up put prices. Usual occurrence during bear markets.
    • Low demand/High supply for calls, driving down calls prices.
    • Stock had recent huge upward price movements and is grossly overvalued, shifting the supply/demand curve for puts.
    • Dividends contributes to put skew, especially if the dividend is a large percentage of stock price.
    Computing the Put/Call Skew

    Calculating the skew requires 4 option prices, the 2 put options surrounding 90% current share price, and the 2 call options surrounding 110% of current share price. All 4 of these options must have bid/ask spread of below 25% to be included in the Put/Call Skew Index.

    Example Computation
    In this example, MA had a put skew of 1.911, let's see how this number is computed from raw data.

    Step 1: Computing prices, getting the right strikes
    LegendDescriptionComputationOutput
    PriceCurrent Share Price$269.16
    110% SP110% of Current Share Price$269.16 * 1.1$296.08
    90% SP90% of Current Share Price$92 * 0.9$242.24
    High Call StrikeCall option immediately above 110% SPStrike above $296.08$300 Call
    Low Call StrikeCall option immediately below 110% SPStrike below $296.08$295 Call
    High Put StrikePut option immediately above 90% SPStrike above $242.24$245 Put
    Low Put StrikePut option immediately below 90% SPStrike below $242.24$240 Put

    Step 2: Ensuring options pass liquidity checks
    OptionExpiryBidAskAsk/Bid
    $295 Call6/19$2.64$2.932.93/2.64 ~= 1.11
    $300 Call6/19$1.65$1.971.97/1.65 ~= 1.19
    $240 Put6/19$4.30$4.604.6/4.30 ~= 1.07
    $245 Put6/19$5.20$5.755.75/5.20 ~= 1.10
    The liquidity check requires Ask/Bid of all 4 options to be below 1.25. If any are above 1.25, they are excluded from Put/Call Skew index. Stocks that barely make the liquidity cut off may enter and exit the Put/Call Skew index multiple times per day.


    Step 3: Computing option midpoints

    OptionComputationMidpoint price
    $295 Call(2.64 + 2.93)/2$2.79
    $300 Call(1.65 + 1.97)/2$1.81
    $240 Put(4.3 + 4.6)/2$4.45
    $245 Put(5.2 + 5.75)/2$5.48

    The midpoint price is taken as the price for that option.

    Step 4: Interpolated Price
    OptionComputationInterpolated price
    $296.08 Call2.785 - (2.785-1.81)/(300-295) * (296.08 - 295)$2.57
    $242.24 Put4.45 + (5.475-4.45)/(245-240) * (242.24 - 240)$4.90

    Interpolate between the midpoint price of the 2 call and put options.

    Step 5: Calculate Skew
    Put interpolated price/call interpolated price, 4.898/2.5744 = 1.903. If the Put price is higher, the skew value is greater than 1. If Call price is higher, the skew is less than 1.

    Notice: In my app, put/call skew is defined as the price of 5% OTM puts/the price of 5% OTM calls on option expiry, rather than 10% OTM as fdscanner does.

    7. Strike Trend

    The strike trend in the above screenshot is a predication of a stock price. The app display Max Pain trend and a few predication prices in the chart.

    First, the app calculates the max-pain point of the stock on each expiry, to indicate the rough market movement. To predicate market with max pain sometimes works well on large cap ETFs, such as SPX and QQQ, that are not easy to manipulate by individual institute.

    Second, the app use a prediction model to predict the next 5 trading days of the stock prices, please see the prediction lines in app screen.

    8. What is PCR?

    PCR is the abbreviation of put call ratio, there are two kinds of PCRs: PCR(OI) and PCR(Volume).

    PCR(OI) = sum of open interests of put options on a given day/sum of open interests of call options on the same given day.

    PCR(Vol) = sum of volumes of put options on a given day/sum of volumes of call options on the same given day.

    How to interpret the Put Call Ratio to take a view on markets
    If you browse through any derivatives report put out by a broker, you will find a lot of emphasis on the PCR. So, how exactly do you interpret the Put Call ratio in practical terms?

    One of the most important things that you need to understand is that the PCR is normally used as a popular contrarian indicator. That means the conclusions are actually counterintuitive. Let us understand this point in greater detail. There is nothing like a range for PCR or an ideal level for PCR. It is the trend that is more important. Here are a few key pointers pertaining to PCR interpretation..

    Normally, times of greed and fear are reflected by significantly high or significantly low levels of PCR. Contrarians believe that PCR is normally headed in the wrong direction when markets are overbought or oversold and that becomes a key guiding factor.

    Let us assume that the PCR has gone up sharply in the last few days and the market index has also corrected by 15% during the last 1 month. How do we interpret this situation? Contrarians believe that there is too much pessimism as small and retail investors are just buying too much of puts to hedge their downside risk. In any F&O market, the put writing is typically done by savvy traders and institutions. High PCR means aggressive put buying by small and medium investors but it also means aggressive selling by more savvy traders. Typically savvy traders sell only when they believe that downside is limited. That could be an indication that markets are bottoming out.

    The reverse situation holds when markets have shot up and the PCR is falling. It means small and medium investors are heavily buying into calls but it also means that savvier investors are selling calls. That is an indication that markets may be topping out.

    Combining PCR with Implied volatility (IV)
    A smart way of interpreting PCR is by combining it with IV. Remember, IV is the volatility that is implied in the option price and it reflects the risk perception in the market. Here are a few pointers..

    If the PCR increases with an increase in IV, it indicates that the put activity is increasing with a heightened sense of risk. That is a bearish signal.

    If the PCR increases with a decrease in IV, it indicates that put activity is increasing with a falling sense of risk. That means more writing of puts and is a bullish signal.

    If the PCR decreases with decrease in IV, it is indicative of unwinding of Puts and can be interpreted as a signal that markets may be bottoming out.

    If the PCR decreases with an increase in IV, it means that puts are just being covered and the markets will again fall once the covering is done with.

    9. Correlation to Inverted-UVXY

    If UVXY is trader's fear gauges, the inverted-UVXY is peace gauges. Let's say you want to see the correlation between QQQ and inverted-UVXY, you can select QQQ in the ticker drop down list and then select "1 month/day" as data granularity, and you will be able to see a correlation coefficient chart as below.

    Correlation to Inverted-UVXY

    A correlation coefficient is a value between -1 and +1, when it is near 0, QQQ has low correlation to inverted-UVXY; when it is close to +1, they are positively correlated; when it is close to -1, they are negatively correlated. 

    Acknowledgement

    I give thanks to everyone who has shared their knowledges with me and has supported me to develop this app. I am glad if this app is useful for you, and appreciate it if you send me a cup of coffee by click the PayPal Donate button below.