Lehtikauppias on tilastoinut iltapäivälehden kysyntää. Kysyntä vaihtelee jonkin verran viikonpäivän mukaan. Lehtikauppias on laskenut tilaston perusteella kunkin viikonpäivän kysynnälle keskiarvon ja keskihajonnan. Tietyn viikonpäivän kysynnän voidaan olettaa noudattavan normaalijakaumaa.
Lehtikauppiaan täytyy ilmoittaa etukäteen tilattavien lehtien lukumäärä. Lehtikauppias pyrkii tietenkin tyydyttämään kysynnän mahdollisimman hyvin ja toisaalta hankkimaan itselleen mahdollisimman korkean voiton. Simulointimallissa simuloidaan kysynnän määriä normaalijakaumasta ja lasketaan simulaatiokierrosten tilastolliset tunnusluvut voitolle ja puuttuvien lehtien määrälle.
Lehtikauppias voisi solmia nk. palautussopimuksen, jolloin myymättömistä lehdistä saa täyden hyvityksen lehtitalolta. Tässä tapauksessa lehden hinta on kauppiaalle korkeampi. Simulointimallissa on laskettu voiton tunnusluvut myös palautussopimusta käyttäen.
import numpy as np
import pandas as pd
TOISTOJA = 10000 #simulointikierrosten lukumäärä
KESKIARVO = 520 #päivämyynnin keskiarvo
KESKIHAJONTA = 50 #päivämyynnin keskihajonta
OSTOHINTA_EI_PALAUTUSTA = 0.25
OSTOHINTA_PALAUTUS = 0.33
MYYNTIHINTA = 1
yhteenveto = pd.DataFrame()
for tilaus in range(510, 600, 10):
kysyntä = np.random.normal(loc = KESKIARVO, scale = KESKIHAJONTA, size = TOISTOJA)
kysyntä = np.round(kysyntä)
myynti = (kysyntä > tilaus) * tilaus + (kysyntä <= tilaus) * kysyntä
voitto_palautus = myynti * (MYYNTIHINTA-OSTOHINTA_PALAUTUS)
voitto_ei_palautusta = myynti * (MYYNTIHINTA - OSTOHINTA_EI_PALAUTUSTA) - (tilaus-myynti) * OSTOHINTA_PALAUTUS
ilman_lehteä = kysyntä - myynti
yhteenveto['Palautus', tilaus] = voitto_palautus
yhteenveto['Ei palautusta', tilaus] = voitto_ei_palautusta
yhteenveto['Ilman lehteä', tilaus] = ilman_lehteä
yhteenveto.mean() #voittojen ja ilman lehteä jääneiden keskiarvot eri tapauksissa
(Palautus, 510) 331.468966 (Ei palautusta, 510) 366.008184 (Ilman lehteä, 510) 25.208100 (Palautus, 520) 335.184920 (Ei palautusta, 520) 368.698080 (Ilman lehteä, 520) 20.028000 (Palautus, 530) 338.061900 (Ei palautusta, 530) 370.035600 (Ilman lehteä, 530) 15.319300 (Palautus, 540) 340.713090 (Ei palautusta, 540) 371.009160 (Ilman lehteä, 540) 11.460100 (Palautus, 550) 342.851998 (Ei palautusta, 550) 371.156952 (Ilman lehteä, 550) 8.321900 (Palautus, 560) 343.883463 (Ei palautusta, 560) 369.519612 (Ilman lehteä, 560) 5.877200 (Palautus, 570) 345.022396 (Ei palautusta, 570) 368.055504 (Ilman lehteä, 570) 4.184500 (Palautus, 580) 346.469060 (Ei palautusta, 580) 367.087440 (Ilman lehteä, 580) 2.886600 (Palautus, 590) 346.997623 (Ei palautusta, 590) 364.639452 (Ilman lehteä, 590) 1.811700 dtype: float64
yhteenveto.describe().style.format('{:.0f}') #tarkempi analyysi eri tapauksista
('Palautus', 510) | ('Ei palautusta', 510) | ('Ilman lehteä', 510) | ('Palautus', 520) | ('Ei palautusta', 520) | ('Ilman lehteä', 520) | ('Palautus', 530) | ('Ei palautusta', 530) | ('Ilman lehteä', 530) | ('Palautus', 540) | ('Ei palautusta', 540) | ('Ilman lehteä', 540) | ('Palautus', 550) | ('Ei palautusta', 550) | ('Ilman lehteä', 550) | ('Palautus', 560) | ('Ei palautusta', 560) | ('Ilman lehteä', 560) | ('Palautus', 570) | ('Ei palautusta', 570) | ('Ilman lehteä', 570) | ('Palautus', 580) | ('Ei palautusta', 580) | ('Ilman lehteä', 580) | ('Palautus', 590) | ('Ei palautusta', 590) | ('Ilman lehteä', 590) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 | 10000 |
mean | 331 | 366 | 25 | 335 | 369 | 20 | 338 | 370 | 15 | 341 | 371 | 11 | 343 | 371 | 8 | 344 | 370 | 6 | 345 | 368 | 4 | 346 | 367 | 3 | 347 | 365 | 2 |
std | 17 | 28 | 32 | 20 | 31 | 29 | 22 | 35 | 26 | 24 | 38 | 22 | 26 | 42 | 19 | 28 | 45 | 16 | 29 | 47 | 13 | 30 | 49 | 11 | 31 | 50 | 9 |
min | 225 | 195 | 0 | 206 | 161 | 0 | 228 | 192 | 0 | 216 | 170 | 0 | 212 | 161 | 0 | 206 | 148 | 0 | 214 | 158 | 0 | 209 | 146 | 0 | 218 | 157 | 0 |
25% | 326 | 357 | 0 | 326 | 354 | 0 | 326 | 350 | 0 | 326 | 348 | 0 | 326 | 344 | 0 | 325 | 339 | 0 | 325 | 336 | 0 | 326 | 333 | 0 | 326 | 331 | 0 |
50% | 342 | 382 | 10 | 348 | 390 | 1 | 348 | 387 | 0 | 348 | 383 | 0 | 348 | 380 | 0 | 348 | 376 | 0 | 348 | 372 | 0 | 348 | 370 | 0 | 348 | 367 | 0 |
75% | 342 | 382 | 44 | 348 | 390 | 34 | 355 | 398 | 23 | 362 | 405 | 14 | 368 | 412 | 3 | 371 | 414 | 0 | 371 | 410 | 0 | 371 | 407 | 0 | 371 | 403 | 0 |
max | 342 | 382 | 188 | 348 | 390 | 208 | 355 | 398 | 194 | 362 | 405 | 164 | 368 | 412 | 145 | 375 | 420 | 134 | 382 | 428 | 148 | 389 | 435 | 129 | 395 | 442 | 129 |