Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Generate specific dates as a dummy (dummy for trading days around holidays)

    Hello Statalist,

    I have panel data for 989 firms between 1 Jan 1995 until 31Dec 2014. I use business calendar date.
    The data as below:

    Code:
    * Example generated by -dataex-. To install: ssc install dataex
    clear
    input float idc str10 dat double(_marketvalue _numbershares _price _returnindex _tradingvalue _tradingvolume _unpaddedprice) str6 company float(caldate bcaldate dow mondaydum)
    87 "12_8_2003"               27.01 103900 .26              31.35 .  .   . "T:BEGR" 16047 2331 5 0
    87 "12_9_2003"               27.01 103900 .26              31.35 .  .   . "T:BEGR" 16048 2332 6 0
    87 "12_10_2003"              27.01 103900 .26              31.35 .  .   . "T:BEGR" 16049 2333 0 0
    87 "12_11_2003"              27.01 103900 .26              31.35 .  .   . "T:BEGR" 16050 2334 1 0
    87 "12_12_2003"              27.01 103900 .26              31.35 .  .   . "T:BEGR" 16051 2335 2 0
    87 ""                            .      .   .                  . .  .   . ""       16052    . . 0
    87 ""                            .      .   .                  . .  .   . ""       16053    . . 0
    87 "12_15_2003"              27.01 103900 .26              31.35 .  .   . "T:BEGR" 16054 2336 3 0
    87 "12_16_2003"              24.42 103900 .23              28.34 .  4 .23 "T:BEGR" 16055 2337 4 0
    87 "12_17_2003"              24.42 103900 .23              28.34 .  .   . "T:BEGR" 16056 2338 5 0
    87 "12_18_2003"              22.86 103900 .22              26.53 . 35 .22 "T:BEGR" 16057 2339 6 0
    87 "12_19_2003"              22.86 103900 .22              26.53 .  .   . "T:BEGR" 16058 2340 0 0
    87 ""                            .      .   .                  . .  .   . ""       16059    . . 0
    87 ""                            .      .   .                  . .  .   . ""       16060    . . 0
    87 "12_22_2003"              22.86 103900 .22              26.53 .  .   . "T:BEGR" 16061 2341 1 0
    87 "12_23_2003"              22.86 103900 .22              26.53 .  .   . "T:BEGR" 16062 2342 2 0
    87 "12_24_2003"              22.86 103900 .22              26.53 .  .   . "T:BEGR" 16063 2343 3 0
    87 "12_25_2003"              22.86 103900 .22              26.53 .  .   . "T:BEGR" 16064 2344 4 0
    87 "12_26_2003"              22.86 103900 .22              26.53 .  .   . "T:BEGR" 16065 2345 5 0
    87 ""                            .      .   .                  . .  .   . ""       16066    . . 0
    87 ""                            .      .   .                  . .  .   . ""       16067    . . 0
    87 "12_29_2003"              22.86 103900 .22              26.53 .  .   . "T:BEGR" 16068 2346 6 0
    87 "12_30_2003" 23.900000000000002 103900 .23 27.740000000000002 .  2 .23 "T:BEGR" 16069 2347 0 0
    87 "12_31_2003" 23.900000000000002 103900 .23 27.740000000000002 .  .   . "T:BEGR" 16070 2348 1 0
    87 "_1_1_2004"  23.900000000000002 103900 .23 27.740000000000002 .  .   . "T:BEGR" 16071 2349 2 0
    end
    format %td caldate
    format %tbmybcal bcaldate
    In my regression, I have dummies for day-of-week and holidays for trading around non-weekend holidays.
    In order to generate dummy for day-of-week, I use this code;

    HTML Code:
     gen dow = dow(bcaldate)
    HTML Code:
    gen mondaydum=1 if bcaldate ==1
    HTML Code:
    replace mondaydum=0 if mondaydum==.

    For the dummy trading around non-weekend holidays, I would like to extract 25dec (Christmas) and 1jan (new year) for every year as a dummy.
    I try this code, but I got error.

    HTML Code:
    gen holiday=1 if bcaldate 25dec* and (-1) if dow (sa)
    invalid '25dec' 
    r(198);
    HTML Code:
     gen holiday=1 if bcaldate 25dec* and (+1) if dow (sun)
    invalid '25dec' 
    r(198);
    Can anyone help me to extract the specific date 25dec and 1jan for every year, so that I can generate it as a dummy variable.
    Thank you in advance.

    Regards,
    Rozita

  • #2
    I've never used business calendars but I'm pretty sure that you are not using it correctly here. The dow() function expects a Stata daily date, not a business calendar date. If you load the help file on business calendars using:

    Code:
    . help business calendar
    and scroll down to item 9:

    9. Obtaining day of week, etc.
    You obtain day of week, etc., by converting business dates to regular dates and then using the standard functions.
    To obtain the day of week of bdate on business calendar calname, type

    . generate dow = dow(dofb(bdate, "calname"))

    See Extracting date components from SIFs in [D] datetime for the other extraction functions.
    Since you have a daily date in the data, you can also get the day of week using
    Code:
    gen dow = dow(caldate)
    I'm not sure I understand what you mean by trading around a holiday. Here's now to create an indicator if there's weekday trading on xmas and new years:
    Code:
    gen holiday = 0
    replace holiday = 1 if inrange(dow, 1, 5) & (month(caldate) == 12 & day(caldate) == 25)
    replace holiday = 1 if inrange(dow, 1, 5) & (month(caldate) == 1 & day(caldate) == 1)

    Comment


    • #3
      Hello Rozita,

      Based on your code, you have a business calendar file called mybcal.stbcal. Another solution is to modify that file to omit all business days you want. If you want to omit Saturdays, Sundays, December 31 and January 01 of every year, mybcal.stbcal will look something like this:

      Code:
       *  mybcal.stbcal
      
      purpose "Test"
      dateformat dmy
      
      range 30dec1994 31dec2014
      centerdate 30dec1994
      
      omit dayofweek (Sa Su)
      omit date 25dec*
      omit date 01jan*
      You can omit holidays based on more complex rules. help datetime_business_calendars_creation gives more details on how to create business calendar files. You can create them "manually", or automatically with bcal create, by inferring holidays from a dataset. You can ascertain there are no errors in your business calendar file with bcal load. Please make sure that the first and last day in the range, and the centerdate, are not holidays.

      Code:
      bcal load mybcal
      So, given a business calendar file and a date variable in %td format, like caldate in your example, you can create a business date, say bcaldate, using function bofd() as follows:

      Code:
      gen bcaldate = bofd("mybcal", caldate)
      You probably do not need additional variables to track holidays.

      I hope this is helpful.

      -- Kreshna


      Comment


      • #4
        Thank you Robert Picard and Kreshna Gopal (StataCorp).
        I take note about how to generate day-of-week using business calendar.


        I had try this code:
        Code:
        HTML Code:
            gen holiday = 0
        HTML Code:
            replace holiday = 1 if inrange(dow, 1, 5) & (month(caldate) == 12 & day(caldate) == 25)
        HTML Code:
            replace holiday = 1 if inrange(dow, 1, 5) & (month(caldate) == 1 & day(caldate) == 1)
        It works well when dummy holiday is set=1 for 25dec and 1jan.

        My apologies because I didn't make it clear about the holiday dummy. The dummy holidays work in this way:

        A dummy for holidays set such that if a holiday falls on a Friday then the preceding Thursday is set to 1, and if the holiday is on a Monday then the following Tuesday is set to 1, and if the holiday is on any other weekday then the day preceding and following the holiday are set to 1; this is intended to capture the fact that trading activity declines substantially around holidays.

        For example, if 25dec falls on Friday, then the preceding Thursday (24dec) is set to 1,
        and if 25 dec fall on Monday then the following Tuesday (26dec) is set to 1.

        I try this code and got error;

        HTML Code:
        replace holiday = 1 if (month(caldate) == 12 & day(caldate) == 25) & (-1) if dow(5) 
        invalid syntax
        r(198);
        Thank you in advance for help and comments.

        Regards,
        rozita






        Comment


        • #5
          What you tried
          Code:
          replace holiday = 1 if (month(caldate) == 12 & day(caldate) == 25) & (-1) if dow(5)
          makes no sense:
          • you have two if qualifiers for the same command; that's not allowed
          • in Stata, anything that evaluates to something else than zero is true so (-1) is true
          • dow(5) shows that you simply do not understand how this basic date function works.
          Working with dates is a bit tricky in Stata and the best vector to a solution is to read and read again the documentation until it makes sense. Start with
          Code:
          help datetime
          You have a more complicated problem in that your data example suggests that you are also using a business calendar. Yet you have holidays with trading data. That doesn't look right to me and suggests that you should read up on Stata's business calendars and perhaps follow Kreshna's advice to omit these holidays.

          Having said this, by their nature, there's nothing in your data that can be used to identify non-weekend holidays. I think it's best to create a separate dataset of holidays and then use that to create your indicator.

          Code:
          * input some holidays
          clear
          input str10 holydate
          "12_25_2003"
          "_1_1_2004"
          end
          
          * convert from string to numeric date
          gen holydaten = date(holydate,"MDY")
          format %td holydaten
          
          * expand to 3 observations for each holiday and note the offset
          expand 3
          bysort holydaten: gen holyoffset = _n - 2
          gen caldate = holydaten + holyoffset
          format %td caldate
          
          * save the dates
          keep caldate holyoffset
          isid caldate, sort
          save "holidays.dta", replace
          
          * Example generated by -dataex-. To install: ssc install dataex
          clear
          input float idc str10 dat double(_marketvalue _numbershares _price _returnindex _tradingvalue _tradingvolume _unpaddedprice) str6 company float(caldate bcaldate dow mondaydum)
          87 "12_8_2003"               27.01 103900 .26              31.35 .  .   . "T:BEGR" 16047 2331 5 0
          87 "12_9_2003"               27.01 103900 .26              31.35 .  .   . "T:BEGR" 16048 2332 6 0
          87 "12_10_2003"              27.01 103900 .26              31.35 .  .   . "T:BEGR" 16049 2333 0 0
          87 "12_11_2003"              27.01 103900 .26              31.35 .  .   . "T:BEGR" 16050 2334 1 0
          87 "12_12_2003"              27.01 103900 .26              31.35 .  .   . "T:BEGR" 16051 2335 2 0
          87 ""                            .      .   .                  . .  .   . ""       16052    . . 0
          87 ""                            .      .   .                  . .  .   . ""       16053    . . 0
          87 "12_15_2003"              27.01 103900 .26              31.35 .  .   . "T:BEGR" 16054 2336 3 0
          87 "12_16_2003"              24.42 103900 .23              28.34 .  4 .23 "T:BEGR" 16055 2337 4 0
          87 "12_17_2003"              24.42 103900 .23              28.34 .  .   . "T:BEGR" 16056 2338 5 0
          87 "12_18_2003"              22.86 103900 .22              26.53 . 35 .22 "T:BEGR" 16057 2339 6 0
          87 "12_19_2003"              22.86 103900 .22              26.53 .  .   . "T:BEGR" 16058 2340 0 0
          87 ""                            .      .   .                  . .  .   . ""       16059    . . 0
          87 ""                            .      .   .                  . .  .   . ""       16060    . . 0
          87 "12_22_2003"              22.86 103900 .22              26.53 .  .   . "T:BEGR" 16061 2341 1 0
          87 "12_23_2003"              22.86 103900 .22              26.53 .  .   . "T:BEGR" 16062 2342 2 0
          87 "12_24_2003"              22.86 103900 .22              26.53 .  .   . "T:BEGR" 16063 2343 3 0
          87 "12_25_2003"              22.86 103900 .22              26.53 .  .   . "T:BEGR" 16064 2344 4 0
          87 "12_26_2003"              22.86 103900 .22              26.53 .  .   . "T:BEGR" 16065 2345 5 0
          87 ""                            .      .   .                  . .  .   . ""       16066    . . 0
          87 ""                            .      .   .                  . .  .   . ""       16067    . . 0
          87 "12_29_2003"              22.86 103900 .22              26.53 .  .   . "T:BEGR" 16068 2346 6 0
          87 "12_30_2003" 23.900000000000002 103900 .23 27.740000000000002 .  2 .23 "T:BEGR" 16069 2347 0 0
          87 "12_31_2003" 23.900000000000002 103900 .23 27.740000000000002 .  .   . "T:BEGR" 16070 2348 1 0
          87 "_1_1_2004"  23.900000000000002 103900 .23 27.740000000000002 .  .   . "T:BEGR" 16071 2349 2 0
          end
          format %td caldate
          format %tbmybcal bcaldate
          
          * assume that idc is some sort of panel identifier
          isid idc caldate, sort
          
          * merge the trading data with the holiday data
          merge m:1 caldate using "holidays.dta", keep(master match) nogen
          isid idc caldate, sort
          
          * flag weekdays that are an offset of a holiday
          gen wanted = inrange(dow(caldate), 1, 5) & inlist(holyoffset,-1,1)

          Comment


          • #6
            Adding on to all the useful tips provided by Robert Picard, another solution is to use a (maybe different) business calendar file to encode the dummy holidays as well. The following .stbcal file omits all Saturdays, Sundays, Dec 25th and Jan 1st of every year. It also omits the day preceding/following Dec 25, if Dec 25 as well as the preceding/following day is a weekday -- and similarly for Jan 01. (Note: here, if Dec 25/Jan 1 is a Saturday or Sunday, then the preceding/following day is not a dummy holiday.)

            Code:
            * mybcal1.stbcal
            purpose "With dummy holidays"
            
            dateformat dmy
            range 30dec1994 31dec2014
            centerdate 30dec1994
            
            omit dayofweek (Sa Su)
            omit date 25dec*
            omit date 01jan*
            omit date 25dec* and +1 if dow(Mo Tu We Th)
            omit date 25dec* and -1 if dow(Tu We Th Fr)
            omit date 01jan* and +1 if dow(Mo Tu We Th)
            omit date 01jan* and -1 if dow(Tu We Th Fr)
            help bcal documents more rules to omit holidays.

            -- Kreshna

            Comment


            • #7
              Thank you Robert Picard and Kreshna Gopal (StataCorp) for help and comments. You have sorted out my problems.

              Comment

              Working...
              X