V předchozím článku jsem se zabýval simulací profitability v tombole a některé detaily se mi ještě úplně nezdály, tak jsem se rozhodl pokračovat v bádání a zpřesnění výsledků.

Hodnoty cen a jejich rozdělení

Abychom docílili věrohodnějších výsledků, hodilo by se generovat hodnoty tombolových cen podle reálného rozdělení, do kterého patří. Našel jsem si nějaký seznam věcí, které tak cca v tombole bývají, a s pomocí umělé inteligence na Bing Chatu jsem pak zkoušel dohledávat jejich ceny. Občas jsme se u toho s Chatbotem trochu nepohodli, ale nakonec jsem se k něčemu dopídil 🙂 .

Z těchto dat mi vyšly následující parametry:

# Fitting of the distribution ' lnorm ' by maximum likelihood 
# Parameters:
#   estimate Std. Error
# meanlog 4.377245  0.3348776
# sdlog   1.640558  0.2367938

Tato distribuce pak vypadá takto, kde 50% cen má hodnotu cca pod 79Kč:

Parametry simulace

V této verzi simulace jsem se soustředil na 4 parametry:

  • % lístků, které si z celkového počtu zakoupíš
  • poměrný zisk tomboly (celková částka, kterou pořadatel utržil prodejem lístků podělená celkovou cenou všech cen v tombole)
  • % počet cen vůči počtu prodaných lístků
  • tvůj poměrný zisk (hodnota vyhraných věcí podělená cenou lístků, které sis koupil)

Vše je vyjádřeno jako % poměr, protože jsem po mnoha pokusech nabyl dojmu, že zde bude spousta interakcí/nelineárních závislostí i mezi dalšími vnitřními parametry, které nyní díky tomuto nemusím sledovat. Oproti minulému pokusu jsem také přidal i počet cen vůči lístkům, protože čím více těchto cen je, tím větší pravděpodobnost výhry jednotlivé lístky mají.

Vizualizace výsledků

Nejdříve si zobrazíme závislost % zakoupených lístků na poměrný zisk a zároveň v souvislosti s poměrným ziskem tomboly, který vypadá takto:

Zde docházíme ke stejnému závěru jako v předchozím článku, a sice že jediný způsob, jak na tombole vydělat, je když se prodají lístky za nižší cenu, než je celková cena tomboly. Dále na grafu vidíme, že bez ohledu na % zakoupených lístků, poměrný zisk zůstává stejný. V absolutních číslech to však znamená, že čím více lístků si koupíš, tím větší efekt bude tento poměrový zisk mít.

Např. pokud pokud pořadatel prodá lístky za 90% ceny hodnoty celé tomboly, tvůj % zisk bude 10%. To znamená, že když si koupíš lístky za 100 Kč, můžeš v průměru očekávat návratnost 110 Kč, ale když jich koupíš jednou tolik (za 200 Kč), tak i průměrná návratnost bude 2x vyšší (220 Kč). A naopak, pokud pořadatel prodá za více než je cena tomboly, pak čím více lístků si koupíš, tím hůře pro tebe. Takže počet zakoupených lístků funguje jako takový násobitel efektu zisku nebo ztráty.

Pokud si stejný graf obarvíme podle % počtu cen, dostaneme:

Zde se vliv % počtu cen nejeví jako nijak viditelný (v lineárním modelu mi tento vliv jako statisticky významný pak sice vyšel, ale jeho efekt byl velmi malý, takže si myslím, že ho můžeme pro zjednodušení zanedbat. Černá čárkovaná čára (stejně jako na předchozím grafu) označuje break even oblast (neboli ani zisk, ani ztráta).

Zajímavé je, že i ve světle modře obarvených místech, kde je počet cen 100% (tzn. prodává se 200 lístků a v tombole je 200 cen; každý lístek tudíž vyhrává), je možné jak vydělat, ale tak i prodělat. A opět to závisí jen a pouze na poměrném zisku tomboly.

Hledání modelu

Při hledání modelu jsem nakonec po mnoha kombinacích došel až k překvapivě jednoduchému výsledku. Vyšlo mi, že poměrný zisk, se dá dost dobře modelovat pouze jako převrácená hodnota poměrného zisku tomboly:

Call:
lm(formula = zisk ~ I(1/p_zisk_tomboly), data = out)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.63884 -0.01593  0.00022  0.01561  0.54179 

Coefficients:
                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)         0.0008711  0.0020619   0.422    0.673    
I(1/p_zisk_tomboly) 0.9987651  0.0018459 541.058   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.05507 on 7998 degrees of freedom
Multiple R-squared:  0.9734,	Adjusted R-squared:  0.9734 
F-statistic: 2.927e+05 on 1 and 7998 DF,  p-value: < 2.2e-16

Model je statisticky významný, vysvětluje až 97,3% celkového rozptylu, ale také první a druhý koeficient lineární rovnice jsou téměř 0 a 1, což nám teď krásně nahrává pokusit se přejít do ryze matematické roviny.

Vizuálně model vypadá takto:

a residuals plot:

Matematika vrací úder

V předchozím článku jsem psal, že mé matematické pokusy se k něčemu dopočítat sice selhaly, ale nyní mám novou šanci jít na to z jinačího úhlu pohledu. Z výše uvedeného modelu vyplývá, že by to celé vlastně mohlo být až takto jednoduché:

kde Zp je poměrný zisk a Zpt poměrný zisk tomboly. Řešením rovnic pak získáme vzorec pro výpočet očekávaného zisku:

kde význam jednotlivých symbolů je následující:

  • Z … zisk v Kč
  • Ht … celková hodnota cen v tombole
  • Pzl … počet zakoupených lístků (ty, které sis koupil)
  • Pl … celkový počet prodaných lístků
  • Cl … cena jednoho lístku

Ověření matematického modelu

Pokud pomocí nasimulovaných dat dopočítám potřebné parametry a pak pro predikci zisku použiju výše zmíněný vzorec, tak residuals plot vypadá následovně:

což za mě vypadá velmi dobře. Co se týká přesnosti modelu, tak průměrná absolutní chyba je ±9,10 Kč, a když si spočítáme kvantily:

> quantile(math_df$residuals, c(.025,.975))
     2.5%     97.5% 
-25.87490  25.95036 

tak si můžeme být na 95% jistí, že chyba tohoto vzorce se bude pohybovat v rozmezí ±25,9 Kč. Takže tolik k tombole a k tomu, na čem závisí finanční úspěch jejich účastníků. Příště mám v plánu ještě jeden článek pro ty, kterým nejde o peníze, ale chcou prostě jen vyhrát 🙂 .

Kód

spust_tombolu = function(p_tvych_listku, p_zisk_tomboly, p_pocet_cen) {
  pocet_prodanych_listku = 200
  pocet_tvych_listku = (p_tvych_listku*pocet_prodanych_listku) |> round()
  
  pocet_cen = (p_pocet_cen*pocet_prodanych_listku) |> round()
  
  hodnoty_cen = rlnorm(pocet_cen,4.377245, 1.640558)
  hodnota_cen_total = sum(hodnoty_cen)
  cena_listku = (p_zisk_tomboly*hodnota_cen_total)/pocet_prodanych_listku
  
  cena_tvych_listku = pocet_tvych_listku*cena_listku
  
  listky_v_losovani = 1:pocet_prodanych_listku
  
  tve_listky = sample(listky_v_losovani, pocet_tvych_listku)
  
  vylosovate_listky = sample(listky_v_losovani, pocet_cen)
  
  tve_vyherni_listky = intersect(vylosovate_listky, tve_listky)
  pocet_vyhernich_listku = length(tve_vyherni_listky)
  
  hodnota_vyher = sample(hodnoty_cen, pocet_vyhernich_listku) |> sum()
  
  pomerovy_zisk = hodnota_vyher / cena_tvych_listku
  pomerovy_zisk
}