# 使用Jupyter制作Slides的介绍

王成军

wangchengjun@nju.edu.cn

计算传播网 http://computational-communication.com

# RISE: "Live" Reveal.js Jupyter/IPython Slideshow Extension
https://github.com/damianavila/RISE

# Installation
- Downnload from https://github.com/damianavila/RISE
- open your teminal, cd to the RISE folder, e.g.,

    >## cd  /github/RISE/

- To install this nbextension, simply run

    >## python setup.py install

from the RISE repository.

In the notebook toolbar, a new button ("Enter/Exit Live Reveal Slideshow") will be available.

The notebook toolbar also contains a "Cell Toolbar" dropdown menu that gives you access to metadata for each cell. If you select the Slideshow preset, you will see in the right corner of each cell a little box where you can select the cell type (similar as for the static reveal slides with nbconvert).

# 将ipynb文件转为slides.html
- download the reveal.js from Github https://github.com/hakimel/reveal.js
- generate html using the following code
- put the generated html into the reveal.js folder
- open the html using chrome

    chengjuns-MacBook-Pro:~ chengjun$ cd github/cjc/code/

    chengjuns-MacBook-Pro:code chengjun$ jupyter nbconvert slides.ipynb --to slides --post serve

# 批量生成slides.html¶
    chengjuns-MacBook-Pro:~ chengjun$ cd github/cjc/code/

    chengjuns-MacBook-Pro:code chengjun$ jupyter nbconvert *.ipynb --to slides

# 数学公式
$E = MC^2$

```latex
%%latex
\begin{align}
a = \frac{1}{2}\\
\end{align}
```

\begin{align}
a = \frac{1}{2}\\
\end{align}

# 程序代码

```python
print 'hello world'
```

    hello world

```python
for i in range(10):
    print i
```

    0
    1
    2
    3
    4
    5
    6
    7
    8
    9

```python
# get a list of all the available magics
```

```python
% lsmagic
```

    Available line magics:
    %alias  %alias_magic  %autocall  %automagic  %autosave  %bookmark  %cat  %cd  %clear  %colors  %config  %connect_info  %cp  %debug  %dhist  %dirs  %doctest_mode  %ed  %edit  %env  %gui  %hist  %history  %install_default_config  %install_ext  %install_profiles  %killbgscripts  %ldir  %less  %lf  %lk  %ll  %load  %load_ext  %loadpy  %logoff  %logon  %logstart  %logstate  %logstop  %ls  %lsmagic  %lx  %macro  %magic  %man  %matplotlib  %mkdir  %more  %mv  %notebook  %page  %pastebin  %pdb  %pdef  %pdoc  %pfile  %pinfo  %pinfo2  %popd  %pprint  %precision  %profile  %prun  %psearch  %psource  %pushd  %pwd  %pycat  %pylab  %qtconsole  %quickref  %recall  %rehashx  %reload_ext  %rep  %rerun  %reset  %reset_selective  %rm  %rmdir  %run  %save  %sc  %set_env  %store  %sx  %system  %tb  %time  %timeit  %unalias  %unload_ext  %who  %who_ls  %whos  %xdel  %xmode

    Available cell magics:
    %%!  %%HTML  %%SVG  %%bash  %%capture  %%debug  %%file  %%html  %%javascript  %%latex  %%perl  %%prun  %%pypy  %%python  %%python2  %%python3  %%ruby  %%script  %%sh  %%svg  %%sx  %%system  %%time  %%timeit  %%writefile

    Automagic is ON, % prefix IS NOT needed for line magics.

```python
% env
# to list your environment variables.
```

    {'Apple_PubSub_Socket_Render': '/private/tmp/com.apple.launchd.Cti3IOL0XG/Render',
     'CLICOLOR': '1',
     'DISPLAY': '/private/tmp/com.apple.launchd.GQAU1RS6KM/org.macosforge.xquartz:0',
     'GIT_PAGER': 'cat',
     'HOME': '/Users/chengjun',
     'JPY_PARENT_PID': '84860',
     'LANG': 'en_US.UTF-8',
     'LC_ALL': 'en_US.UTF-8',
     'LC_CTYPE': 'UTF-8',
     'LOGNAME': 'chengjun',
     'PAGER': 'cat',
     'PATH': '/Users/chengjun/anaconda/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/local/git/bin:/usr/texbin',
     'PWD': '/Users/chengjun',
     'SECURITYSESSIONID': '186a5',
     'SHELL': '/bin/bash',
     'SHLVL': '2',
     'SSH_AUTH_SOCK': '/private/tmp/com.apple.launchd.VNCcz4m0az/Listeners',
     'TERM': 'xterm-color',
     'TERM_PROGRAM': 'Apple_Terminal',
     'TERM_PROGRAM_VERSION': '343',
     'TERM_SESSION_ID': 'FDFD985A-CDD6-415E-A3B0-E8A2A05CC9B4',
     'TMPDIR': '/var/folders/l6/ntr5b4610hx38gy0_2xp7ngh0000gn/T/',
     'USER': 'chengjun',
     'XPC_FLAGS': '0x0',
     'XPC_SERVICE_NAME': '0',
     '_': '/Users/chengjun/anaconda/python.app/Contents/MacOS/python',
     '__CF_USER_TEXT_ENCODING': '0x1F5:0x0:0x0'}

```python
%prun
```

```python
%time range(10)
```

    CPU times: user 11 µs, sys: 9 µs, total: 20 µs
    Wall time: 21 µs

    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

```python
%timeit range(100)
```

    The slowest run took 295.47 times longer than the fastest. This could mean that an intermediate result is being cached.
    1000000 loops, best of 3: 748 ns per loop

!: to run a shell command. E.g., ! pip freeze | grep pandas to see what version of pandas is installed.

```python
! cd /Users/chengjun/github/
```

```python
% matplotlib inline
# to show matplotlib plots inline the notebook.
import matplotlib.pyplot as plt

plt.plot(range(10), range(10), 'r-o')
plt.show()
```

# This is the End.

## Thanks for your attention.


```python
try:
    import openmdao.api as om
    import dymos as dm
except ImportError:
    !python -m pip install openmdao[notebooks]
    !python -m pip install dymos[docs]
    import openmdao.api as om
    import dymos as dm
```

# Defining ODEs

Optimal control problems contain ordinary differential equations (ODE) or differential algebraic equations (DAE) that dictate the evolution of the state of the system.
Typically this evolution occurs in time, and the ODE represents equations of motion (EOM).
The equations of motion can define a variety of systems, not just mechanical ones.
In other fields they are sometimes referred to as *process equations*.

\begin{align}
    \dot{\bar{x}} = f_{ode}(\bar{x},t,\bar{u},\bar{d})
\end{align}

To represent EOM, Dymos uses a standard OpenMDAO System (a Group or Component).
This System takes some set of variables as input and computes outputs that include the time-derivatives of the state variables $\bar{x}$.
The ODE may also be a function of the current time $t$.

Finally, the dynamics may be subject to some set of controllable parameters.
In Dymos these are broken into the dynamic controls $\bar{u}$ and the static parameters $\bar{d}$.

##  System Options

ODE Systems in Dymos need provide values at numerous points in time we call nodes.
For performance reasons, it's best if it can do so using vectorized mathematical operations to compute the values simultaneously rather than using the loop to perform the calculation at each node.
Different optimal control transcriptions will need to have computed ODE values at different numbers of nodes, so each ODE system in Dymos is required to support the option `num_nodes`, which is defined in the `initialize` method.

ODE system may define initial options as well.
Since these options in OpenMDAO are typically provided as arguments to the instantiation of the ODE system, the user has the ability to provide additional input keyword arguments using the `ode_init_kwargs` option on Phase.

## Variables of the Optimal Control Problem

Dymos needs to know how state, time, and control variables are to be connected to the System, and needs to know which outputs to use as state time-derivatives.

### Time

The following time options can be set via the `set_time_options` method of Phase:

```python
from IPython.display import display, HTML, IFrame, Code
from dymos.phase.options import TimeOptionsDictionary
obj = TimeOptionsDictionary()
display(HTML(obj.to_table(fmt='html')))
```

### States

States have the following options set via the `add_state` and `set_state_options` methods of Phase:

```python
from dymos.phase.options import StateOptionsDictionary
obj = StateOptionsDictionary()
display(HTML(obj.to_table(fmt='html')))
```

###  Controls

Inputs to the ODE which are to be dynamic controls are added via the `add_control` and `set_control_options` methods of Phase. The available options are as follows:

```python
from dymos.phase.options import ControlOptionsDictionary
obj = ControlOptionsDictionary()
display(HTML(obj.to_table(fmt='html')))
```

###  Parameters

Inputs to the ODE which are non-time-varying can be specified using the `add_parameter` method of Phase.
Parameters may be used as design variables (by setting `opt = True`), or they may be connected to an output external to the Phase or Trajectory.
The available options are as follows:

```python
from dymos.phase.options import ParameterOptionsDictionary
obj = ParameterOptionsDictionary()
display(HTML(obj.to_table(fmt='html')))
```

By default, Dymos assumes that the ODE is defined such that a value of the parameter is provided at each node.
This makes it easier to define the partials for the ODE in a way such that some inputs may be used interchangeably as either controls or parameters.
If an ODE input is only to be used as a static variable (and not sized as `num_nodes` in the first dimension), then the user may specify option `static_target = True` to override this behavior.

### Tagging Variables

Dymos will also automatically find and add any states that have been declared in components in the ODE. The syntax
for declaring them is as follows.

```python
self.add_output('vdot', val=np.zeros(nn), desc='acceleration magnitude', units='m/s**2',
                tags=['dymos.state_rate_source:v', 'dymos.state_units:m/s'])
```

The state is defined by adding tags to the state rate's output.
The tag 'dymos.state_rate_source:v' declares that 'v' is the state for which this output ('vdot') is the rate source.
You can also optionally use a tag in the format 'dymos.state_units:m/s' to define units for that state.
If you need to set any other options, then use `set_state_options` at the phase level.

Inputs which are sized as 'static' in the ODE (the first dimension is _not_ the number of nodes), must be made known to Dymos when using them as parameters.
This is normally accomplished with the 'static_target=True' option when calling add_parameter.
To avoid repetitive use of this option, users can add the tag 'dymos.static_target' to any input which should always be considered static.
When connecting to multiple targets, a 'dymos.static_target' tag on one of them will result in all of them being considered static.
Inputs tagged with 'dymos.static_target' cannot be used as controls or polynomial controls.

| Tag                                  | Applies to | Description                                                                                |
|--------------------------------------|------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| dymos.state_rate_source:{state_name} | Outputs    | Specifies that the tagged output provides the rate used to integrate the state of the given name.                                                                                |
| dymos.state_units:{units}            | Outputs    | Specifies the default units to be used for the state whose rate is provided by the tagged output. May only be used on outputs also tagged with 'dymos.state_rate_source:{state_name}'.                                      |
| dymos.static_target                  | Inputs     | Specifies that the input is _not_ shaped with num_nodes as the first dimension. This effects the way in which parameters are connected to the input. Inputs tagged with 'dymos.static_target' cannot be used as controls.   |

## Automatic target detection

Dymos will attempt to automatically connect variables to targets in the same name if those targets
exist at the top-level of the ODE and have the same name as the state, control, parameter, or 'time'.

## Vectorizing the ODE

In addition to specifying the ODE Options, a system used as an ODE is required to have a metadata
entry called `num_nodes`.  When evaluating the dynamics, these systems will receive time, states,
controls, and other inputs as *vectorized* values, where item in the vector represents the variable
value at a discrete time in the trajectory.

The nodes are discretization or collocation locations in the polynomials which represent
each segment.  The number of nodes in a given phase (to be evaluated by the ODE system) is determined
by the number of segments in the phase and the polynomial order in each segment.  When Dymos instantiates
the ODE system it provides the total number of nodes at which evaluation is required to the ODE system.
Thus, at a minimum, the `initialize` method of components for an ODE system typically look something
like this:

The inputs and outputs of the system are expected to provide a scalar or dimensioned
value *at each node*.  Vectorization of the component via numpy adds a significant performance increase
compared to using a for loop to cycle through calculations at each node.  It's important to remember
that vectorized data is going to be coming in, this is especially important for defining partials.
From the perspective of the ODE system, the outputs at some time `t` only depend on the values
of the input variables at time `t`.  When the output variables are scalar at any given time, this
results in components whose Jacobian matrices are diagonal.  This large degree of sparsity leads
to computational advantages when using sparse-aware optimizers like SNOPT.  Users should declare
the partial derivatives of their components to be sparse (by specifying nonzero rows and columns)
whenever possible.

```python
class MyODESystem(om.ExplicitComponent):

    def initialize(self):
        self.metadata.declare('num_nodes', types=int)
```

For example, if `MyODEComponent` is to compute the linear function $y = a * x + b$ then the
setup, compute, and compute partials methods might look like this:

```python
def setup(self):
    nn = self.metadata['num_nodes']

    self.add_input('a', shape=(nn,), units='m')
    self.add_input('x', shape=(nn,), units='1/s')
    self.add_input('b', shape=(nn,), units='m/s')

    self.add_output('y', shape=(nn,), units='m/s')

    r = c = np.arange(nn)
    self.declare_partials(of='y', wrt='a', rows=r, cols=c)
    self.declare_partials(of='y', wrt='x', rows=r, cols=c)
    self.declare_partials(of='y', wrt='b', rows=r, cols=c, val=1.0)

def compute(self, inputs, outputs):
    a = inputs['a']
    x = inputs['x']
    b = inputs['b']

    outputs['y'] = a * x + b

def compute_partials(self, inputs, outputs, partials):
    a = inputs['a']
    x = inputs['x']
    b = inputs['b']

    partials['y', 'a'] = x
    partials['y', 'x'] = a
```

A few things to note here.  We can use the `shape` or `val` argument of `add_input` and `add_output`
to dimension each variable.  In this case each variable is assumed to be a scalar at each point in
time (each node).  We use the `rows` and `cols` arguments of `declare_partials` to provide the sparsity.
Here using `arange(nn)` for both gives us a diagonal jacobian with `nn` rows and `nn` columns.  Since
the number of nonzero values in the jacobian is `nn`, we only need to provide `nn` values in the
`compute_partials` method.  It will automatically fill them into the sparse jacobian matrix, in
row-major order.

In this example, the partial of `y` with respect to `b` is linear, so we can simply provide it in
the `declare_partials` call rather than reassigning it every time `compute_partials` is called.
The provided scalar value of `1.0` is broadcast to all `nn` values of the Jacobian matrix.

## Dimensioned Inputs and Outputs

The above example assumes all inputs and outputs are scalar at each node.  Sometimes the user may
encounter a situation in which the inputs and/or outputs are vectors, matrices, or tensors at
each node.  In this case the dimension of the variable is `num_nodes`, with the dimension of the
variable at a single node filling out the remaining indices. A 3-vector is thus dimensioned
`(num_nodes, 3)`, while a 3 x 3 matrix would be sized `(num_nodes, 3, 3)`.

##  Non-Vector Inputs

Declaring inputs as vectors means that they have the potential to be used either as parameters or as dynamic controls which can assume a different value at each node.
For some quantities, such as gravitational acceleration in the Brachistochrone example, we can assume that the value will never need to be dynamic.
To accommodate this, parameters can be declared static with the argument `static_target=True`.
This prevents Dymos from "fanning out" the static value to the *n* nodes in the ODE system.

##  Providing the ODE to the Phase

Phases in Dymos are instantiated with both the `ode_class` and the `transcription` to be used.
Internally, Dymos needs to instantiate the ODE multiple times.
This instantiation takes the form:

```python
ode_instance = ode_class(num_nodes=<int>, **ode_init_kwargs)
```

This allows an OpenMDAO ExecComp to be used as an ODE via a lambda.
For instance, the brachistochrone ODE can be written as:

```python
ode = lambda num_nodes: om.ExecComp(['vdot = g * cos(theta)',
                                     'xdot = v * sin(theta)',
                                     'ydot = -v * cos(theta)'],
                                    g={'value': 9.80665, 'units': 'm/s**2'},
                                    v={'shape': (num_nodes,), 'units': 'm/s'},
                                    theta={'shape': (num_nodes,), 'units': 'rad'},
                                    vdot={'shape': (num_nodes,),
                                          'units': 'm/s**2',
                                          'tags': ['state_rate_source:v']},
                                    xdot={'shape': (num_nodes,),
                                          'units': 'm/s',
                                          'tags': ['state_rate_source:v']},
                                    ydot={'shape': (num_nodes,),
                                          'units': 'm/s',
                                          'tags': ['state_rate_source:v']},
                                    has_diag_partials=True)

t = dm.Radau(num_segments=10, order=3)
phase = dm.Phase(ode_class=ode, transcription=t)
```

Note the use of `has_diag_partials=True` to provide more efficient graph coloring for the derivatives.

In theory, this also means you can implement Python's `__call__` method for an ODE.
The following code will return a copy of the brachistochrone ODE with the appropriate number of nodes.
Note that the implementation below does not deal with any options provided via the `ode_init_kwargs`.

```python
class CallableBrachistochroneODE(om.ExplicitComponent):

    def initialize(self):
        self.options.declare('num_nodes', types=int)

    def __call__(self, num_nodes, **kwargs):
        from copy import deepcopy
        ret = deepcopy(self)
        ret.options['num_nodes'] = num_nodes
        return ret

    def setup(self):
        nn = self.options['num_nodes']

        # Inputs
        self.add_input('v', val=np.zeros(nn), desc='velocity', units='m/s')

        self.add_input('g', val=9.80665, desc='grav. acceleration', units='m/s/s')

        self.add_input('theta', val=np.ones(nn), desc='angle of wire', units='rad')

        self.add_output('xdot', val=np.zeros(nn), desc='velocity component in x', units='m/s',
                        tags=['state_rate_source:x', 'state_units:m'])

        self.add_output('ydot', val=np.zeros(nn), desc='velocity component in y', units='m/s',
                        tags=['state_rate_source:y', 'state_units:m'])

        self.add_output('vdot', val=np.zeros(nn), desc='acceleration magnitude', units='m/s**2',
                        tags=['state_rate_source:v', 'state_units:m/s'])

        self.declare_partials(of='*', wrt='*', method='cs')
        self.declare_coloring(wrt='*', tol=1.0E-12)
```

An instance of the above ODE can then be provided to the phase upon instantiation.

```python
ode = CallableBrachistochroneODE(num_nodes=1)
t = dm.Radau(num_segments=10, order=3)
phase = dm.Phase(ode_class=ode, transcription=t)
```

This can potentially lead to unintended behavior if multiple copeis of the ODE are intended to share data.
See [the Python docs](https://docs.python.org/3/library/copy.html) for some of the limitations of deepcopy.


---
Project Microeconometrics | Summer 2020, M.Sc. Economics, University of Bonn | [Vincent Selz](https://github.com/VincentSelz)

# Replication of “A Structural Analysis of Disappointment Aversion in a Real Effort Competition” by David Gill and Victoria Prowse (2012)
---

### Miscellaneous

In this notebook, I replicate the findings of

> Gill, David, and Victoria Prowse. 2012. A Structural Analysis of Disappointment Aversion in a Real Effort Competition. *American Economic Review*, 102 (1): 469-503.

The original paper and the corresponding data and code can be found [here](https://www.aeaweb.org/articles?id=10.1257/aer.102.1.469). For their analysis, the authors use Stata and Matlab.

To view this notebook:

* Recommended, is to clone the repository and to locally view it via jupyter notebook.
* Unfortunately, the notebook cannot be inspected with mybinder or nbviewer, since rendering it returns an error.

Aside, from the accompanying text, the results are labelled into three categories:

    Successful replication: All the results are replicated.

    Extension: The results of the paper are expanded.

    Notes: Pointers to the workflow.

Generally, most code, with the exception of R code, is moved to the auxiliary files to enhance readability.

Table of Contents

1  Introduction

2  Experimental Design

2.1  Slider Task

2.2  Experimental Procedure

3  Theoretical Predictions

3.1  Canonical Model

3.2  Disappointment Aversion

4  Identification Strategy

5  Empirical Results

5.1  Data Exploration

5.2  Reduced Form Analysis

5.2.1  Model

5.2.2  Results

5.2.3  Fixed vs. Random Effects

5.2.4  Further Investigation

5.3  Structural Model

5.3.1  Empirical Specification

5.3.2  Method of Simulated Moments

5.3.3  Empirical Moments

5.3.4  Weighting Matrix

5.3.5  Simulation

5.3.6  Further Steps

6  Critical Assessment

7  Appendix

7.1  Effort Distribution Per Round

7.2  Prize Distribution

7.3  Moment Computation Specifications

8  References

```python
%load_ext rpy2.ipython
%load_ext autoreload
%autoreload 2
%matplotlib inline

from datetime import datetime
from IPython.display import HTML
from IPython.display import display
from linearmodels.panel import PanelOLS
from scipy.stats import chisquare
import numpy as np
import pandas as pd
import pandas.io.formats.style
import respy as rp
import scipy.stats as stats
import seaborn as sns
import matplotlib as plt
import matplotlib.pyplot as pyplt

from auxiliary.helper import *
from auxiliary.msm import *
from auxiliary.overview import *
from auxiliary.simulation import *

# Displays floats only to the third decimal
pd.set_option("display.precision", 3)
pd.set_option('display.max_colwidth', -1)
```

    /Users/vincentselz/opt/anaconda3/lib/python3.7/site-packages/respy/_numba.py:2: NumbaDeprecationWarning: An import was requested from a module that has moved location.
    Import requested from: 'numba.cgutils', please update to use 'numba.core.cgutils' or pin to Numba version 0.48.0. This alias will not be present in Numba version 0.50.0.
      from numba import cgutils

```r
%%R

library(plm)
library(haven)
library(msm)
library(stargazer)
library(car)
```

---
# Introduction
---
Gill & Prowse (2012) use a real effort tournament in a laboratory experiment to test experimentally whether agents are disappointment averse. Pairs of subjects need to complete a real effort task sequentially. The payoff is determined by a lottery where the probabilities of winning are linear in the difference in the agent's efforts. Hence, in the standard framework, the effort of the *First Mover* should not impact the choice of effort for the *Second Mover*. Yet, as predicted by Gill & Prowse's model of disappointment aversion, subjects exhibit a discouragement effect, where high effort by the *First Mover*, impacts the effort by the *Second Mover* negatively. Their effort choices are strategic substitutes.

Gill & Prowse (2012) use a reduced form **random effects panel regression** to estimate potential effects. Given the substantial variation induced by their experimental design, they subsequently use the **Method of Simulated Moments (MSM)** to estimate the parameters of a structural model of disappointment aversion. This structural model allows them to estimate the strength of disappointment aversion on average but also to estimate the extent of heterogeneity in disappointment aversion across the population.

This notebook will attempt to replicate the results of Gill & Prowse (2012) and will further add extensions in data exploration and the reduced form analysis. If possible Python is used to replicate the findings, yet if not possible R is used. For instance, the random effects regression with the common Python packages did yield close results but did not reproduce the same numbers reported in the paper. Unfortunately, I was not capable to reproduce the results of the structural estimation. Nonetheless, the steps taken towards the estimation of structural model are outlined. For this implementation, the documentation by [respy](https://respy.readthedocs.io/en/latest/) is closely followed.

In the following section, the experimental design is shown. Next, the identification strategy is discussed, followed by the theoretical predictions. Then, the empirical analysis and extension thereof are shown. Lastly, the paper will be critically assessed.

---
#  Experimental Design
---
The six experimental session took place from late February to early March 2009 at the Nuffield Centre for Experimental Social Sciences (CESS) in Oxford. Per session twenty subjects participated in the study, leading to a subject pool of 120 participants in total. Each of them were paid a show-up fee of 4 pounds and went on to earn a further 10 pounds on average.

## Slider Task

The slider task consists of a single screen displaying numerous sliders. The number and position of sliders is not varied across subjects or across repetition of the task. At first, the sliders who range from 0 to 100 are placed at 0. It is possible to place the slider at every integer position between 0 and 100. The integer position is displaced next to the slider. The sliders can be adjusted and readjusted an unlimited number of times. The task for the subjects is to position as many sliders as possible at 50 during the time allocated to the subject. The number of sliders positioned at 50 constitutes the **points score**. The points score and the time remaining is displayed to the subject. In this experiment, 48 sliders were displayed and the subjects had 120 seconds to position them. Below, the schematic representation illustrates the task at hand.

## Experimental Procedure

Each session consists of 10 *First Movers* and 10 *Second Movers*, who stay in their role for the duration of their session. After two practice rounds, the subjects played 10 paying rounds. The prize for each pair was drawn randomly from {0.10,0.20,...3.90} and then revealed to the pair members. The task was completed sequentially, where the *Second Mover* observes the points score of the First Mover. This information is also displayed next to the alloted time and the own points score during the task. The probability to win the ensuing lottery is determined by

\begin{equation*}
P_i(e_i,e_j) = \frac{e_i - e_j + 50}{100}
\end{equation*}

were $e_i$ in this setting corresponds to the points score of player $i$, and respectively $e_j$ for player $j$. Henceforth, effort is used synonymously to the points score. This use of the term is unlike the traditional literature, where effort is the associated cost of action. Here, it directly corresponds to the behavior of the subjects.

After each round the subjects were paired with another subjects. To ensure that subjects never meet each other, the *'no contagion'* matching algorithm by Cooper et al. (1996) is used. This prevents strategic action by the subjects, where they collude by decreasing their efforts. In fact, zero effort by both subjects yields the social optimum.

---
# Theoretical Predictions
---

The paired subjects compete with each other to win a fixed prize $v$. First, the first movers works at the slider task and subsequently the second mover chooses his effort. Together the above stated probability to winning prize $v$ is determined. The probabilities are linear in the difference of points scores. For their analysis, the authors only focus on the Second Mover. This leaves them with a pure optimization problem.

## Canonical Model

For the canonical model to work, the separability assumption common in tournament literature is used. The assumption states that the utility $U_{2}$ can be separated into the *material utility* $u_{2}(y_{2})$ and the *cost of effort* $C(e_{2})$. This implies cost of effort does not depend on whether the agent wins the prize and the valuation of the prize does not change with increasing effort. This leaves the agent with the expected utility:

\begin{equation*}
EU_2(e_2,e_1) = P_2(e_2,e_1)u_2(v) + \left(1 - P_2(e_1,e_2)\right) u_2(0) - C_2(e_2)
\end{equation*}

Given the linearity of the winning probabilities in the difference of efforts, the effort $e_1$ of the First Mover has no impact on the Second Mover's effort $e_2$. This leads to the proposition:

**PROPOSITION 1:** *In the canonical model without disappointment aversion the Second Mover’s optimal effort $e_2$ (or set of optimal efforts) does not depend on the First Mover’s effort $e_1$.*

The relative lack of further structural assumptions makes this model malleable. For instance, the results still holds when risk aversion, inequity aversion (Fehr and Schmidt 1999) or a fixed reference point are webbed into the utility function.

## Disappointment Aversion

The basis of the model of disappointment aversion is that agents are sensitive to deviations from their expectations.  They suffer a psychological loss when they receive less than what they expect and experience elation when they receive more. For instance, an employee feels disappointed by a raise because she expected the raise to be bigger. These potential psychological losses and gains, in turn, inform the agent in her decision process.

The agent compares the material utility $u_2(y_2)$ to a reference point $R_2$. She is experiencing a loss when the material utility is less than the reference point and joy when the material utility is above this reference level.  Without further assumptions on the form of this reference point $R_2$, this leaves the agent with the following utility

\begin{equation*}
U_2(e_2,R_2,e_1) = u_2(y_2) + I_{u_2(y_2) \geq R_2}G_2(u_2(y_2) - R_2) + I_{u_2(y_2) \leq R_2}L_2(u_2(y_2) - R_2) - C_2(e_2)
\end{equation*}

The loss function $L_2(x)$ is strictly negative for all $x < 0$ and the gain function is $G_2(x) \geq 0$ for $x > 0$. At $x = 0$ both functions equal zero. Loss aversion dictates that $G_2(x) < |L_2(-x)|$ for all $x > 0$. The losses are more painful than equal-sized gains are pleasurable. Traditionally, this reference point is set exogenously (Kahneman and Tversky 1979). Yet, such a fixed reference point does not link the First Mover effort to the Second Mover effort. To model disappointment aversion the reference point must be formed endogenously. Köszegi and Rabin (2007) propose a *choice-acclimating* reference point, where the reference point is equal to the expected utility. In this implementation the reference point is dependent on the effort of both the Second Mover herself and the First Mover's effort. In contrast to the model by Köszegi and Rabin, the Second Mover is aware that her effort choice affects the reference point when optimizing her behavior. In this setting this leads to $R_2 = vP_2(e_2,e_1)$. This step is crucial to allow for a possible discouragement effect.

As is custom in the literature, piece-wise linearity is imposed on the gain-loss utility. $l_2$ is the slope of the loss function and $g_2$ is the slope of the gain function. Loss aversion imposes $l_2 > g_2$ and leads to the (strictly positive) definition of the strength of disappointment aversion

\begin{equation*}
\lambda_2 \equiv l_2 - g_2.
\end{equation*}

Thus, the disappointment averse expected utility can be formulated as

\begin{equation*}
EU_2(e_2,e_1) = P_2 v + g_2(v - vP_2) + (1 - P_2)(0 + l_2(0 + vP_2) - C_2(e_2) \\
= vP_2 - \lambda_2vP_2(1 - P_2) - C_2(e_2)
\end{equation*}

The extra term in the middle of the equation is coined the **disappointment deficit** by the authors. This disappointment deficit is proportional to the variance of the Second Mover's two-point distribution of monetary payoffs. Due to disappointment aversion, the Second Mover dislikes variance in her monetary payoff. This is a key distinction to risk aversion, where agents only care about their probability of winning and not about the variance in their potential payoffs. This variance is strictly concave and maximized at $P_2$. When the efforts yield a zero probability for the Second Mover to win, she has a reference point of zero and combined with the probability she can never be disappointed. Yet at this point, small increases in probability lead to large increases in the variance of monetary payoffs. These increases get smaller but continue until $P_2 = \frac{1}{2}$. At this point the variance reaches its highest point. From this point on increases in $P_2$ reduce the variance of monetary payoffs. This relationship can expressed as:

**PROPOSITION 2:** *When the Second Mover is disappointment averse, higher First Mover effort discourages the Second Mover: the Second Mover’s optimal effort $e_2$ is always (weakly) decreasing in the First Mover’s effort $e_1$.*

In order to derive an analytical expression, the authors assume a quadratic cost of effort of the form

\begin{equation*}
C_2(e_2) = be_2 + \frac{ce_{2}^{2}}{2}.
\end{equation*}

With this term the Second Mover's reaction function can be expressed.

**PROPOSITION 3:** *Suppose a disappointment averse Second Mover has a quadratic cost function and a strictly concave objective function, i.e., $\gamma_2c_2 − \lambda_2v > 0$. When the action space is continuous, the slope of the Second Mover’s reaction function in the interior is given by*

\begin{equation*}
\frac{de_2}{de_1} = \frac{-\lambda_2v}{2\gamma^2c - \lambda_2v} < 0
\end{equation*}

*which becomes strictly more negative in the strength of disappointment aversion $\lambda_2$ and the value of the prize $v$. When the action space is discrete, the discrete analog of the reaction function behaves similarly.*

---
# Identification Strategy
---
In their paper Gill and Prowse aim to evaluate whether subjects exhibit disappointment aversion. In order to do that, they set up the aforementioned laboratory experiment. The causal graph below illustrates their identification strategy. We can assume that the effort of the Second Mover's $e_2$ is affected by the value of the prize $v$ and the effort of the First Mover $e_1$. In addition to that there can be learning throughout the ten played periods. Strictly speaking this term is inaccurate, since it actually captures to very different ideas of learning. First, the learning of the Slider Task, where the agent improves his/her performance by experience. But second, there can be meta-learning, where the agent gets more selective under which conditions she exerts effort.

Figure 2: Causal Graph (This graph is drawn with [draw.io](https://app.diagrams.net/).)

The advantages of an laboratory experiment are evident in the identification strategy by the authors. As the experimenters have total control over the environmental variables, they can randomize all those links, making for a straightforward identification. The prizes are drawn from a uniform distribution between 0.10 and 3.90 Pounds (with 0.10-steps). This variation also has advantages in the construction of structural equations as will be seen later. The ten playing rounds make it possible to control for individual specific effects and the matching algorithm ensures that there is no feedback back from the Second Mover effort to the First Mover, thus eliminating possible strategic interaction. The learning effect can be, albeit imperfectly, controlled for with round dummies. Thus, all channels can effectively be controlled for.

---
# Empirical Results
---
## Data Exploration

Before we are turning to the empirical analysis to estimate the strength of disappointment aversion, we can visually inspect the data to see why the authors pursue their empirical strategy. The data consists of 120 subjects, 60 First and 60 Second Mover that are all observed over 10 rounds. Of the 120 subjects, one subject failed to correctly position any slider during the training or playing rounds. The dataset excluding this subject is called **df_2_pref** and is used mainly for the analysis. The points score is interpreted as the effort choice by the subject. Although still discrete, this gives them a finely gradated measure of effort.

The variable of interest is the Second Mover's effort and, thus, the authors are performing a conditional analysis of the Second Mover's effort choice. Their reasoning is that this analysis is sufficient for the purpose of identifying and estimating the strength of disappointment aversion. Including the First Mover's effort would make further assumptions necessary and increase the computational complexity substantially.

    Replication of Table 1 of the paper.

```python
df_1, df_2, df_2_pref = get_datasets()
rslt = effort_overview(df_2_pref)
print('Table 1: Summary of the First and Second Mover efforts')
rslt
```

    Table 1: Summary of the First and Second Mover efforts

      Mean E1
      SD E1
      Mean E2
      SD E2
      Min E1
      Min E2
      Max E1
      Max E2

      period

      1
      22.034
      5.991
      21.763
      6.101
      1
      0
      33
      34

      2
      22.627
      6.708
      23.458
      4.836
      0
      11
      33
      33

      3
      24.763
      6.075
      24.831
      4.875
      0
      12
      37
      38

      4
      24.627
      5.956
      25.203
      4.502
      0
      16
      35
      36

      5
      24.966
      6.800
      25.119
      5.660
      0
      0
      36
      35

      6
      24.729
      7.508
      24.898
      7.039
      1
      0
      37
      39

      7
      25.881
      5.855
      25.763
      6.109
      9
      0
      37
      37

      8
      26.831
      5.858
      26.169
      5.133
      9
      14
      41
      35

      9
      25.593
      8.550
      26.254
      6.702
      0
      0
      38
      40

      10
      26.322
      6.781
      26.729
      5.988
      1
      0
      40
      39

One important inference that can be made is that the maximum of effort is 41 correctly positioned sliders. This is lower than the highest possible maximum of 48 sliders. If, subjects reached this limit, this would suggest that the task is not well suited to identify exerted effort. Another inference that can be made is that the effort choices increase over the rounds, suggesting that learning indeed takes place.

Note: The following graphs and charts are extensions to the paper.

```python
effort_chart(rslt)
```

This chart visualizes Table 1 of the paper. The black bar is indicating the standard deviation of the respective means. Clearly, there appears to be no clear distinction between $e_2$ and $e_1$, when simply inspecting these descriptives. Effort averages are increasing from about 22 correctly positioned sliders to more than 26 over the playing rounds. A closer look at the effort distribution per round shows (Appendix) that there is some variation and a non-neglible amount of subjects are choosing zero effort. Yet, the distribution do appear to behave approximately normal.

However, we are also interested in how the effort of the Second Movers responds to the different prizes. This is shown below. Canonically, the increase in incentives increases the willingness to exert effort. This would manifest itself in a strictly monotonous relationship for each individuals. Given prizes are randomly distributed, this should also hold globally. However, this cannot be observed here, suggesting that there are other effects than the monetary incentive at play.

```python
pyplt.plot(df_2_pref.groupby('prize')['e2'].mean())
pyplt.xlabel('Prize')
pyplt.ylabel('Average Second Mover Effort')
pyplt.show()
print('Figure 4: Average Second Mover Efforts Per Prize Level \n')
stat = df_2_pref['e2'].corr(df_2_pref['prize'])
print(f'The correlation between Prize and Second Mover effort is {stat:0.3f}')
```

```python
joint_effort(df_2_pref)
print('Figure 5: Correlation between First and Second Mover Effort')
```

As mentioned above, the link the authors want to investigate is whether the effort $e_1$ of the First Mover negatively impacts the choice of effort $e_2$ made by the Second Mover. A naive strategy checks for the correlation between those two effort choices. Where disappointment aversion predicts a negative relationship, the canonical model suggest that there is no link between the effort choices. The correlation indicates that there is little to no correlation, and if at all, the effort choices are positively correlated. This positive relationship is suggested by peer effects (Falk and Ichino 2006), where subjects imitate the behavior of their peers and compete by matching or beating the observed effort levels.

Naturally, this is an insufficient analysis without controlling for any of the other effects on Second Mover effort described in the identification strategy. Next, the authors use a reduced form analysis to examine the Second Mover's behavior.

## Reduced Form Analysis

### Model

Each subject plays ten rounds resulting in data with a panel structure. Here, proposition 1 predicts that when controlling for prize and round effects, the effort of the Second Mover will not depend on the First Mover's effort. In contrast, disappointment aversion predicts a negative relationship. The model to be estimated is:
\begin{equation}
e_{2,n,r} = \beta_1 + \beta_2v_{n,r} + \beta_3e_{1,n,r} + \beta_4e_{1,n,r}  *  v_{n,r} + d_r + \omega_n + \epsilon_{n,r}
\end{equation}

for   n = 1,...,N and r = 1,...10. Where n denotes the Second Mover and r indicates the paying round. The inclusion of the interaction term is informed by Proposition 3, where the negative effect of the First Mover's effort is larger at higher prizes. Round dummies $d_r$ are included with the first round being the omitted dummy. The round-invariant Second Mover effects are denoted by $\omega_n$ and are assumed to be identically and independently distributed over Second Movers with a variance of $\sigma_\omega^2$. $\epsilon_{n,r}$ is an observable that varies over Second Movers, it is also assumed to be identically and independently distributed over rounds and Second Movers with variance $\sigma_\epsilon^2$.

Note: In the following cells the analysis with R is set up. R is used because using RandomEffects of the linearmodels package does not reproduce the results.

```r
%%R

# import data
df <- read_dta("data/paper_data/master_data.dta")

# convert the data frame to a data format recognizable by 'plm'
pdf <- subset(pdata.frame(df, index = c("Subject", "Period")))
pdf_pref <- subset(pdf, !Subject==302)
```

```r
%%R

# Random Effects Regressions
re <- plm(Effort~e1+prize+E1timesPrize+TT2+TT3+TT4+TT5+TT6+TT7+TT8+TT9+TT10, data = pdf, model = "random")
re_pref <- plm(Effort~e1+prize+E1timesPrize+TT2+TT3+TT4+TT5+TT6+TT7+TT8+TT9+TT10, data = pdf_pref, model = "random")
# Fixed Effects Regressions
fe <- plm(Effort~e1+prize+E1timesPrize+TT2+TT3+TT4+TT5+TT6+TT7+TT8+TT9+TT10, data = pdf, model = "within")
fe_pref <- plm(Effort~e1+prize+E1timesPrize+TT2+TT3+TT4+TT5+TT6+TT7+TT8+TT9+TT10, data = pdf_pref, model = "within")

# Standard Errors of Omega and Epsilon
pref_1 <- round(sqrt(re_pref$ercomp$sigma2[2]),digits=3)
pref_2 <- round(sqrt(re_pref$ercomp$sigma2[1]),digits=3)
se_re_1 <- round(sqrt(re$ercomp$sigma2[2]),digits=3)
se_re_2 <- round(sqrt(re$ercomp$sigma2[1]),digits=3)
```

### Results

    Replication of the parameters and standard errors in Table 2 of the paper.

For this model, the theory suggests three hypotheses:

* Second Mover effort does **not** depend on the corresponding First Mover effort, controlling for prize and round effects **(Proposition 1)**.

* Second Mover effort, in fact, depends (negatively) on the respective First Mover effort, with controls for prize and round effects **(Proposition 2)**.

* The negative effect of the First Mover's effort on the Second Mover's effort is larger at higher prices **(Proposition 3)**.

```r
%%R

stargazer(re_pref, re, type="text", title="Table 2: Random Effects Regressions",
          dep.var.labels="Second Mover Effort",
          #omit=c("TT2","TT3","TT4","TT5","TT6","TT7","TT8","TT9","TT10"), # unchecking this gives the coefficients reported in the paper.
          covariate.labels=c("First Mover Effort", "Prize", "Prize x First Mover Effort"),
          column.labels=c("Preferred Sample", "Full Sample"),
          add.lines = list(
            c("Standard Error of Omega", pref_1 , se_re_1),
            c("Standard Error of Epsilon",pref_2,se_re_2)),
          no.space=TRUE)
```

    Table 2: Random Effects Regressions
    =======================================================
                                   Dependent variable:
                               ----------------------------
                                   Second Mover Effort
                               Preferred Sample Full Sample
                                     (1)            (2)
    -------------------------------------------------------
    First Mover Effort              0.044          0.047
                                   (0.049)        (0.049)
    Prize                          1.639***      1.655***
                                   (0.602)        (0.592)
    Prize x First Mover Effort     -0.049**      -0.050**
                                   (0.023)        (0.023)
    TT2                            1.689**        1.655**
                                   (0.709)        (0.699)
    TT3                            3.084***      3.034***
                                   (0.713)        (0.702)
    TT4                            3.448***      3.369***
                                   (0.713)        (0.702)
    TT5                            3.322***      3.279***
                                   (0.714)        (0.703)
    TT6                            3.262***      3.193***
                                   (0.713)        (0.701)
    TT7                            4.123***      4.043***
                                   (0.716)        (0.705)
    TT8                            4.567***      4.487***
                                   (0.720)        (0.709)
    TT9                            4.709***      4.632***
                                   (0.716)        (0.704)
    TT10                           5.180***      5.066***
                                   (0.725)        (0.712)
    Constant                      19.777***      19.392***
                                   (1.400)        (1.447)
    -------------------------------------------------------
    Standard Error of Omega         4.288          5.342
    Standard Error of Epsilon       3.852          3.826
    Observations                     590            600
    R2                              0.137          0.135
    Adjusted R2                     0.119          0.117
    F Statistic                   91.452***      91.268***
    =======================================================
    Note:                       *p<0.1; **p<0.05; ***p<0.01

Proposition 3 can be accepted, the interaction between the First Mover's effort and the prize is significantly negative, suggesting that the effect of the First Mover's effort is larger at higher prices. Furthermore, the interaction term (at the average price) and the First Mover effort together are negative, albeit not significant. This supports Proposition 1 in favor of Proposition 2. Notable but only mentioned in a footnote are the large and highly significant round effects that tend to increase over the rounds. As indicated in Section 4, this can be due to learning.

The following regression shows the fixed effects regression that is mentioned in the text but not explicitly shown.

```r
%%R

stargazer(fe_pref,fe, type="text", title=" Table 3: Fixed Effects Regressions",
          dep.var.labels="Second Mover Effort",
          omit=c("TT2","TT3","TT4","TT5","TT6","TT7","TT8","TT9","TT10"),
          covariate.labels=c("First Mover Effort", "Prize", "Prize x First Mover effort","Intercept"),
          column.labels=c("Preferred Sample", "Full Sample"),
          no.space=TRUE)
```

    Table 3: Fixed Effects Regressions
    ==========================================================================
                                             Dependent variable:
                               -----------------------------------------------
                                             Second Mover Effort
                                  Preferred Sample           Full Sample
                                         (1)                     (2)
    --------------------------------------------------------------------------
    First Mover Effort                  0.047                   0.050
                                       (0.050)                 (0.049)
    Prize                             1.716***                1.701***
                                       (0.605)                 (0.594)
    Prize x First Mover effort        -0.051**                -0.051**
                                       (0.024)                 (0.023)
    --------------------------------------------------------------------------
    Observations                         590                     600
    R2                                  0.151                   0.148
    Adjusted R2                         0.037                   0.034
    F Statistic                7.709*** (df = 12; 519) 7.655*** (df = 12; 528)
    ==========================================================================
    Note:                                          *p<0.1; **p<0.05; ***p<0.01

### Fixed vs. Random Effects

The authors opt to use a random effects linear regression. Random effect models are closely related to the fixed effects models. Here, the different assumptions made by the two approaches are discussed. This is followed by the replication of the Hausman test that can be found in Table 2 of the paper.

Both approaches are workhorses when working with panel/cross sectional time series data. The key distinction between the two models are the different assumptions made about the omitted variables. Implicitly, the random effects model assumes that there are no omitted variables correlated with the explanatory variables. The entities are drawn randomly from a population. If this is accurate, the model yields unbiased results and produces the smallest standard errors. In comparison, the fixed effects model makes no such strong assumptions about the correlation of omitted variables with the explanatory variables. In fact, the approach can control for omitted variables bias. The subjects serve as their own controls. For this to hold true, the fixed effects has to be time-invariant. However, being able to control for omitted variable bias comes at the cost of producing higher standard errors.

The **Hausman test** provides a means for comparing these two models. It tests for the independence of $\omega_n$ and the explanatory variables $x_{it}$. It looks as follows:
\begin{equation}
W = \frac{(\tilde\beta_{RE} - \tilde\beta_{FE})^2}{Var(\tilde\beta_{RE}) - Var(\tilde\beta_{FE})} \sim \chi_1^2
\end{equation}

The null hypothesis $H_0$ is that there is no covariance between the explanatory variables and the specific effects. Making the random effects model a suitable candidate. If this hypothesis is rejected, the $H_1$ leaves us with the fixed effects model coefficients as the only consistent coefficients.

    Replication of the Hausman test in  Table 2 of the paper.

```r
%%R

# Hausman Test testing the Random Effects assumption
hausman <- phtest(fe,re)
hausman_pref <- phtest(fe_pref,re_pref)

hausman_pref
```

    	Hausman Test

    data:  Effort ~ e1 + prize + E1timesPrize + TT2 + TT3 + TT4 + TT5 +  ...
    chisq = 2.6008, df = 12, p-value = 0.9978
    alternative hypothesis: one model is inconsistent

The Hausman Test cannot reject $H_0$ and, thus, the use of random effects is supported. This holds true for the preferred sample as well as the full sample.

### Further Investigation

One advantage of laboratory experiments is that environmental variables can be easily altered in a controlled fashion. However, this often does leave only few covariates to further investigate. Especially with the data provided by the authors, there are only limited options on how to expand their reduced form findings. In an earlier working paper the authors include men and women dummies, unfortunately they were not available in the provided dataset.

Extension: The following regressions toggle around with different interaction terms.

```r
%%R

# Split interaction term on the first and the last rounds
new_split <- pdf_pref
new_split$Period <- as.numeric(new_split$Period)
split <- pdf_pref
split$Period <- as.numeric(split$Period)

# Reported split
split$last <- ifelse(split$Period <= 5, 0, split$E1timesPrize)
split$first <- ifelse(split$Period > 5, 0, split$E1timesPrize)

# New Split
new_split$last <- ifelse(new_split$Period <= 4, 0, new_split$E1timesPrize)
new_split$first <- ifelse(new_split$Period > 4, 0, new_split$E1timesPrize)

# Random Effects regression
split_interaction <- plm(Effort~e1+prize+last+first+TT2+TT3+TT4+TT5+TT6+TT7+TT8+TT9+TT10, data = split, model = "random")
new_interaction_split <- plm(Effort~e1+prize+last+first+TT2+TT3+TT4+TT5+TT6+TT7+TT8+TT9+TT10, data = new_split, model = "random")

stargazer(split_interaction,new_interaction_split, type="text", title="Table 4: Interaction Term Round Splits",
          dep.var.labels="Second Mover Effort",
          omit=c("TT2","TT3","TT4","TT5","TT6","TT7","TT8","TT9","TT10"),
          covariate.labels=c("First Mover Effort", "Prize", "Last","First","Intercept"),
          column.labels=c("Split at round 5", "Split at round 4"),
          no.space=TRUE)
```

    Table 4: Interaction Term Round Splits
    ====================================================
                              Dependent variable:
                       ---------------------------------
                              Second Mover Effort
                       Split at round 5 Split at round 4
                             (1)              (2)
    ----------------------------------------------------
    First Mover Effort      0.044            0.043
                           (0.049)          (0.050)
    Prize                  1.640***         1.619***
                           (0.604)          (0.605)
    Last                   -0.047**         -0.050**
                           (0.024)          (0.024)
    First                  -0.050**         -0.046*
                           (0.024)          (0.025)
    Intercept             19.843***        19.687***
                           (1.415)          (1.416)
    ----------------------------------------------------
    Observations             590              590
    R2                      0.136            0.136
    Adjusted R2             0.117            0.117
    F Statistic           90.911***        90.977***
    ====================================================
    Note:                    *p<0.1; **p<0.05; ***p<0.01

The specification where the interaction term is split at round 5 is mentioned in the paper. Using a different break point, where the interaction term the first four rounds is denoted by first and the last six rounds are denoted by last. This follows from the visual inspection of the effort distribution per round that can be found in the Appendix.

The new split is very similar to the older specification. Nonetheless, the interaction for the first rounds in the new specification is not significant at the 5% level anymore. Yet, further inspecting the coefficients does not lead to any new conclusions. The last rounds have a larger negative effect than the first round but the differences are minor and the test below affirms that the difference is not significant.

```r
%%R

# Test equality of the interaction term for the first and the last five rounds.
linearHypothesis(split_interaction, c("first=last"))

# Test for equality of the split interaction term with a break at round 4
linearHypothesis(new_interaction_split, c("first=last"))
```

    Linear hypothesis test

    Hypothesis:
    - last  + first = 0

    Model 1: restricted model
    Model 2: Effort ~ e1 + prize + last + first + TT2 + TT3 + TT4 + TT5 +
        TT6 + TT7 + TT8 + TT9 + TT10

      Res.Df Df  Chisq Pr(>Chisq)
    1    577
    2    576  1 0.1868     0.6656

```r
%%R

# New dataset.
new_interact <- pdf_pref

# Interaction term partioned for prize level
new_interact$small <- ifelse(new_interact$prize < 2, new_interact$E1timesPrize, 0)
new_interact$medium <- ifelse(new_interact$prize >= 2 & new_interact$prize <= 2.60, new_interact$E1timesPrize, 0)
new_interact$high <- ifelse(new_interact$prize >= 2.70, new_interact$E1timesPrize, 0)

# interaction term for different prize level
new_spec <- plm(Effort~e1+prize+small+medium+high+TT2+TT3+TT4+TT5+TT6+TT7+TT8+TT9+TT10, data = new_interact, model = "random")

# No prize controls
no_prizes <- plm(Effort~e1+TT2+TT3+TT4+TT5+TT6+TT7+TT8+TT9+TT10, data = pdf_pref, model = "random")

# Render the table
stargazer(no_prizes,new_spec, type="text", title="Table 5: New Interaction Term Specifications",
          dep.var.labels="Second Mover Effort",
          omit=c("TT2","TT3","TT4","TT5","TT6","TT7","TT8","TT9","TT10"), # unchecking this gives the coefficients reported in the paper.
          covariate.labels=c("First Mover Effort", "Prize", "Small","Medium","High"),
          column.labels=c("No Prize Controls", "Interaction per Prize Level"),
          no.space=TRUE)
```

    Table 5: New Interaction Term Specifications
    ================================================================
                                    Dependent variable:
                       ---------------------------------------------
                                    Second Mover Effort
                       No Prize Controls Interaction per Prize Level
                              (1)                    (2)
    ----------------------------------------------------------------
    First Mover Effort      -0.036                  0.024
                            (0.026)                (0.052)
    Prize                                         1.608***
                                                   (0.601)
    Small                                          -0.032
                                                   (0.029)
    Medium                                         -0.031
                                                   (0.025)
    High                                           -0.045*
                                                   (0.024)
    Constant               22.556***              19.801***
                            (0.946)                (1.399)
    ----------------------------------------------------------------
    Observations              590                    590
    R2                       0.118                  0.142
    Adjusted R2              0.103                  0.122
    F Statistic            77.783***              95.534***
    ================================================================
    Note:                                *p<0.1; **p<0.05; ***p<0.01

In the regression table above, two specifications can be seen. The first specification, also reported in the paper, eliminates all prize control and can report a negative but insignificant effect of $e_1$ on $e_2$. The other specification looks as follows:

\begin{equation}
e_{2,n,r} = \beta_1 + \beta_2v_{n,r} + \beta_3e_{1,n,r} + \beta_4Small_{n,r} +\beta_5Medium_{n,r} + \beta_6High_{n,r} + d_r + \omega_n + \epsilon_{n,r}
\end{equation}
where
* $Small_{n,r} : e_{1,n,r}*v_{n,r}$ for $v_{n,r} < 2$
* $Medium_{n,r} : e_{1,n,r}*v_{n,r}$ for $2 \leq v_{n,r} \leq 2.60$
* $Large_{n,r} : e_{1,n,r}*v_{n,r}$ for $v_{n,r} > 2.60$

denote the interaction term for different prize ranges. This can inform whether this relationship is stable throughout the whole prize range.

As can be seen, the effect decreases with the prize value. Whereas the interaction on Small and Medium prize levels is not significant at any level, the interaction with the high prizes is borderline significant (10%).

## Structural Model

### Empirical Specification
After not accumulating convincing evidence of disappointment aversion in the reduced form analysis the authors turn to structural estimation strategies. Thanks to the variations induced by the experimental design, the data is well-suited for such an analysis. Beyond, the estimation of disappointment aversion, this approach also allows for the estimation of population-level heterogeneity.

In order to estimate disappointment aversion the authors use the following specifications:

\begin{equation}
\lambda_{2,n} \sim N(\tilde\lambda_2,\sigma_\lambda^2)
\end{equation}
for n = 1,...,N.

Here, $\lambda$ is held fixed on the subject-level. It can vary throughout Second Movers but does not vary over rounds. In addition to $\lambda$ the convexity parameter $c_{n,r}$ is estimated at round and subject-level:

\begin{equation}
c_{n,r} = \kappa + \delta_r + \mu_n + \pi_{n,r}
\end{equation}
for n = 1,...,N; r = 1,...10.

$\kappa$ represents a component common across all Second Movers. $\delta_r$ denotes the round effects that allow the marginal costs of effort to vary over rounds (where $\delta_1$ is omitted). For instance, if due to learning the tasks gets easier in the later periods $\delta_r$ is negative and decreasing over rounds. $\mu_n$ indicates the unobserved differences in the cost of effort on the subject-level that are constant over rounds. $\pi_{n,r}$ denotes the unobserved differences that vary over rounds and Second Movers. For $\pi$ and $\mu$ both scale and shape parameters of a Weibull distribution are estimated. The reasoning for opting for a Weibull distribution is that it has positive support allowing to impose convex cost of effort function on all subjects. In total, this leaves them with the following 17 unknown parameter:

    Extension: Description and trial values for the unknown parameters.

```python
print('Table 6: Parameter description')
params_description(return_descriptives=True)
```

    Table 6: Parameter description

      value
      comment
      lower
      upper

      category
      name

      lambda
      lambda
      2.00
      strength of disappointment aversion on average
      1.0
      3.0

      std_lambda
      1.50
      standard deviation of strength of disappointment aversion
      0.5
      2.5

      cost_of_effort
      phi_pi
      0.35
      unobserved differences in cost of effort functions that vary over rounds and individuals
      0.0
      0.7

      varphi_pi
      0.85
      unobserved differences in cost of effort functions that vary over rounds and individuals
      0.2
      1.5

      phi_mu
      0.35
      unobserved differences in cost of effort functions between individuals, constant over rounds
      0.0
      0.7

      varphi_mu
      0.85
      unobserved differences in cost of effort functions between individuals, constant over rounds
      0.2
      1.5

      kappa
      1.75
      common cost parameter
      1.0
      2.5

      b
      -27.50
      common cost parameter
      -35.0
      -20.0

      delta_2
      0.00
      round effects for round 2
      -1.0
      0.0

      delta_3
      0.00
      round effects for round 3
      -1.0
      0.0

      delta_4
      0.00
      round effects for round 4
      -1.0
      0.0

      delta_5
      0.00
      round effects for round 5
      -1.0
      0.0

      delta_6
      0.00
      round effects for round 6
      -1.0
      0.0

      delta_7
      0.00
      round effects for round 7
      -1.0
      0.0

      delta_8
      0.00
      round effects for round 8
      -1.0
      0.0

      delta_9
      0.00
      round effects for round 9
      -1.0
      0.0

      delta_10
      0.00
      round effects for round 10
      -1.0
      0.0

Regarding the selection of the bounds, the authors do not provide any decision rule, however they do run the estimation with different specifications. From their Matlab codes the upper and lower bounds of the values of their preffered specification can be extracted. The bounds are configured for estimation with *estimagic*. Setting bounds is a decisive factor in the success of optimization. Structural models usually provide sufficient information in order to select sensible bounds. The starting trial values are the mean between the bounds with the round effects, set at zero, being the exception. The cost parameter $b$ reported in the table below sticks out but since it is part of the cost of effort function:

\begin{equation}
C_2(e_{2,n,r}) = be_{2,n,r} + \frac{c_{n,r}e_{2,n,r}^{2}}{2}
\end{equation}

where the mean effort choices are between 20 and 30 correctly positioned sliders, this seems reasonable.

### Method of Simulated Moments

The parameter of interest are estimated by the **Method of Simulated Moments (MSM)** that was pioneered by McFadden (1989) and by Pakes and Pollard (1989). The idea is, similar to the Generalized Method of Moments (GMM), to use a vector of moments M with $k \geq 17$, where every included moment is dependent on the endogenous variables. The step that differentiates MSM from GMM is the use of simulated samples. In each of the S simulated sample the Second Mover face the same prizes and First Mover effort as observed in the actual sample. The behavior of the Second Movers in the simulated sample is guided by the trial  $\theta_t$ values of the unknown parameters $\theta$. The unobservables $\mu$ and $\pi$ are assigned to the Second Movers with the specified distributions.

For all Second Movers and each round the utility for all 49 possible effort choices is computed and the simulated action corresponds to the effort choice with the highest achieved utility. In order to compare the simulated samples to the experimental sample the vector of moments $M_s(\theta_t)$ are computed. These moments are used in the following metric:

\begin{equation*}
J(\theta_t) =  \left(M - \frac{1}{S} \sum\limits_{S=1}^S M_S(\theta_t)\right)'W_N\left(M - \frac{1}{S} \sum\limits_{S=1}^S M_S(\theta_t)\right)
\end{equation*}

This is the core function of the MSM approach. The objective of this metric is $J(\theta_t): \hat\theta = arg min_{\theta_t} J(\theta_t)$. It minimizes the distance between the average of the simulated moments and the empirical moments **M**. Thus, the moments induced by the structural parameters have to be as close to the actual moments as possible. $W_N$ is the weighting matrix of $k \times k$ dimension. For this simulation, the authors specify the diagonal elements of the weigthing matrix as the inverse of N times the bootstrapped variance of the moments and zeroes on the non-diagonal elements. In total, 38 moments are used to estimate the 17 unknown parameters.

    Note: The following attempt of implementation follows the steps outlined by the respy documentation closely.

### Empirical Moments

In order to estimate the parameters that are of interest, moments need to be simulated. A dataframe fashioned after Table 4 is provided below. It gives an overview over the moments the authors choose to be estimated.

    Replication of the descriptions in Table 4.

```python
print('Table 7: Description of the moments')
moments_description()
```

    Table 7: Description of the moments

      comment

      name

      effort_std
      standard deviation of effort

      autocorrelation_l1
      autocorrelation with lag 1

      autocorrelation_l2
      autocorrelation with lag 2

      round_change_std
      standard deviation of round-round change of effort

      period_average
      average effort in period i

      cond_corr_e2_prize
      correlation of e2 and prize, conditional on control effects

      cond_corr_e2_e1
      correlation of e2 and e1, conditional on control effects

      cond_corr_e2_e1timesprize
      correlation of e2 and e1 * prize, conditional on control effects

      j_perc_cond_corr_e2_prize
      jth percentile of cond. correlation e1 and prize of specific effects

      j_perc_cond_corr_e2_e1
      jth percentile of cond. correlation e1 and e2 of specific effects

      j_perc_cond_corr_e2_e1timesprize
      jth percentile of cond. correlation e2 and e1 * prize of specific effects

      low_effort_low_prize
      effort conditional on low e1 and low prizes

      low_effort_high_prize
      effort conditional on low e1 and high prizes

      high_effort_low_prize
      effort conditional on high e1 and low prizes

      high_effort_high_prize
      effort conditional on high e1 and high prizes

      low_effort_prop
      probability of low effort

      high_effort_prop
      probability of high effort

The functions needed for the estimation of those moments are found in the *auxiliary/msm.py*-file. They are stored in the dictionary to access them later. For all those moments separate functions are used, eventhough some functions have similarities with each other. This was done to follow the guides outlined on the *respy* website as closely as possible. Yet, one difference is that in this situation the moments are computed for the whole sample, whereas the *respy* outline computes them at a period level.

```python
calc_moments = {
    'effort_std': effort_std,
    'corr_round_lag1': pooled_autocorr_lag1,
    'corr_round_lag2': pooled_autocorr_lag2,
    'round_change_std': round_change_std,
    'mean_period_1': period1_average,
    'mean_period_2': period2_average,
    'mean_period_3': period3_average,
    'mean_period_4': period4_average,
    'mean_period_5': period5_average,
    'mean_period_6': period6_average,
    'mean_period_7': period7_average,
    'mean_period_8': period8_average,
    'mean_period_9': period9_average,
    'mean_period_10': period10_average,
    'cond_corr_e2_prize': cond_corr_e2_prize,
    'cond_corr_e2_e1': cond_corr_e2_e1,
    'cond_corr_e2_e1timesprize': cond_corr_e2_e1timesprize,
    'perc17_cond_corr_e2_prize': perc17_cond_corr_e2_prize,
    'perc33_cond_corr_e2_prize': perc33_cond_corr_e2_prize,
    'perc50_cond_corr_e2_prize': perc50_cond_corr_e2_prize,
    'perc66_cond_corr_e2_prize': perc66_cond_corr_e2_prize,
    'perc83_cond_corr_e2_prize': perc83_cond_corr_e2_prize,
    'perc17_cond_corr_e2_e1': perc17_cond_corr_e2_e1,
    'perc33_cond_corr_e2_e1': perc33_cond_corr_e2_e1,
    'perc50_cond_corr_e2_e1': perc50_cond_corr_e2_e1,
    'perc66_cond_corr_e2_e1': perc66_cond_corr_e2_e1,
    'perc83_cond_corr_e2_e1': perc83_cond_corr_e2_e1,
    'perc17_cond_corr_e2_e1timesprize': perc17_cond_corr_e2_e1timesprize,
    'perc33_cond_corr_e2_e1timesprize': perc33_cond_corr_e2_e1timesprize,
    'perc50_cond_corr_e2_e1timesprize': perc50_cond_corr_e2_e1timesprize,
    'perc66_cond_corr_e2_e1timesprize': perc66_cond_corr_e2_e1timesprize,
    'perc83_cond_corr_e2_e1timesprize': perc83_cond_corr_e2_e1timesprize,
    'low_effort_low_prize': low_effort_low_prize,
    'low_effort_high_prize': low_effort_high_prize,
    'high_effort_low_prize': high_effort_low_prize,
    'high_effort_high_prize': high_effort_high_prize,
    'low_effort_prop': low_effort_prop,
    'high_effort_prop': high_effort_prop
}
```

These function, in turn, are used to calculate the empirical moments. These are the moments that are computed with the experimental sample without any simulation. They are found below.

    Replication of the observed moments in Table 5.

```python
empirical_moments = observed_moments(df_2_pref)
empirical_moments
```

    {'effort_std': 5.8745832443237305,
     'corr_round_lag1': 0.6523300435833547,
     'corr_round_lag2': 0.5955089258400272,
     'round_change_std': 4.82824351834171,
     'mean_period_1': 21.762712478637695,
     'mean_period_2': 23.457626342773438,
     'mean_period_3': 24.830509185791016,
     'mean_period_4': 25.20339012145996,
     'mean_period_5': 25.11864471435547,
     'mean_period_6': 24.898305892944336,
     'mean_period_7': 25.762712478637695,
     'mean_period_8': 26.169490814208984,
     'mean_period_9': 26.25423812866211,
     'mean_period_10': 26.72881317138672,
     'cond_corr_e2_prize': 0.12361415759953642,
     'cond_corr_e2_e1': 0.04149206717166187,
     'cond_corr_e2_e1timesprize': -0.09501348232241316,
     'perc17_cond_corr_e2_prize': -0.2749740360569023,
     'perc33_cond_corr_e2_prize': 0.03305363732319229,
     'perc50_cond_corr_e2_prize': 0.22225342393899755,
     'perc66_cond_corr_e2_prize': 0.3876273607645051,
     'perc83_cond_corr_e2_prize': 0.46911122033916214,
     'perc17_cond_corr_e2_e1': -0.32799713935543484,
     'perc33_cond_corr_e2_e1': -0.2179878357116517,
     'perc50_cond_corr_e2_e1': 0.019100550720606655,
     'perc66_cond_corr_e2_e1': 0.17869322920672392,
     'perc83_cond_corr_e2_e1': 0.3609552623371953,
     'perc17_cond_corr_e2_e1timesprize': -0.1943010508973714,
     'perc33_cond_corr_e2_e1timesprize': 0.01887267598522453,
     'perc50_cond_corr_e2_e1timesprize': 0.14626187907883428,
     'perc66_cond_corr_e2_e1timesprize': 0.2982281135137103,
     'perc83_cond_corr_e2_e1timesprize': 0.47429080067835255,
     'low_effort_low_prize': 23.821428298950195,
     'low_effort_high_prize': 25.485294342041016,
     'high_effort_low_prize': 25.8360652923584,
     'high_effort_high_prize': 25.049999237060547,
     'low_effort_prop': 0.0288135593220339,
     'high_effort_prop': 0.015254237288135594}

    Note: Some moments were not precisely specified in Table 4. The different computation specifications for these moments can be found in the Appendix.

### Weighting Matrix

The weighting matrix is important to account for differences in magnitude between the moments. It assigns each moment a different weight and hence controls the importance the optimizing function gives to each moment. In the paper it is specified that the diagonal elements of the weighting matrix are the inverse of N times the variances of the sample moments and zeros elsewhere. 2000 Bootstrap samples with replacement are used to compute $W_n$. For my weighting matrix, I am orienting myself at the example [here](https://respy.readthedocs.io/en/latest/how_to_guides/msm_estimation_exercise.html), where the diagonal elements are the inverse variance of the bootstrapped moments. The function needed to be adapted to suit the objects in this notebook. For example, bootstrap sampling is used with replacement because the observed sample is small. Given cell timeout constraints with Travis CI, only 20 bootstrap samples are used to compute the weighting matrix. I'd suggest running the function with atleast 100 bootstraped samples, if possible.

    Note: The following functions are still at a premature stage.

```python
start = datetime.now()
weighting_matrix = get_weighting_matrix(
   data=df_2_pref,
   empirical_moments=empirical_moments,
   calc_moments=calc_moments,
   n_bootstrap_samples=20,
   n_observations_per_sample=59,
   replace_missing_variances=None)
end = datetime.now()
time_taken = end - start
print(time_taken)
```

    0:00:32.065119

```python
weighting_matrix
```

    array([[8.04287763e+00, 0.00000000e+00, 0.00000000e+00, ...,
            0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
           [0.00000000e+00, 3.60573471e+02, 0.00000000e+00, ...,
            0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
           [0.00000000e+00, 0.00000000e+00, 1.60206819e+02, ...,
            0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
           ...,
           [0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ...,
            7.21242976e-01, 0.00000000e+00, 0.00000000e+00],
           [0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ...,
            0.00000000e+00, 1.75150514e+04, 0.00000000e+00],
           [0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ...,
            0.00000000e+00, 0.00000000e+00, 2.40707560e+04]])

### Simulation

As I mentioned above, I was not able to replicate the Method of Simulated Moments. Yet, I was able to get the simulation running. In the simulation below, first the effort choices are simulated induced by the prespecified trial values. For each subjects and round every possible effort choices is simulated and the utility maximizing choice is drawn. Then, using these choices the moments are computed. Finally, they are added together and divided by the number of simulations.

```python
params = params_description()
simulated_moments = get_simulated_moments(df=df_2_pref, params=params, calc_moments=calc_moments, empirical_moments=empirical_moments, num_simulation=2, seed=123)
simulated_moments.round(3)
```

    /Users/vincentselz/opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py:205: SettingWithCopyWarning:
    A value is trying to be set on a copy of a slice from a DataFrame

    See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
      self._setitem_with_indexer(indexer, value)

    effort_std                          2.217
    corr_round_lag1                     0.457
    corr_round_lag2                     0.437
    round_change_std                    2.318
    mean_period_1                       11.364
    mean_period_2                       11.203
    mean_period_3                       11.407
    mean_period_4                       11.068
    mean_period_5                       11.212
    mean_period_6                       11.178
    mean_period_7                       11.263
    mean_period_8                       11.025
    mean_period_9                       11.297
    mean_period_10                      11.322
    cond_corr_e2_prize                  0.056
    cond_corr_e2_e1                     0.057
    cond_corr_e2_e1timesprize          -0.057
    perc17_cond_corr_e2_prize          -0.352
    perc33_cond_corr_e2_prize          -0.199
    perc50_cond_corr_e2_prize          -0.012
    perc66_cond_corr_e2_prize           0.173
    perc83_cond_corr_e2_prize           0.394
    perc17_cond_corr_e2_e1             -0.403
    perc33_cond_corr_e2_e1             -0.148
    perc50_cond_corr_e2_e1              0.039
    perc66_cond_corr_e2_e1              0.196
    perc83_cond_corr_e2_e1              0.384
    perc17_cond_corr_e2_e1timesprize   -0.377
    perc33_cond_corr_e2_e1timesprize   -0.158
    perc50_cond_corr_e2_e1timesprize    0.026
    perc66_cond_corr_e2_e1timesprize    0.134
    perc83_cond_corr_e2_e1timesprize    0.379
    low_effort_low_prize                11.167
    low_effort_high_prize               11.478
    high_effort_low_prize               11.541
    high_effort_high_prize              11.281
    low_effort_prop                     0.931
    high_effort_prop                    0.000
    dtype: float64

Thankfully, the moments provide a good overview of what went wrong in the simulation. It appears in general the level of efforts are too low in the simulated samples. As can be seen in the last row not even one simulated effort was above 35 correctly placed sliders. In addition to that the variance is lower than in the original sample. To optimize these values is precisely the task of the MSM. It chooses such parameter values that the simulated moments fit the empirical moments as closely as possible. The actual simulation runs 30 times, thus simulating 17,700 pairings. Here, the simulation is run only 2 times because of the cell timeout. I'd suggest using atleast 10 simulations.

### Further Steps

The framework from above now can be used to construct the criterion function. Here, my contribution ends. In order to elicit the optimal parameter values the above mentioned criterion function $J(\theta_t)$ is used. The simulation depends on three different random draws, which are held constant throughout the estimation. This ensures that as the parameter values $\theta_t$ are adjusted, the simulated samples only vary due to changes in $\theta_t$ and not due to the exogenously induced random draws. Due to the discrete nature of the optimization, the authors opt to use Simulated Annealing (1994) instead of gradient or Hessian-based optimization methods to solve for the MSM estimates.

---
# Critical Assessment
---
The saying is that when having a well designed experiment, the following empirical analysis is straight forward. This study turns this saying around and shows that structural models can help overcome difficulties in identifying causal effects. In this experiment, results of the reduced form evidence provided little to no evidence for disappointment aversion. The interaction term between First Mover effort and prize was significant but the main variable of interest, the sole First Mover effort, was not. Here, the use of structural estimation salvaged the situation.

In general, I argue that the experiment was not well suited for the identification. The highly significant dummy variables for round effects in the reduced form analysis, suggest that the design did pick up various confounds that were not intended. The significant negative $\delta_r$ in the structural estimation corroborates that learning, in fact, did take place through the paying rounds. The experimenters set up two training rounds, yet it appears this was not enough. Expanding the training rounds might help filter these confounds out of the experimental sample.

The empirical analysis by the authors is sound and well justified. Yet, I do not agree with their assessment that the reduced form analysis offers evidence consistent with disappointment aversion. For this to be the case the impact of $e_1$ on $e_2$ has to be significantly lower than zero which is not true. In their structural model they test various specifications that would favor explanations other than disappointment aversion for the observed behavior. Unfortunately, I was not able to reproduce the MSM, else I could have commented more extensively on the intrinsics of those specifications.

From a experimenter's perspective the study supplies a novel approach to real effort tasks. The slider task provides a convincing method to elicit finely grained discrete effort choices. Yet, for a sample of N subjects 2N need to be paid, since the First Movers also need to be compensated - this appears to be cost-inefficient. Potentially, similar to the training round, the First Mover effort can be simulated making the double payments redundant. Of course, it remains to be seen whether the knowledge of having a tournament with a real person has an effect on the Second Mover.

The primary contribution by this paper is twofold. First, it anwers the question what an agent's reference point constitutes. In line with Abeler (2011), their evidence suggests that the reference points is given by the expected reference point as the model of reference-dependent preferences predicts. Furthermore, the structural analysis allows them to estimate the strength of loss-aversion around the reference point and provides estimates about the heterogeneity of disappointment aversion in the underlying population. Since their model does not fix the reference point at the point of optimization, as the parsimonious model of reference-dependent preferences does, this makes the observed behavior applicable to the situation where the agents can affect their probability of success e.g. competing about promotions. Second, the paper contributes to the discussion about how quickly reference points form. Given that the Second Mover almost immediately observes the First Mover's effort choice and optimizes her behavior, it indicates that reference points form instantly.

---
# Appendix
---

## Effort Distribution Per Round

```python
effort_distr_per_round(df_2_pref)
print('Figure 6: Effort Distribution Per Round')
```

## Prize Distribution

The authors state that the prizes for the tournament are drawn from a uniform distribution. An inspection shows the randomization is successful. The visualization but more importantly the $\chi^2$-Test confirms that it is not significantly different from a uniform distribution.

```python
prize_distribution(df_2_pref)
print('Figure 7: Prize Distribution')
```

```python
chisquare(df_2_pref['prize'])
```

    Power_divergenceResult(statistic=361.38135, pvalue=0.9999999999999948)

## Moment Computation Specifications

As mentioned above, the description in Table 4 sometimes do not match the used computation methods or the description is not specific enough to replicate the solution. Here, I set out how the original results can still be obtained.

First, the conditional means in the table are misspecified. Whereas Table 4 states that the specified effort and prizes need to be strictly higher or lower, their Matlab function uses non-strict inequality. The respective functions can be found in the subdirectory MatLabCode under moments.m line 168 and following. They use the *sign* function to indicate when prices are higher or efforts are higher thant the respective threshold, then subsequently delete them. Yet, this still leaves the Second Mover efforts that are equal to the threshold in the sample.

Second, for the autocorrelation the authors use the pooled autocorrelation. First, all differences from round r-1 to round r are computed and then the correlation is calculated. The implicit assumption here is that that the variances on the subject-level are equal. In turn, the pooled sample variance decreases the denominator, leading to higher autocorrelation estimates. The alternative is to compute the autocorrelations separately for each subject and to use the mean of these correlations:

```python
stat1 = pooled_autocorr_lag1(df_2_pref)
stat2 = calc_autocorrelation_lag1(df_2_pref)

print('The different autocorrelation specifications: \n')
print(f'Reported Autocorrelation: {stat1:0.3f} Mean Autocorrelation: {stat2:0.3f}')
```

    The different autocorrelation specifications:

    Reported Autocorrelation: 0.652 Mean Autocorrelation: 0.123

Third, the reported percentile results are not compatible with the standard behavior by *np.percentile* or *pandas.quantile*. Instead, it needs to be specified that the interpolation method selects the lower of the two value, when the true percentile lies between two values.

# References

* **Abeler, Johannes, Armin Falk, Lorenz Goette, and David Huffman. 2011.** Reference Points and Effort Provision. American Economic Review, 101(2): 470–92.
* **Cooper, Russell, Douglas V. DeJong, Robert Forsythe, and Thomas W. Ross. 1996.** Cooperation without Reputation: Experimental Evidence from Prisoner’s Dilemma Games.
Games and Economic Behavior, 12(2): 187–218.
* **Falk, Armin, and Andrea Ichino. 2006.** Clean Evidence on Peer Effects.” Journal of Labor Economics, 24(1): 39–57.
* **Fehr, Ernst and Klaus M. Schmidt. 1999.** A Theory of Fairness, Competition, and Cooperation. The Quarterly Journal of Economics. Volume 114, Issue 3. Pages 817–868
* **Gabler, Janos and Tobias Raabe. 2020.** respy - A Framework for the Simulation and Estimation of Eckstein-Keane-Wolpin Models.
[https://github.com/OpenSourceEconomics/respy](https://github.com/OpenSourceEconomics/respy)
* **Gill, David, and Victoria Prowse. 2012.** A Structural Analysis of Disappointment Aversion in a Real Effort Competition. American Economic Review, 102 (1): 469-503.
* **Goffe, William L., Gary D. Ferrier, and John Rogers. 1994.** Global Optimization of Statistical Functions with Simulated Annealing. Journal of Econometrics, 60(1–2): 65–99.
* **Kahneman, Daniel, and Amos Tversky. 1979.** Prospect Theory: An Analysis of Decision under Risk. Econometrica, 47(2): 263–91.
* **Koszegi, Botond and Matthew Rabin. 2006.** A Model of Reference-Dependent Preferences,
The Quarterly Journal of Economics, 121, issue 4, p. 1133-1165.
* **McFadden, Daniel. 1989.** A Method of Simulated Moments for Estimation of Discrete Response Models Without Numerical Integration.
Econometrica, 57(5), 995-1026.
* **Pakes, Ariel and David Pollard. 1989.** Simulation and the Asymptotics of Optimization Estimators.
Econometrica, 57(5), 1027-1057.


# Mammal sleep
# ศึกษาการนอนของสัตว์เลี้ยงลูกด้วยนม
https://en.wikipedia.org/wiki/Mammal

```python
from IPython.display import HTML, YouTubeVideo, IFrame
```

```python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
```

```python
df=pd.read_csv('https://github.com/prasertcbs/tutorial/raw/master/msleep.csv', nrows=10)
df[:10]
```

      name
      genus
      vore
      order
      conservation
      sleep_total
      sleep_rem
      sleep_cycle
      awake
      brainwt
      bodywt

      0
      Cheetah
      Acinonyx
      carni
      Carnivora
      lc
      12.1
      NaN
      NaN
      11.9
      NaN
      50.000

      1
      Owl monkey
      Aotus
      omni
      Primates
      NaN
      17.0
      1.8
      NaN
      7.0
      0.01550
      0.480

      2
      Mountain beaver
      Aplodontia
      herbi
      Rodentia
      nt
      14.4
      2.4
      NaN
      9.6
      NaN
      1.350

      3
      Greater short-tailed shrew
      Blarina
      omni
      Soricomorpha
      lc
      14.9
      2.3
      0.133333
      9.1
      0.00029
      0.019

      4
      Cow
      Bos
      herbi
      Artiodactyla
      domesticated
      4.0
      0.7
      0.666667
      20.0
      0.42300
      600.000

      5
      Three-toed sloth
      Bradypus
      herbi
      Pilosa
      NaN
      14.4
      2.2
      0.766667
      9.6
      NaN
      3.850

      6
      Northern fur seal
      Callorhinus
      carni
      Carnivora
      vu
      8.7
      1.4
      0.383333
      15.3
      NaN
      20.490

      7
      Vesper mouse
      Calomys
      NaN
      Rodentia
      NaN
      7.0
      NaN
      NaN
      17.0
      NaN
      0.045

      8
      Dog
      Canis
      carni
      Carnivora
      domesticated
      10.1
      2.9
      0.333333
      13.9
      0.07000
      14.000

      9
      Roe deer
      Capreolus
      herbi
      Artiodactyla
      lc
      3.0
      NaN
      NaN
      21.0
      0.09820
      14.800

## Display Web page

```python
IFrame('https://www.yru.ac.th/th', width=800, height=450)
```

```python
IFrame('https://th.wikipedia.org/wiki/สัตว์เลี้ยงลูกด้วยน้ำนม', width=800, height=450)
```

```python
IFrame('https://en.wikipedia.org/wiki/Mammal', width=800, height=450)
```

## Display PDF
https://www.datacamp.com/community/data-science-cheatsheets

```python
IFrame('http://www.africau.edu/images/default/sample.pdf', width=800, height=900)
```

## เรือพระที่นั่งสุพรรณหงส์

```python
df.style.highlight_max(subset=['sleep_total'], color='deepskyblue').highlight_min(subset=['sleep_total'], color='tan')
```

        	        name	        genus	        vore	        order	        conservation	        sleep_total	        sleep_rem	        sleep_cycle	        awake	        brainwt	        bodywt

                        0
                        Cheetah
                        Acinonyx
                        carni
                        Carnivora
                        lc
                        12.1
                        nan
                        nan
                        11.9
                        nan
                        50

                        1
                        Owl monkey
                        Aotus
                        omni
                        Primates
                        nan
                        17
                        1.8
                        nan
                        7
                        0.0155
                        0.48

                        2
                        Mountain beaver
                        Aplodontia
                        herbi
                        Rodentia
                        nt
                        14.4
                        2.4
                        nan
                        9.6
                        nan
                        1.35

                        3
                        Greater short-tailed shrew
                        Blarina
                        omni
                        Soricomorpha
                        lc
                        14.9
                        2.3
                        0.133333
                        9.1
                        0.00029
                        0.019

                        4
                        Cow
                        Bos
                        herbi
                        Artiodactyla
                        domesticated
                        4
                        0.7
                        0.666667
                        20
                        0.423
                        600

                        5
                        Three-toed sloth
                        Bradypus
                        herbi
                        Pilosa
                        nan
                        14.4
                        2.2
                        0.766667
                        9.6
                        nan
                        3.85

                        6
                        Northern fur seal
                        Callorhinus
                        carni
                        Carnivora
                        vu
                        8.7
                        1.4
                        0.383333
                        15.3
                        nan
                        20.49

                        7
                        Vesper mouse
                        Calomys
                        nan
                        Rodentia
                        nan
                        7
                        nan
                        nan
                        17
                        nan
                        0.045

                        8
                        Dog
                        Canis
                        carni
                        Carnivora
                        domesticated
                        10.1
                        2.9
                        0.333333
                        13.9
                        0.07
                        14

                        9
                        Roe deer
                        Capreolus
                        herbi
                        Artiodactyla
                        lc
                        3
                        nan
                        nan
                        21
                        0.0982
                        14.8

```python
df['brain_body_ratio']=df.brainwt / df.bodywt
df
```

      name
      genus
      vore
      order
      conservation
      sleep_total
      sleep_rem
      sleep_cycle
      awake
      brainwt
      bodywt
      brain_body_ratio

      0
      Cheetah
      Acinonyx
      carni
      Carnivora
      lc
      12.1
      NaN
      NaN
      11.9
      NaN
      50.000
      NaN

      1
      Owl monkey
      Aotus
      omni
      Primates
      NaN
      17.0
      1.8
      NaN
      7.0
      0.01550
      0.480
      0.032292

      2
      Mountain beaver
      Aplodontia
      herbi
      Rodentia
      nt
      14.4
      2.4
      NaN
      9.6
      NaN
      1.350
      NaN

      3
      Greater short-tailed shrew
      Blarina
      omni
      Soricomorpha
      lc
      14.9
      2.3
      0.133333
      9.1
      0.00029
      0.019
      0.015263

      4
      Cow
      Bos
      herbi
      Artiodactyla
      domesticated
      4.0
      0.7
      0.666667
      20.0
      0.42300
      600.000
      0.000705

      5
      Three-toed sloth
      Bradypus
      herbi
      Pilosa
      NaN
      14.4
      2.2
      0.766667
      9.6
      NaN
      3.850
      NaN

      6
      Northern fur seal
      Callorhinus
      carni
      Carnivora
      vu
      8.7
      1.4
      0.383333
      15.3
      NaN
      20.490
      NaN

      7
      Vesper mouse
      Calomys
      NaN
      Rodentia
      NaN
      7.0
      NaN
      NaN
      17.0
      NaN
      0.045
      NaN

      8
      Dog
      Canis
      carni
      Carnivora
      domesticated
      10.1
      2.9
      0.333333
      13.9
      0.07000
      14.000
      0.005000

      9
      Roe deer
      Capreolus
      herbi
      Artiodactyla
      lc
      3.0
      NaN
      NaN
      21.0
      0.09820
      14.800
      0.006635

```python
df.query('vore=="herbi"')
```

      name
      genus
      vore
      order
      conservation
      sleep_total
      sleep_rem
      sleep_cycle
      awake
      brainwt
      bodywt
      brain_body_ratio

      2
      Mountain beaver
      Aplodontia
      herbi
      Rodentia
      nt
      14.4
      2.4
      NaN
      9.6
      NaN
      1.35
      NaN

      4
      Cow
      Bos
      herbi
      Artiodactyla
      domesticated
      4.0
      0.7
      0.666667
      20.0
      0.4230
      600.00
      0.000705

      5
      Three-toed sloth
      Bradypus
      herbi
      Pilosa
      NaN
      14.4
      2.2
      0.766667
      9.6
      NaN
      3.85
      NaN

      9
      Roe deer
      Capreolus
      herbi
      Artiodactyla
      lc
      3.0
      NaN
      NaN
      21.0
      0.0982
      14.80
      0.006635

```python
df['sleep_total'].hist(grid=False);
```

```python
df.vore.value_counts().plot.barh();
```

```python
df[['vore', 'sleep_total']].groupby('vore').mean().plot(kind='bar');
```

## Embed YouTube

```python
# https://www.youtube.com/watch?v=w-nPeOhEoyw
YouTubeVideo('w-nPeOhEoyw', width=600, height=340)
```

```python
YouTubeVideo('bWlO_H4vuNw', width=600, height=340)
```

## LaTeX

Quadratic equation
$$x=\frac{-b\pm\sqrt{b^2-4ac}}{2a}$$

## Heart curve
http://mathworld.wolfram.com/HeartCurve.html
$$\begin{align}
x&=16sin^3(t)\\
y&=13cos(t)-5cos(2t)-2cos(3t)-cos(4t)
\end{align}$$

```python
def heart():
    # http://mathworld.wolfram.com/HeartCurve.html
    t = np.linspace(0, 2 * np.pi, 360)
    # print(t)
    x = 16 * np.sin(t) ** 3
    y = 13 * np.cos(t) - 5 * np.cos(2 * t) - 2 * np.cos(3 * t) - np.cos(4 * t)
    plt.plot(x, y, color='pink')
    plt.plot(x + 10, y)
    plt.show()

def heart2():
    # http://mathworld.wolfram.com/HeartCurve.html
    t = np.linspace(0, 2 * np.pi, 360)
    # print(t)
    x = 16 * np.sin(t) ** 3
    y = 13 * np.cos(t) - 5 * np.cos(2 * t) - 2 * np.cos(3 * t) - np.cos(4 * t)
    r = np.linspace(.1, 1, 5)
    plt.text(0, 0, "I \u2764 Python")

    for n in r:
        # plt.plot(x + n, y)
        # plt.plot(x * n, y)
        # plt.plot(x * n / 5, y)
        plt.plot(x * n / 5, y * n / 5)
    plt.show()
```

```python
heart()
```

```python
heart2()
```