Announcement

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

  • How to use a variables value as variable name in a loop?

    Hi,

    I'm currently working on a dataset containing stock ( and other) prices in a firm's home currency, and want to convert these to USD so that the values can be compared.

    fic => identifies countries, looks like NLD, SWE, GER etc
    prccd => stockprice variable
    ex##us => exchange rates, number of foreign currency per USD. looks like exeuus, exsdus, etc.

    while I could use the following for every variable to be replaced,

    Code:
    gen USDmcap = .
    gen USDstockprice = .
    gen USDtotalrepo = .
    //etc
    
    replace USDstockprice = prccd / exsdus if fic == "SWE"
    replace USDmcap = marketcap / exsdus if fic == "SWE"
    //etc
    it would require a lot of editing and allow for errors when I am adjusting all the variables . Therefore, I wanted to make a loop. I currently have the following.

    Code:
    g str9 matchficex = "a"
    replace matchficex = "SWEexsdus" if fic == "SWE"
    // ======= manually copy+paste the above 30 times and only once adjust it so that the proper combination of country identifiers + currency vars are matched
    // ...
    
    //replace USDstockprice = prccd / RUNASVAR(substr(matchficex,4,9)) if fic == substr(matchficex,1,3)
    The IF-function above is triggered as both fic and the substring are in string format. However, I'm trying to solve the problem where I currently have RUNASVAR()

    The substring there returns "exsdus". the idea is that the function returns the value stored inside the variable exsdus (which would be exchange rate 7.40344 or something) and not just the name.

    When I used to code in mIRC, I would have utilized the following code:
    Code:
    //replace %USDstockprice = %prccd / %ex [ $+ [ substr(matchficex,6,9) ] ] if %fic == substr(matchficex,1,3)
    or
    //replace %USDstockprice = %prccd / % [ $+ [ substr(matchficex,4,9) ] ] if %fic == substr(matchficex,1,3)
    As in that programming language % identifies a variable, and I could use brackets just like you use them in math to let mIRC compute whatever is inside the brackets first, and then run it as variable by removing the spaces afterwards through the use of $+

    Could anyone tell me if there is something in stata that would allow me to get the job done?

    EDIT: If it helps to find a potentially different solution, all exchange rate variables start with ex* -- However, I haven't been able to come up with a foreach-function solution that may work.

    PS: Given that I am working with a 20-year dataset, at some point some currency pairs need to be changed (e.g. eurozone countries), but that is something I'll solve easily.
    Last edited by Sebastiaan Emiel; 08 Sep 2017, 11:01.

  • #2
    This is very likely an easy thing to code in a Stata loop. But the overall approach, and certainly the specifics, depend on details of your data set.

    Run -ssc install dataex- to get Robert Picard's -dataex- command. Then run -help dataex- and read the instructions for using it. Use it to post a small representative sample of your Stata data set here. If you do that, I'm confident you will get a timely and helpful response.

    (Note: If the exchange rates and the stock prices are in separate datasets that need to be combined for this process, be sure to provide examples from each of them, and make sure that the exchange rates example includes exchange rates that would actually be used in the stock price example.)

    Comment


    • #3
      Originally posted by Clyde Schechter View Post
      This is very likely an easy thing to code in a Stata loop. But the overall approach, and certainly the specifics, depend on details of your data set.

      Run -ssc install dataex- to get Robert Picard's -dataex- command. Then run -help dataex- and read the instructions for using it. Use it to post a small representative sample of your Stata data set here. If you do that, I'm confident you will get a timely and helpful response.

      (Note: If the exchange rates and the stock prices are in separate datasets that need to be combined for this process, be sure to provide examples from each of them, and make sure that the exchange rates example includes exchange rates that would actually be used in the stock price example.)
      All data has already been merged into a single file. Here are some of the variables used in this dataline.

      EDIT: The below illustrates how the dataset looks, and has ~2 swedish obs around the middle, which I tested the lines in the original post with.

      Code:
      * Example generated by -dataex-. To install: ssc install dataex
      clear
      input str6 gvkey double prccd str4 fic double(exslus exsdus exszus extaus exthus exusuk exukus exvzus exauus exfnus exfrus exgeus exgrus exusir exirus exitus exneus expous exspus exeuus) float marketcap
      "001166"   42.635 "NLD"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  2720.002
      "001491"    131.5 "ISR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  839.6316
      "001855"     4.99 "PHL"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 10414.293
      "001932"   46.215 "GBR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  86161.88
      "002018"    15.86 "ISR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 24154.227
      "002162"     2.32 "PHL"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 567.97406
      "002410"    5.096 "GBR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  99235.87
      "002411"    4.461 "GBR" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269   44431.3
      "002721"     3295 "JPN"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 4394750.5
      "004311"    17.88 "ISR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 531.81854
      "004925"     4467 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269 2298833.3
      "005180"    15.62 "GBR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464   76694.7
      "005650"    524.7 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269   2536118
      "005691"   2992.5 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269   5420700
      "006203"    8.009 "ISR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 9067.1875
      "006494"   1932.5 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269 1878327.5
      "006506"   1668.5 "JPN"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 2070807.4
      "006512"     4914 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269 1855617.8
      "006972"     7010 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269  981461.4
      "007041"      .42 "MYS" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269     117.6
      "007114"     1016 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269 2492302.3
      "007471"     1298 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269 2331875.3
      "007652"      277 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269  721510.9
      "007908"     4961 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269  10400213
      "008020"    254.7 "DNK"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464    512600
      "008169"   32.643 "ISR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 1550.5426
      "008544"     1365 "PHL"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 294916.13
      "008546"       29 "NLD"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464   26959.7
      "008594"      297 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269 110550.36
      "009135"     1156 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269  861118.4
      "009213"    .8775 "GBR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  180.9739
      "009501"      .46 "ISR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  84.09129
      "009818"     2873 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269   3626979
      "010137"     3348 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269   4734258
      "010275"     6200 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269  803462.1
      "010622"      207 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269  877183.6
      "010845"   32.925 "GBR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464   42257.9
      "010846"    39.05 "NLD"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  66960.12
      "011217"    107.2 "SWE"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  53016.64
      "011749"    167.6 "SWE"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  70233.21
      "011758" 1.877956 "ZMB" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269 301.97586
      "012368"    256.3 "SWE"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 16555.588
      "012383"     41.3 "NOR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  85449.63
      "012384"   22.425 "GBR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  99318.16
      "012596"    1.426 "ISR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 137.74402
      "012616"     1374 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269  197001.5
      "012673"   2.2345 "GBR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  37898.13
      "012754"     7.89 "NZL"  147.8  8.336 .9934 32.58 35.68  1.453 .6882312456985547 9.975 . . . . . . . . . . .  .898069151324652 167.82806
      "013145"    4.409 "ESP"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464   9349.14
      "013294"   1.3525 "GBR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464    189.35
      "013312"    18.65 "AUS"  145.2 8.5028 .9792 32.22 35.15 1.3242 .7551729346020238 9.975 . . . . . . . . . . . .9064539521392314  59898.04
      "013556"    92.13 "FRA"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 19504.352
      "013683"     8.82 "ESP"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  44433.45
      "013932"    2.683 "LUX"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 3786.1394
      "014140"    4.959 "ESP"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  72313.83
      "014229"    32.68 "ISR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 288.51355
      "014242"    18.17 "AUS"  145.2 8.5028 .9792 32.22 35.15 1.3242 .7551729346020238 9.975 . . . . . . . . . . . .9064539521392314 2689.2476
      "014447"    181.4 "FRA"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  91992.17
      "014538"    138.3 "ISR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 140286.11
      "014605"    18.16 "JEY"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  23259.84
      "014611"    7.315 "JEY"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  2881.149
      "014802"    27.87 "AUS"  146.2 8.5726 .9694 31.27  34.6 1.3015  .768344218209758 9.975 . . . . . . . . . . . .8898380494749957  74049.92
      "014894"    2.225 "GBR" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269  59091.15
      "014924"    6.693 "VGB"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 245.63023
      "015172"    8.665 "NLD"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 11168.804
      "015181"    6.375 "ESP"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  41862.17
      "015319"    13.42 "ESP"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 20186.547
      "015321"   20.125 "ESP"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 21307.387
      "015334"    59.39 "NLD"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 14976.757
      "015362"    29.51 "AUS"  146.2 8.5726 .9694 31.27  34.6 1.3015  .768344218209758 9.975 . . . . . . . . . . . .8898380494749957  98745.38
      "015444"   32.955 "IRL"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  27441.58
      "015482"      149 "FRA"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 254.50854
      "015483"    686.8 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269 1201473.4
      "015498"    144.3 "HKG"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  275878.9
      "015505"        5 "IRL"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 13571.906
      "015508"    195.1 "GBR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  273577.2
      "015509"    6.569 "GBR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 130498.09
      "015511"      150 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269  202744.5
      "015512"     22.6 "NLD"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464      3390
      "015513"       54 "DNK"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464      9369
      "015518"     .177 "DEU" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269 112.10913
      "015522"     .918 "ESP"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 3852.7156
      "015526"       21 "AUT"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464       525
      "015530"     29.7 "HKG"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  80271.42
      "015531"      645 "CHE"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  5550.993
      "015532"      130 "FRA"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 256.46323
      "015535"    67.05 "CHE"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464   395.595
      "015538"    128.4 "NOR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 209137.77
      "015545"     1.42 "GBR"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464       142
      "015547"     5.36 "FRA"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  16814.72
      "015549"    2.734 "ITA"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464 16890.154
      "015552"    214.2 "DNK"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  210711.3
      "015554"     6.67 "GBR" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269  1305.097
      "015562"       42 "CHE"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464    708.75
      "015565"    20.31 "SGP"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464   9613.11
      "015567"      471 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269 221788.33
      "015575"    7.246 "DEU"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  9074.583
      "015576"    17.25 "DEU"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464  23792.46
      "015579"      520 "JPN" 145.25 8.0962 .9583 32.18 35.09 1.4381 .6953619358876295 9.975 . . . . . . . . . . . .8779631255487269  652116.9
      "015590"      900 "CHE"  149.6 9.0803 1.016  32.4 35.81 1.2337 .8105698305909054 9.975 . . . . . . . . . . . .9476876421531464       513
      end
      Last edited by Sebastiaan Emiel; 08 Sep 2017, 10:58.

      Comment


      • #4
        OK. I'm only going to be able to give you a partial solution because I don't know what all of these currency abbreviations are. I have no idea, for example, what sl, or sd, or sz, or ta is (and several others. So I don't know what country to link them to. I will write the solution so that it works for those that I can figure out. I am sure that you will have no difficulty completing it with your knowledge of the currencies and their abbreviations. I also don't recognize all of the country name abbreviations, so there are gaps on that side as well.

        Code:
        local GBR_rate exukus
        local eurozone DEU ESP FRA IRL ITA LUX NLD 
        foreach e of local eurozone {
            local `e'_rate exeuus
        }
        
        levelsof fic, local(countries)
        
        gen USD_stockprice = .
        gen USD_marketcap = .
        
        foreach c of local countries {
            local exchange_rate ``c'_rate'
            if `"`exchange_rate'"' != "" {
                replace USD_stockprice = prccd/`exchange_rate'
                replace USD_marketcap = marketcap/`exchange_rate'
            }
        }
        So the code begins by creating a local macro for each country containing the name of the variable that gives its exchange rate. Some have to be done individually, like GBR, which has its own currency. The eurozone countries can be done in a loop. You will need to extend this part of the code so that every country in your data set is covered. I have omitted many because, either I didn't know what country the three-letter code referred to, or because I didn't know which currency exchange rate variable was correct for that country.

        Once those are done, USD_stockprice and USD_marketcap are created, with all missing values. Then in a loop over all the countries, we apply the appropriate exchange rate. Note that the -if `"`exchange_rate'"' != "" {...}- block is needed here only because my code is incomplete: there are countries for which I have not indicated the appropriate exchange rate. If you are able to assign an exchange rate variable name to every country code that appears in fic, then the two -replace- statements can be run without guarding them by an -if- block. If, at the end, you, too, have some countries for which you do not have an exchange rate variable, then you will need to leave the -if {}- structure as is.

        Comment


        • #5
          Originally posted by Clyde Schechter View Post
          OK. I'm only going to be able to give you a partial solution because I don't know what all of these currency abbreviations are. I have no idea, for example, what sl, or sd, or sz, or ta is (and several others. So I don't know what country to link them to. I will write the solution so that it works for those that I can figure out. I am sure that you will have no difficulty completing it with your knowledge of the currencies and their abbreviations. I also don't recognize all of the country name abbreviations, so there are gaps on that side as well.

          Code:
          local GBR_rate exukus
          local eurozone DEU ESP FRA IRL ITA LUX NLD
          foreach e of local eurozone {
          local `e'_rate exeuus
          }
          
          levelsof fic, local(countries)
          
          gen USD_stockprice = .
          gen USD_marketcap = .
          
          foreach c of local countries {
          local exchange_rate ``c'_rate'
          if `"`exchange_rate'"' != "" {
          replace USD_stockprice = prccd/`exchange_rate'
          replace USD_marketcap = marketcap/`exchange_rate'
          }
          }
          So the code begins by creating a local macro for each country containing the name of the variable that gives its exchange rate. Some have to be done individually, like GBR, which has its own currency. The eurozone countries can be done in a loop. You will need to extend this part of the code so that every country in your data set is covered. I have omitted many because, either I didn't know what country the three-letter code referred to, or because I didn't know which currency exchange rate variable was correct for that country.

          Once those are done, USD_stockprice and USD_marketcap are created, with all missing values. Then in a loop over all the countries, we apply the appropriate exchange rate. Note that the -if `"`exchange_rate'"' != "" {...}- block is needed here only because my code is incomplete: there are countries for which I have not indicated the appropriate exchange rate. If you are able to assign an exchange rate variable name to every country code that appears in fic, then the two -replace- statements can be run without guarding them by an -if- block. If, at the end, you, too, have some countries for which you do not have an exchange rate variable, then you will need to leave the -if {}- structure as is.
          Thanks!


          Comment


          • #6
            Originally posted by Clyde Schechter View Post
            OK. I'm only going to be able to give you a partial solution because I don't know what all of these currency abbreviations are. I have no idea, for example, what sl, or sd, or sz, or ta is (and several others. So I don't know what country to link them to. I will write the solution so that it works for those that I can figure out. I am sure that you will have no difficulty completing it with your knowledge of the currencies and their abbreviations. I also don't recognize all of the country name abbreviations, so there are gaps on that side as well.

            Code:
            local GBR_rate exukus
            local eurozone DEU ESP FRA IRL ITA LUX NLD
            foreach e of local eurozone {
            local `e'_rate exeuus
            }
            
            levelsof fic, local(countries)
            
            gen USD_stockprice = .
            gen USD_marketcap = .
            
            foreach c of local countries {
            local exchange_rate ``c'_rate'
            if `"`exchange_rate'"' != "" {
            replace USD_stockprice = prccd/`exchange_rate'
            replace USD_marketcap = marketcap/`exchange_rate'
            }
            }
            So the code begins by creating a local macro for each country containing the name of the variable that gives its exchange rate. Some have to be done individually, like GBR, which has its own currency. The eurozone countries can be done in a loop. You will need to extend this part of the code so that every country in your data set is covered. I have omitted many because, either I didn't know what country the three-letter code referred to, or because I didn't know which currency exchange rate variable was correct for that country.

            Once those are done, USD_stockprice and USD_marketcap are created, with all missing values. Then in a loop over all the countries, we apply the appropriate exchange rate. Note that the -if `"`exchange_rate'"' != "" {...}- block is needed here only because my code is incomplete: there are countries for which I have not indicated the appropriate exchange rate. If you are able to assign an exchange rate variable name to every country code that appears in fic, then the two -replace- statements can be run without guarding them by an -if- block. If, at the end, you, too, have some countries for which you do not have an exchange rate variable, then you will need to leave the -if {}- structure as is.
            I was unable to check it properly until today. However, when I ran the code the following occurs:

            The first row of my real dataset has a NLD (=eurozone) observation. Your code currently correctly runs for that observation. Only, after it does that, it selects the euro-exchange rate for all consecutive variables - even if they are not in the eurozone, or have even had a combination listed before.

            A test by sorting it by fic so that ARE comes first, shows the same result: eurozone var is selected for all.

            I think the error lies in this bit of your code:
            Code:
            foreach c of local countries {
             local exchange_rate ``c'_rate' if `"`exchange_rate'"' != "" { replace USD_stockprice = prccd/`exchange_rate' replace USD_marketcap = marketcap/`exchange_rate' } }
            Since it doesnt have an additional filter to make sure it only changes if the FIC matches.

            I currently tested something with this code:

            Code:
            clear
            use stocks28
            sort fic gvkey
            drop exusir exusnz exusal
            
            drop if fic == "ARE" | fic == "ARG"
            
            local GBR_rate exukus
            local AUS_rate exalus
            local eurozone DEU ESP FRA IRL ITA LUX NLD
            foreach e of local eurozone {
                local `e'_rate exeuus
            }
            //
            levelsof fic, local(countries)
            
            gen USD_stockprice = .
            gen USD_marketcap = .
            gen USD_totalrepo = .
            
            
            foreach c of local countries {
                local exchange_rate ``c'_rate'
                di ``c'_rate'
                if `"`exchange_rate'"' != "" {
                    replace USD_stockprice = prccd/`exchange_rate'
                    replace USD_marketcap = marketcap/`exchange_rate'
                }
            }
            //
            As I observed the results, it seems that the IF-condition inside the last foreach is indeed triggered by every single country identifier at the moment. So, it rewrites all the USD_* with those of the final country done (which happens to be a euro country).

            This seems to bring us to a similar situation as I had when I initially started. Only, this time instead of getting the correct exchange rate, we need to match the IF-function properly.

            Simply changing:

            Code:
            foreach c of local countries {
                local exchange_rate ``c'_rate'
                di ``c'_rate'
                if `"`exchange_rate'"' != "" {
                    replace USD_stockprice = prccd/`exchange_rate'
                    replace USD_marketcap = marketcap/`exchange_rate'
                }
            }
            
            to
            
            foreach c of local countries {
                local exchange_rate ``c'_rate'
                di ``c'_rate'
                if `"`exchange_rate'"' != "" & fic == `c' {
                    replace USD_stockprice = prccd/`exchange_rate'
                    replace USD_marketcap = marketcap/`exchange_rate'
                }
            }
            doesnt work.

            How do you suggest to fix it?

            EDIT:
            Code:
            foreach c of local countries {
                local exchange_rate ``c'_rate'
                di ``c'_rate'
                di "`c'"
                if fic == "`c'" {
                di "testing123"
                }
                if `"`exchange_rate'"' != "" & fic == "`c'" {
                    replace USD_stockprice = prccd/`exchange_rate'
                    replace USD_marketcap = marketcap/`exchange_rate'
                }
            }
            here, the testing123 only shows up for the first combo to run (AUS). And, now, with the if-condition adjusted, everything is divided by the aus currency pair: it is also the only one for which the if function now holds.
            Last edited by Sebastiaan Emiel; 09 Sep 2017, 10:19.

            Comment


            • #7
              OK, sorry. I made a mistake in my original code. Your attempts to correct it are failing because you are using the -if- command when you should be using the -if- condition. The correct code would be:

              Code:
              local GBR_rate exukus
              local eurozone DEU ESP FRA IRL ITA LUX NLD 
              foreach e of local eurozone {
                  local `e'_rate exeuus
              }
              
              levelsof fic, local(countries)
              
              gen USD_stockprice = .
              gen USD_marketcap = .
              
              foreach c of local countries {
                  local exchange_rate ``c'_rate'
                  if `"`exchange_rate'"' != "" {
                      replace USD_stockprice = prccd/`exchange_rate' if fic == `"`c'"'
                      replace USD_marketcap = marketcap/`exchange_rate' if fic == `"`c'"'
                  }
              }
              You will find that this uses the given exchange rate only in the country that is being treated within each iteration of the loop and leaves you with correct results.

              I'm sorry for that error.

              So, let's review the difference between the -if- command, -if whatever { do something } -, and the -if- qualifier -some_command if whatever-.

              The -if- command checks the condition as a global property of the Stata state at the moment. That condition may refer to system parameters, the values of local macros, global properties of the data set, really, anything. If the condition is found to be true, then it executes the command(s) between the curly braces and applies them to the entire data set (unless the commands themselves contain -if- conditions). In other words, the -if- command does not in any way select particular observations for its actions: it is all or nothing.

              By contrast, the -if- qualifier goes observation by observation through the data set and determines for which observations the condition holds. The command containing the -if- qualifier is then applied to only those observations.

              Now, you can get some confusing situations. Suppose an -if- command refers to properties of a variable. For example, what if you write:

              Code:
              if fic == "NLD" {
                  do something
              }
              This presents Stata with a quandary, because it has to determine whether -fic == "NLD"- is globally true or false and then, accordingly, do, or not do, "something." Stata resolves all such dilemmas by presuming that fic, in this context, means fic[1]. So it looks to see if the first observation has fic == "NLD", and if it does, then the condition is considered globally true, and "something" is done. Otherwise, "something" is not done.

              I think you will find that these considerations explain why my incorrect code in #2 did what it did, and why you got the results you got from your various attempts to correct it.

              I do believe the code I've posted in this thread is correct. Please let me know if you encounter difficulties with it, but I don't think you will. Again, my apologies for the time you wasted trying to fix my error.

              Comment


              • #8
                Originally posted by Clyde Schechter View Post
                OK, sorry. I made a mistake in my original code. Your attempts to correct it are failing because you are using the -if- command when you should be using the -if- condition. The correct code would be:

                Code:
                local GBR_rate exukus
                local eurozone DEU ESP FRA IRL ITA LUX NLD
                foreach e of local eurozone {
                local `e'_rate exeuus
                }
                
                levelsof fic, local(countries)
                
                gen USD_stockprice = .
                gen USD_marketcap = .
                
                foreach c of local countries {
                local exchange_rate ``c'_rate'
                if `"`exchange_rate'"' != "" {
                replace USD_stockprice = prccd/`exchange_rate' if fic == `"`c'"'
                replace USD_marketcap = marketcap/`exchange_rate' if fic == `"`c'"'
                }
                }
                You will find that this uses the given exchange rate only in the country that is being treated within each iteration of the loop and leaves you with correct results.

                I'm sorry for that error.

                So, let's review the difference between the -if- command, -if whatever { do something } -, and the -if- qualifier -some_command if whatever-.

                The -if- command checks the condition as a global property of the Stata state at the moment. That condition may refer to system parameters, the values of local macros, global properties of the data set, really, anything. If the condition is found to be true, then it executes the command(s) between the curly braces and applies them to the entire data set (unless the commands themselves contain -if- conditions). In other words, the -if- command does not in any way select particular observations for its actions: it is all or nothing.

                By contrast, the -if- qualifier goes observation by observation through the data set and determines for which observations the condition holds. The command containing the -if- qualifier is then applied to only those observations.

                Now, you can get some confusing situations. Suppose an -if- command refers to properties of a variable. For example, what if you write:

                Code:
                if fic == "NLD" {
                do something
                }
                This presents Stata with a quandary, because it has to determine whether -fic == "NLD"- is globally true or false and then, accordingly, do, or not do, "something." Stata resolves all such dilemmas by presuming that fic, in this context, means fic[1]. So it looks to see if the first observation has fic == "NLD", and if it does, then the condition is considered globally true, and "something" is done. Otherwise, "something" is not done.

                I think you will find that these considerations explain why my incorrect code in #2 did what it did, and why you got the results you got from your various attempts to correct it.

                I do believe the code I've posted in this thread is correct. Please let me know if you encounter difficulties with it, but I don't think you will. Again, my apologies for the time you wasted trying to fix my error.
                Thanks! This does indeed work.

                No problem regarding the error in the previous code; it was a minor thing I should have been able to fix.

                The thing you just explained does answer a few things I was wondering about.

                Comment


                • #9
                  Though there is one thing I do wonder:

                  Code:
                  local eurozone DEU ESP FRA IRL ITA LUX NLD
                  foreach e of local eurozone {
                      local `e'_rate exeuus
                  }
                  correctly sets the euro-pair as currency for the euro countries.
                  however, before the introduction of the euro, a different pair needs to be picked up. I'm currently working with a subset (year 2016) of my data to make everythign process faster while testing it.

                  If I were to do something along the lines of the following:

                  Code:
                  local eurozone DEU ESP FRA IRL ITA LUX NLD
                  foreach e of local eurozone {
                      local `e'_rate exeuus
                  }
                  
                  replace DEU_rate exgeus if datadate < INTRO
                  replace FRA_rate exfrus if datadate < INTRO
                  //....
                  
                  // ; or, if this is the hypothetically correct way:
                  
                  replace `DEU_rate' exgeus if datadate < INTRO
                  replace `FRA_rate' exfrus if datadate < INTRO
                  //....
                  I'm not sure if replacing local variables like that would work.

                  a simple test with:

                  Code:
                   li gvkey datadate in 1/30 if datadate > mdy(5,30,2016)
                  
                       +--------------------+
                       |  gvkey    datadate |
                       |--------------------|
                    1. | 001166   31dec2016 |
                    2. | 001491   31dec2016 |
                    3. | 001855   31dec2016 |
                    4. | 001932   31dec2016 |
                    5. | 002018   31dec2016 |
                       |--------------------|
                    6. | 002162   31dec2016 |
                    7. | 002410   31dec2016 |
                    9. | 002721   31dec2016 |
                   10. | 004311   31dec2016 |
                   12. | 005180   31dec2016 |
                       |--------------------|
                   15. | 006203   31dec2016 |
                   17. | 006506   31dec2016 |
                   25. | 008020   31dec2016 |
                   26. | 008169   31dec2016 |
                   27. | 008544   31dec2016 |
                       |--------------------|
                   28. | 008546   31dec2016 |
                  shows that it in principle would indeed work with normal variables. I'm just not that familiar with the properties of local vars, and just mainly use them in loops.
                  Last edited by Sebastiaan Emiel; 09 Sep 2017, 11:02.

                  Comment


                  • #10
                    You're trying to treat local macros as if they were variables. You can't "replace" a local macro. You can overwrite it, but I don't think that's the best way to do it here.

                    I would approach this by creating a separate local macro for each of the Eurozone countries that gives the exchange rate for its previous currency. Again, I'm at a loss to do this completely because I don't understand the abbreviations here, but let me assume that exfrus gives the exchange rate for the French Franc and that fic "FRA" is France. Similarly, I'll guess that exitus is the exchange rate for the Italian Lira and that "ITA" is the code for Italy. You can correct these if they're wrong, and then expand the code to include the other Eurozone countries:

                    Code:
                    local GBR_rate exukus
                    local eurozone DEU ESP FRA IRL ITA LUX NLD
                    foreach e of local eurozone {
                        local `e'_rate exeuus
                    }
                    local FRA_rate_prior exfrus
                    local ITA_rate_prior exitus
                    
                    local INTRO = td(1jan1999)
                    
                    levelsof fic, local(countries)
                    
                    gen USD_stockprice = .
                    gen USD_marketcap = .
                    
                    foreach c of local countries {
                        local exchange_rate ``c'_rate'
                        if `"`exchange_rate'"' != "" {
                            replace USD_stockprice = prccd/`exchange_rate' if fic == `"`c'"'
                            replace USD_marketcap = marketcap/`exchange_rate' if fic == `"`c'"'
                        }
                        local prior_rate ``c'_rate_prior'
                        if `"`prior_rate'" != "" {
                            replace USD_stockprice = prccd/`prior_rate' if fic == `"`c'"' & datadate < `INTRO'
                            replace USD_marketcap = marketcap/`prior_rate' if fic == `"`c'"' & datadate < `INTRO'
                        }
                    }
                    Note: Because I do not have example data that contains both the exchange rate variables and the datadate variable, this code is not tested. So beware of typos and possibly other errors, though I have tried to be careful.

                    Let me also add that I think this entire process is greatly complicated by the data structure you are using. Perhaps the data was given to you this way, and you have no choice. But just for the sake of how one might do this kind of thing in the future, I would not have a data set like this in the first place. I would start with two data sets. One of the contains the information about the individual firms (with the variables gvkey prccd, fic and marketcap, datadate). Then I would have a separate data set with exchange rates, organized rather differently. My data set with the exchange rates would contain four variables: fic (coded exactly as the fic variable is in the stock data set), start_date, end_date, and ex_rate. The variables start_date and end_date would refer to time periods for which that value of the exchange rate prevailed for that country. Then I would use Robert Picard's -rangejoin- command (from SSC) to put the two data sets together, pairing observations in the exchange rate data set with observations in the stock data set where the fic matched and where datadate fell between start_date and end_date. The end result would be a data set in which you have gvkey, prccd, fic, marketcap, and then the single correct exchange rate for that country on that date (and a few other unneeded variables that you could then drop.) Then you wouldn't need all these macros and ifs and ands and buts. You would just calculate the USD_stockprice and USD_marketcap with a single -gen- command for each.



                    Comment

                    Working...
                    X