Players age every offseason. All players start as blank slates at age 15, and are aged up from 15 to their current age; this includes players on starting rosters, as well as players in the draft pool. Here is the average simulated OPS of a hitter at various ages along with standard deviations in the population (these aren't error bars); the pitcher graph is probably the opposite average-wise. These are current as of the end of year 1.
age 16: 0.552 +/- 0.056
age 17: 0.604 +/- 0.080
age 18: 0.660 +/- 0.096
age 19: 0.710 +/- 0.096
age 20: 0.743 +/- 0.113
age 21: 0.742 +/- 0.107
age 22: 0.776 +/- 0.119
age 23: 0.804 +/- 0.130
age 24: 0.810 +/- 0.134
age 25: 0.824 +/- 0.133
age 26: 0.817 +/- 0.137
age 27: 0.806 +/- 0.161
age 28: 0.781 +/- 0.131
age 29: 0.774 +/- 0.123
age 30: 0.764 +/- 0.140
age 31: 0.730 +/- 0.132
age 32: 0.678 +/- 0.142
age 33: 0.647 +/- 0.139
age 34: 0.574 +/- 0.119
age 35: 0.540 +/- 0.133
age 36: 0.492 +/- 0.125
age 37: 0.463 +/- 0.125
age 38: 0.411 +/- 0.116
age 39: 0.342 +/- 0.083
age 40: 0.303 +/- 0.102
and for pitchers:
age 16: 0.984 +/- 0.086
age 17: 0.918 +/- 0.079
age 18: 0.889 +/- 0.088
age 19: 0.852 +/- 0.091
age 20: 0.813 +/- 0.098
age 21: 0.800 +/- 0.100
age 22: 0.795 +/- 0.091
age 23: 0.765 +/- 0.109
age 24: 0.785 +/- 0.110
age 25: 0.787 +/- 0.106
age 26: 0.762 +/- 0.111
age 27: 0.784 +/- 0.127
age 28: 0.800 +/- 0.119
age 29: 0.819 +/- 0.113
age 30: 0.852 +/- 0.134
age 31: 0.850 +/- 0.133
age 32: 0.914 +/- 0.150
age 33: 0.935 +/- 0.156
age 34: 1.008 +/- 0.166
age 35: 1.094 +/- 0.176
age 36: 1.126 +/- 0.182
age 37: 1.231 +/- 0.202
age 38: 1.315 +/- 0.182
age 39: 1.461 +/- 0.181
age 40: 1.574 +/- 0.174

The probabilities UP and DOWN are a function of the player's age. UP is given by max(0.95, 1.06-age), where age is the age that the player is becoming. DOWN is given by UP(51-age) (hence symmetry). So at age 25 for instance, UP is 0.81 and DOWN is 0.80. As anyone familiar with probability will recall, the expected number of UPs in this process is given by UP/(1-UP), so on average at age 25 you would expect 4+ UPs and 4 DOWNs. This process obviously has a large amount of volatility, and there is essentially no cap on the process; however, many abilities suffer diminishing marginal returns (to take one example, once a pitcher has good enough control to literally walk nobody, further improvements to control are not meaningful).

Almost all skills work this way. The exceptions are defense for hitters and bonus for pitchers. Defense for hitters is less volatile; a hitter is rated for defense at each position. The player has an athleticism change which is a function of their (new) age, given by rand((25.5-age) * 0.6). Call this random-variable athleticism change x; then a player then has defense at each position change accordingly. For their listed position (which the GM can choose and change at any time), it is rand(base). For related positions (other infield positions if the player is an infielder, and other outfield positions if the player is an outfielder; catcher is related to nothing), it is x-rand(1), and for unrelated positions it is x-rand(2). x is the same for all positions, but the other random numbers are generated one per position (not counting the listed position). Note that this has changed, so original players will have screwier defense, though with the same expected value.

Pitchers have two skills, bonus and stamina, which are determined by their role. Pitcher stamina (number of pitches on average to get 5 fatigue) is 80 for starters, 40 for MRs, and 20 for relievers; bonus is 0 for starters, 2 for MRs, and 3 for relievers. In addition, if you switch a pitcher's role, he gets a penalty for the new role (modeling unfamiliarity): this starts at -2 upon the position switch, and asymptotes to 0. Every offseason (including the first), the pitcher loses a fraction of rand(1) * rand(1) of his penalty, so on average, he will get a quarter of the way to the target, but with sizable variance -- could get all the way there, could not move at all.