Programming Challenge

Discussion in 'Trading Software' started by nitro, Feb 27, 2007.

  1. nitro

    nitro

    Give the source code of a function that takes in a DateTime, and calculates whether the given day is the 3rd Friday of the month. There is more than one way to do this, but elegance is always preferred.

    This is useful for calculating whether the Friday is options expiration Friday or not.

    Programming language is up to you, but preferably C or Java or Basic.

    nitro
     
  2. Third Friday is not too hard, but you have to deal with Good Friday holidays sometimes.

    I just put all the Exp dates in a structure and find them when needed.

    Brute force and decidedly Not elegant. Works fine for me tho.


    Here's a little more elegant exp finder in WealthScript (mostly Pascal) you can convert to C. (not my code)

    Code:
    function ExpirationDate( Year, Month : integer ) : integer;
    begin
      var G_Date, G_Month, G_Year, G_Day : integer;
      var n, y, m, d, w : integer;
    
      function _jnbr( y, m, d : integer ) : integer;
      begin
        var a, s, j1, jd : float;
        jd := -1 * Int( 7 * ( Int( ( m + 9 ) / 12 ) + y ) / 4 );
        s := integer( ( ( m - 9 ) < 0 ) or 1 );
        a := Abs( m - 9 );
        j1 := Int( y + s * Int( a / 7 ) );
        j1 := -1 * Int( ( Int( j1 / 100 ) + 1 ) * 3 / 4 );
        jd := jd + Int( 275 * m / 9 ) + d + j1;
        jd := jd + 1721029 + 367 * y;
        Result := Int( jd );
      end;
    
      procedure _jdate( n : Integer );
      begin
        var d, t, w, x, y, z : float;
    
        G_Date := 0;
        G_Month := 0;
        G_Year := 0;
        G_Day := -1;
    
        if ( n > 0 ) then
        begin
          x := n + 68569;
          y := Trunc( 4 * x/146097 );
          x := x-Trunc( ( 146097 * y + 3 )/4 );
          z := Trunc( 4000 * ( x + 1 )/1461001 );
          x := x-Trunc( 1461 * z/4 ) + 31;
          w := Trunc( 80 * x/2447 );
          t := x-Trunc( 2447 * w/80 );
          x := Trunc( w/11 );
          w := w + 2 - 12 * x;
          z := 100 * ( y - 49 )+ z + x;
          d := n + 0.5;
    
          G_Date := Int( t );
          G_Month := Int( w );
          G_Year := Int( z );
          G_Day := 1 + Trunc( ( d/7 - Trunc( d/7 ) )* 7 + 0.000000000317 );
        end;
      end;
    
      function GoodFri( y : integer ) : integer;
      begin
        var r, n, p : integer;
        var y1, a, b1, b, m1, m, q1, q, w1, w : float;
    
        n := y - 1900;
        y1 := n/19;
        a := Trunc( ( y1 - Trunc( y1 ) ) * 19+0.001 );
        b1 := ( 7*a+1 )/19;
        b := Trunc( b1 );
        m1 := ( 11 * a + 4 - b )/29;
        m := Trunc( ( m1 - Trunc( m1 ) ) * 29 + 0.001 );
        q1 := n/4;
        q := Trunc( q1 );
        w1 := ( n + q + 31 - m )/7;
        w := Trunc( ( w1 - trunc( w1 ) ) * 7 + 0.001 );
        r := Int( 25 - m - w );
        p := Int( r );
        if ( r <= 0 ) then p := 31 + r;
        n := 4;
        if ( r <= 0 ) then n := 3;
        n := n - 1;
        result := _jnbr( y, n + 1, p - 2 );
      end;
    
      for d := 15 to 21 do
      begin
        n := _jnbr( Year, Month, d );
        _jdate( n );
        d := G_Date;
        w := G_Day;
        if ( d >= 15 ) and ( d <= 21 ) and ( w = 5 ) then
        begin
          if n = GoodFri( Year ) then d := d - 1;
          Result := Year*10000 + Month*100 + d;
          Exit;
        end;
      end;
    end;
     
  3. swandro

    swandro

    The following lines of VB code return the date of the third Friday in the month.

    If Weekday(DateSerial(Year(Now), Month(Now), 1)) = 7 Then
    Debug.Print DateAdd("d", 14 + 5, DateSerial(Year(Now), Month(Now), 1))
    Else
    Debug.Print DateAdd("d", 14 + (6 - Weekday(DateSerial(Year(Now), Month(Now), 1))), DateSerial(Year(Now), Month(Now), 1))
    End If


    The input is Now, which is today. You could compare the answer to Now and if the difference is zero, then today would be the third Friday in the month.

    I have not tested this extensively - but it certainly works for the current month.
     
  4. Code:
    public class ThirdFriday {
    	public boolean isOptionsFriday(Date date) {
    		Calendar cal = Calendar.getInstance();
    		cal.setTime(date);
    		return 
    			cal.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY && 
    			cal.get(Calendar.WEEK_OF_MONTH) == 3;
    	}
    }
    
     
  5. Hmmm. Can a week start on a saturday? If so, your logic above will fail.
     
  6. MGJ

    MGJ

    Look at a calendar for 2007. June 2007 shows you that the earliest possible date of a 3rd Friday, is the 15th of the month. December 2007 shows you that the latest possible date of a 3rd Friday, is the 21st of the month.

    So the test is (DayOfWeek == FRIDAY) AND (15 <= DayOfMonth <= 21). Simple and straightforward.

    Some people wish to CALCULATE the date of the 3rd Friday ratehr than merely testing whether a given day is, or is not, a 3rd Friday. TO do this simply, just write seven straightforward IF statements, viz,

    IF(the first of the month falls on a Saturday) THEN date_of_3rd_Friday = 21;
    IF(the first of the month falls on a Sunday) THEN date_of_3rd_Friday = 20;
    IF(the first of the month falls on a Monday) THEN date_of_3rd_Friday = 19;
    etc.
     
  7. lol, nice Wayne. There are complete black box trading systems with fewer lines of code than that.
     
  8. nitro

    nitro

    All excellent responses. This is my favorite, if it only worked in C# :(

    There is no WEEKOFMONTH parameter AFAIK.

    nitro
     
  9. nitro

    nitro

    ...
    cal.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY
    ...

    nitro
     
  10. nitro

    nitro

    First, to readers that don't know, in VB the first day of the week is Sunday = 7, Monday = 1, Tuesday = 2, etc.

    The first part of the if clearly works. If the first day of the week is Sunday = 7, then add 19 days + 1 day, and you get the third Friday which would always be the 20th. That always works.

    The second part of the if is more complex. If the first of the month is any other day than Sunday, add 1 day to 14 + (6 - DayOfWeekOfFirstDayOfMonth), and that in theory is the third Friday. Doesn't works this month, Feb 2007: 14 + (6 - 4) + 1 = 17th (Unless Thursday is the 5th day in VB?)

    Interestingly enough, you can turn this calculation to get the weekofmonth using a little modular arithmetic once you get it working...

    nitro
     
    #10     Feb 27, 2007