Panel badania: ujawnienia AI w GAMAM
Szkoła Główna Handlowa w Warszawie | 2026
Instrukcja:
Interfejs umożliwia zdalne wykonanie skryptu na serwerze – wyniki obliczeń są na bieżąco wyświetlane w konsoli.
Istnieje również możliwość pobrania kompletnego pakietu replikacyjnego (skrypt, dane, wyniki) w celu weryfikacji lub własnych analiz.
Uruchomione badanie działa niezależnie od użytkownika. Kolejne uruchomienie możliwe jest po zakończeniu poprzedniego.
Istnieje również możliwość pobrania kompletnego pakietu replikacyjnego (skrypt, dane, wyniki) w celu weryfikacji lub własnych analiz.
Uruchomione badanie działa niezależnie od użytkownika. Kolejne uruchomienie możliwe jest po zakończeniu poprzedniego.
Skrypt badania
# =====================================================================
# MASTER SCRIPT
# =====================================================================
#
# SPIS TREŚCI
# 0. Instalacja i wczytanie bibliotek – wiersz 107
# (ładowanie wszystkich niezbędnych pakietów)
# 1. Uniwersalny słownik – w. 125
# (terminy ogólne, specyficzne, future, risk)
# 2. Funkcje pomocnicze – w. 208
# (zliczanie terminów, słów, segmentacja zdań, synchronizacja kalendarzowa)
# 3. Analiza raportów 10-K (całe raporty) – w. 376
# - Analiza całych raportów 10-K (gęstość AI na 1000 słów)
# - Tabela 5: Liczba odniesień do AI
# - Tabela 6: Gęstość na 1000 słów
# - Tabela 6.1: Średnia dla grupy GAMAM
# 4. Analiza sekcji narracyjnych (Business, MD&A, Risk Factors) – w. 456
# - Analiza gęstości AI w poszczególnych sekcjach
# - Test Kruskala-Wallisa różnic między sekcjami
# - Tabela H1: Porównanie sekcji narracyjnych vs finansowa
# - Weryfikacja hipotezy H1
# 5. Analiza raportów 10-Q – w. 549
# - Synchronizacja kalendarzowa (rok fiskalny → kalendarzowy)
# - Agregacja roczna (Q1-Q3)
# - Tabela 10: Gęstość 10-Q
# - Tabela 10.1: Średnia GAMAM (10-Q)
# 6. Analiza Earnings Calls – w. 697
# - Synchronizacja kalendarzowa (rok fiskalny → kalendarzowy)
# - Podział na presentation i Q&A
# - Tabela 13: Gęstość EC (średnia roczna)
# - Tabela 13.1: Średnia GAMAM (EC)
# - Tabela 13.2: Podział presentation/Q&A
# - Korelacja Spearmana: presentation vs Q&A
# - Porównanie EC vs 10-K - weryfikacja H2
# 7. Korelacje ujawnień z R&D i CAPEX (H3) – w. 913
# - Korelacje Spearmana (globalne i wewnątrz spółek)
# - Regresja panelowa Fixed Effects (10-K)
# * Model CAPEX (surowy)
# * Model R&D (surowy)
# * Model łączny CAPEX + R&D
# * Modele log-log
# * Model z efektami czasowymi
# - Test Hausmana (FE vs RE)
# - Test F (FE vs Pooled OLS)
# - Tabela 16: Korelacje Spearmana dla EC
# - Tabela 17: Modele panelowe dla EC
# - Weryfikacja hipotezy H3
# 8. Analiza jakościowa (Future/Risk, General/Specific) – w. 1182
# - Analiza kontekstu: Future i Risk w zdaniach z AI
# - Podział na terminy ogólne i specyficzne
# - Tabela 22: Średnia dla grupy GAMAM (ważona)
# - Tabela 23: Podział na spółki (ważony)
# 9. Event Study – w. 1221
# - Obliczanie CAR dla okien [-1,+1], [-3,+3], [-5,+5]
# - Podział na HIGH/LOW według mediany gęstości AI
# - Tabele 26 i 25: Test hipotezy H4 (regresja + Mann-Whitney)
# - CAAR (średnie CAR) z testem t
# - Regresja CAR (M1, M2, M3)
# - Tabela 27: Test BMP
# - Analiza wolumenu obrotu (zmiana procentowa)
# - Specyfikacja T+0 (dzień publikacji)
# - Specyfikacja bez roku 2022
# - Test Placebo
# - Test Corrado
# - Alternatywne testy statystyczne dla H4:
# * Test permutacyjny
# * Bayes Factor
# * Regresja kwantylowa (mediana)
# * Bootstrapowy przedział ufności (95%)
# * Analiza zmiany intensywności (delta_density)
# 10. Funkcja główna main() – w. 2451
#
# Format plików w poszczególnych załącznikach:
# - pkt 3 (10-K, całe raporty) → .txt
# - pkt 4 (10-K, sekcje narracyjne) → .txt
# - pkt 5 (10-Q) → .pdf
# - pkt 6 (Earnings calls) → .txt
# - pkt 7 (Korelacje z R&D/CAPEX) → dane z pkt 3 i 6 (brak własnych plików)
# - pkt 8 (Analiza jakościowa) → dane z pkt 3 i 6 (brak własnych plików)
# - pkt 9 (Event Study) → .pdf (10-K i 10-Q) + .txt (Earnings calls) + .csv + .xlsx
# Wymagane nazwy plików (przykłady):
# - pkt 3 (10-K, cały raport): `10-K 2024 Microsoft.txt`
# - pkt 4 (sekcje narracyjne):
# * Business: `Microsoft 2025 10-K Business.txt`
# * MD&A: `Microsoft 2025 10-K MD&A.txt`
# * Risk: `Microsoft 2025 10-K Risk Factors.txt`
# - pkt 5 (10-Q): `10-Q3 2023 Alphabet.pdf`
# - pkt 6 (Earnings calls): `Amazon_2023_Q2_earnings.txt`
# - pkt 9 (Event Study):
# * 10-K (.pdf): `10-K 2024 Apple.pdf`
# * 10-Q (.pdf): `10-Q2 2022 Meta.pdf`
# * Earnings calls (.txt): `Alphabet_2023_Q2_earnings.txt`
# * Dane cenowe (.csv): `AAPL_US.csv`, `MSFT_US.csv`, `GOOGL_US.csv`,
# `AMZN_US.csv`, `META_US.csv`, `SPX_US.csv`
# * Daty zdarzeń i EPS_suprise (.xlsx): `mag_tabele_i_wykresy.xlsx`
# =====================================================================
# ŚCIEŻKI
folder_10k <- "10K"
folder_narrative <- "Business - Risk Factors - MD&A"
folder_10q <- "10-Q"
folder_ec <- "earnings_calls"
folder_prices <- "event_study"
# =====================================================================
# 0. INSTALACJA I WCZYTANIE BIBLIOTEK
# =====================================================================
required_packages <- c(
"stringr", "tidyr", "dplyr", "lubridate",
"plm", "lmtest", "sandwich", "pdftools",
"readxl", "quantreg", "car", "clubSandwich",
"BayesFactor"
)
# Bezpieczne ładowanie pakietów bez prób ich reinstalacji
suppressPackageStartupMessages({ for (pkg in required_packages) {
if (!require(pkg, character.only = TRUE)) {
stop(paste("Błąd krytyczny: Brak pakietu", pkg, "na serwerze!"))
}
} })
# =====================================================================
# 1. SŁOWNIK
# =====================================================================
# --- Terminy ogólne ---
AI_TERMS_GENERAL <- c(
# --- Terminy ogólne i strategiczne ---
"artificial intelligence", "\\bai\\b", "\\bai-", "machine intelligence",
"cognitive computing", "sovereign ai", "ai strategy", "ai investment",
"ai initiative", "ai research",
# --- Uczenie maszynowe i Architektura ---
"machine learning", "\\bml\\b", "supervised learning", "unsupervised learning",
"reinforcement learning", "deep learning", "neural network", "neural networks",
"\\bcnn\\b", "\\brnn\\b", "transformer model", "attention mechanism",
"neural engine", "\\bnpu\\b"
)
# --- Terminy specyficzne (Specific) ---
AI_TERMS_SPECIFIC <- c(
# --- Generatywna AI i Agenci ---
"generative ai", "\\bgenai\\b", "generative model", "diffusion model",
"large language model", "large language models", "\\bllm\\b", "\\bllms\\b",
"foundation model", "multimodal model", "\\bgpt\\b", "\\bchatgpt\\b", "\\bai agent\\b",
"agentic ai", "context window", "parameter count",
# --- Procesy modelowe i Interakcja ---
"model training", "inference engine", "fine-tuning", "pre-training",
"model deployment", "\\bprompting\\b", "\\btokenization\\b", "cost per token",
# --- Infrastruktura AI ---
"ai compute", "\\bgpu\\b", "\\bgpus\\b", "\\btpu\\b", "compute cluster",
"data pipeline", "data labeling", "ai workloads", "ai platform",
"on-device ai", "edge ai",
# --- Zastosowania ---
"autonomous systems", "recommendation engine", "algorithmic recommendation",
"anomaly detection", "predictive analytics",
# --- Ryzyka, etyka i bezpieczeństwo ---
"model risk", "model bias", "\\bexplainability\\b", "\\bhallucination\\b",
"responsible ai", "ethical ai", "ai governance", "ai compliance",
"adversarial attack", "data poisoning",
# --- Brand Terms - Alphabet ---
"google ai", "\\bgemini\\b", "\\bbard\\b", "\\bdeepmind\\b", "vertex ai", "\\bpaalm\\b", "tpu v5",
# --- Brand Terms - Microsoft ---
"microsoft ai", "\\bcopilot\\b", "azure ai", "\\bopenai\\b", "\\bphi–3\\b", "copilot\\+",
# --- Brand Terms - Meta ---
"meta ai", "\\bllama\\b", "\\bpytorch\\b", "segment anything", "superintelligence",
# --- Brand Terms - Amazon ---
"amazon ai", "\\balexa\\b", "amazon q", "aws ai", "\\bbedrock\\b", "\\btitan\\b",
# --- Brand Terms - Apple ---
"apple intelligence", "\\bsiri\\b", "\\bajax\\b"
)
ALL_AI_TERMS <- c(AI_TERMS_GENERAL, AI_TERMS_SPECIFIC)
ALL_AI_TERMS_SORTED <- ALL_AI_TERMS[order(nchar(ALL_AI_TERMS), decreasing = TRUE)]
FUTURE_INDICATORS <- c(
"will", "expect", "anticipate", "plan", "intend", "goal", "target",
"outlook", "guidance", "pipeline", "roadmap", "future", "upcoming",
"next year", "next quarter", "long-term", "strategic", "opportunity",
"potential", "going forward", "looking ahead", "we believe",
"we project", "we forecast", "we aim", "committed to", "investing in",
"expanding", "scaling", "ramp up"
)
RISK_INDICATORS <- c(
"risk", "risks", "uncertainty", "uncertainties", "challenge", "challenges",
"concern", "concerns", "threat", "threats", "exposure", "vulnerability",
"vulnerabilities", "caution", "cautionary", "subject to", "potential adverse", "adverse", "difficult", "difficulties",
"complex", "complexity", "regulatory", "regulation", "compliance",
"ethical", "bias", "hallucination", "misuse", "abuse", "safeguard",
"mitigate", "mitigation", "unforeseen", "unexpected", "volatile",
"disruption", "liability", "litigation", "may", "could", "might"
)
# =====================================================================
# 2. FUNKCJE POMOCNICZE
# =====================================================================
count_terms <- function(text, terms_list) {
if (is.na(text) || nchar(text) == 0) return(0)
text_clean <- clean_text(text)
total_count <- 0
for (term in terms_list) {
if (grepl("\\\\b", term)) {
pattern <- term
} else if (grepl(" ", term)) {
term_regex <- str_replace_all(term, " ", "\\\\s+")
pattern <- paste0("\\b", term_regex, "\\b")
} else {
pattern <- paste0("\\b", term, "\\b")
}
count <- str_count(text_clean, pattern)
total_count <- total_count + count
text_clean <- str_remove_all(text_clean, pattern)
}
return(total_count)
}
count_words <- function(text) {
if (is.na(text) || nchar(text) == 0) return(0)
return(length(str_split(tolower(text), "\\s+")[[1]]))
}
calculate_density <- function(mentions, words) {
result <- ifelse(words > 0, (mentions / words) * 1000, 0)
return(round(result, 2))
}
count_terms_with_details <- function(text, terms_list) {
text_lower <- tolower(text)
total_count <- 0
term_counts <- list()
clean_length <- function(t) {
nchar(str_replace_all(t, "\\\\b", ""))
}
sorted_terms <- terms_list[order(sapply(terms_list, clean_length), decreasing = TRUE)]
for (term in sorted_terms) {
if (str_detect(term, "^\\\\b")) {
pattern <- term
} else {
pattern <- paste0("\\b", str_replace_all(term, "([.\\\\+*?\\[\\^\\]$()])", "\\\\\\1"), "\\b")
}
matches <- str_extract_all(text_lower, regex(pattern, ignore_case = TRUE))[[1]]
count <- length(matches)
if (count > 0) {
total_count <- total_count + count
term_counts[[term]] <- count
text_lower <- str_replace_all(text_lower, regex(pattern, ignore_case = TRUE), "")
}
}
return(list(total = total_count, counts = term_counts))
}
ABBREVIATIONS <- c("Mr", "Mrs", "Ms", "Dr", "Prof", "Inc", "Corp", "Co", "Ltd",
"Jan", "Feb", "Mar", "Apr", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
"e.g", "i.e", "vs", "etc")
split_into_sentences <- function(text) {
text <- str_replace_all(text, "\\.{3,}", "___ELLIPSIS___")
for (abbr in ABBREVIATIONS) {
text <- str_replace_all(text, paste0("\\b", abbr, "\\."), paste0(abbr, "___DOT___"))
}
text <- str_replace_all(text, "(\\d)\\.(\\d)", "\\1___DECIMAL___\\2")
sentences <- str_split(text, "(?<=[.!?])\\s+")[[1]]
sentences <- str_replace_all(sentences, "___DOT___", ".")
sentences <- str_replace_all(sentences, "___DECIMAL___", ".")
sentences <- str_replace_all(sentences, "___ELLIPSIS___", "...")
sentences <- sentences[str_trim(sentences) != ""]
return(sentences)
}
sentence_has_ai <- function(sentence, terms_list) {
sentence_lower <- tolower(sentence)
for (term in terms_list) {
if (grepl("\\\\b", term)) {
if (str_detect(sentence_lower, regex(term, ignore_case = TRUE))) return(TRUE)
} else {
if (str_detect(sentence_lower, regex(paste0("\\b", term, "\\b"), ignore_case = TRUE))) return(TRUE)
}
}
return(FALSE)
}
analyze_qualitative <- function(text, company, year, doc_type) {
total_words <- count_words(text)
result <- count_terms_with_details(text, ALL_AI_TERMS_SORTED)
total_ai_count <- result$total
term_counts <- result$counts
general_count <- 0
specific_count <- 0
for (term in names(term_counts)) {
if (term %in% AI_TERMS_GENERAL) {
general_count <- general_count + term_counts[[term]]
} else if (term %in% AI_TERMS_SPECIFIC) {
specific_count <- specific_count + term_counts[[term]]
}
}
ai_per_1000 <- if (total_words > 0) (total_ai_count / total_words) * 1000 else 0
if (total_ai_count > 0) {
pct_general <- (general_count / total_ai_count) * 100
pct_specific <- (specific_count / total_ai_count) * 100
} else {
pct_general <- 0
pct_specific <- 0
}
sentences <- split_into_sentences(text)
future_count <- 0
risk_count <- 0
ai_sentences <- 0
for (sentence in sentences) {
if (sentence_has_ai(sentence, ALL_AI_TERMS_SORTED)) {
ai_sentences <- ai_sentences + 1
sent_lower <- tolower(sentence)
if (any(sapply(FUTURE_INDICATORS, function(x) grepl(x, sent_lower, fixed = TRUE)))) future_count <- future_count + 1
if (any(sapply(RISK_INDICATORS, function(x) grepl(x, sent_lower, fixed = TRUE)))) risk_count <- risk_count + 1
}
}
pct_future <- if (ai_sentences > 0) round(future_count / ai_sentences * 100, 1) else 0
pct_risk <- if (ai_sentences > 0) round(risk_count / ai_sentences * 100, 1) else 0
return(data.frame(
company = company, year = year, doc_type = doc_type,
total_words = total_words, total_ai = total_ai_count,
AI_Total = total_ai_count,
AI_Specific_Count = specific_count,
AI_General_Count = general_count,
AI_Sentences_Count = ai_sentences,
Future_Count = future_count,
Risk_Count = risk_count,
mentions = total_ai_count, words = total_words, density = round(ai_per_1000, 2),
pct_general = round(pct_general, 1), pct_specific = round(pct_specific, 1),
pct_future = pct_future, pct_risk = pct_risk,
stringsAsFactors = FALSE
))
}
sync_calendar <- function(fiscal_year, fiscal_quarter, company) {
cal_year <- as.numeric(fiscal_year)
cal_quarter <- fiscal_quarter
if (company == "MSFT") {
if (fiscal_quarter == "Q1") { cal_quarter <- "Q3"; cal_year <- cal_year - 1 }
else if (fiscal_quarter == "Q2") { cal_quarter <- "Q4"; cal_year <- cal_year - 1 }
else if (fiscal_quarter == "Q3") { cal_quarter <- "Q1" }
else if (fiscal_quarter == "Q4") { cal_quarter <- "Q2" }
} else if (company == "AAPL") {
if (fiscal_quarter == "Q1") { cal_quarter <- "Q4"; cal_year <- cal_year - 1 }
else if (fiscal_quarter == "Q2") { cal_quarter <- "Q1" }
else if (fiscal_quarter == "Q3") { cal_quarter <- "Q2" }
else if (fiscal_quarter == "Q4") { cal_quarter <- "Q3" }
}
return(list(year = as.character(cal_year), quarter = cal_quarter))
}
# =====================================================================
# 3. ANALIZA RAPORTÓW 10-K
# =====================================================================
clean_text <- function(text) {
if (is.na(text) || nchar(text) == 0) return("")
text %>%
tolower() %>%
str_replace_all("[\r\n\t]", " ") %>%
str_replace_all("\\s+", " ") %>%
str_trim()
}
read_document_text <- function(file_path) {
if (grepl("\\.pdf$", file_path, ignore.case = TRUE)) {
pages <- pdftools::pdf_text(file_path)
pages <- pages[nchar(pages) > 20]
text <- paste(pages, collapse = " ")
text <- gsub("([a-zA-Z])-\\s+([a-zA-Z])", "\\1\\2", text)
text <- gsub("([a-zA-Z])-\\n+([a-zA-Z])", "\\1\\2", text)
text <- gsub("[\r\n\t]", " ", text)
text <- gsub("\\s+", " ", text)
text <- iconv(text, from = "UTF-8", to = "ASCII", sub = " ")
return(clean_text(text))
} else {
text <- paste(readLines(file_path, warn = FALSE), collapse = " ")
return(clean_text(text))
}
}
analyze_10k_full <- function(folder_path) {
cat("\n", strrep("=", 70), "\n")
cat("ZAŁĄCZNIK 2 – ANALIZA RAPORTÓW 10-K (CAŁE RAPORTY)\n")
cat(strrep("=", 70), "\n")
files <- list.files(folder_path, pattern = "\\.txt$", full.names = TRUE, ignore.case = TRUE)
results <- list()
for (file in files) {
name <- basename(file)
company <- case_when(
grepl("Alphabet", name) ~ "GOOGL",
grepl("Amazon", name) ~ "AMZN",
grepl("Apple", name) ~ "AAPL",
grepl("Meta", name) ~ "META",
grepl("Microsoft", name) ~ "MSFT",
TRUE ~ NA_character_
)
year <- str_extract(name, "202[2-5]")
if (is.na(company) || is.na(year)) next
cat("Przetwarzam:", company, year, "-", name, "\n")
text <- read_document_text(file)
if (nchar(text) == 0) next
result <- analyze_qualitative(text, company, year, "10-K")
results[[length(results) + 1]] <- result
cat(" → AI:", result$total_ai, "| gęstość:", result$density, "| Future:", result$pct_future, "% | Risk:", result$pct_risk, "%\n")
}
if (length(results) == 0) return(NULL)
df <- bind_rows(results)
cat("\n--- TABELA 5: Liczba odniesień (10-K) ---\n")
table_5 <- df %>% select(company, year, total_ai) %>%
pivot_wider(names_from = year, values_from = total_ai, values_fill = 0) %>%
mutate(avg_2022_2025 = round((`2022`+`2023`+`2024`+`2025`)/4, 0))
print(table_5)
cat("\n--- TABELA 6: Gęstość na 1000 słów (10-K) ---\n")
table_6 <- df %>% select(company, year, density) %>%
pivot_wider(names_from = year, values_from = density, values_fill = 0) %>%
mutate(avg_2022_2025 = round((`2022`+`2023`+`2024`+`2025`)/4, 2))
print(table_6)
cat("\n--- TABELA 6.1: Średnia GAMAM (10-K) ---\n")
table_7 <- df %>% group_by(year) %>% summarise(gamam_avg_density = round(mean(density), 2))
print(table_7)
return(df)
}
# =====================================================================
# 4. ANALIZA RAPORTÓW 10-K - SEKCJE NARRACYJNE
# =====================================================================
analyze_narrative_sections <- function(folder_path, results_full_10k) {
cat("\n", strrep("=", 70), "\n")
cat("ZAŁĄCZNIK 2.1 – SEKCJE NARRACYJNE (Business, MD&A, Risk Factors)\n")
cat(strrep("=", 70), "\n")
files <- list.files(folder_path, pattern = "\\.txt$", full.names = TRUE)
results <- list()
for (file in files) {
name <- basename(file)
parts <- str_split(str_replace(name, "\\.txt$", ""), " ")[[1]]
company <- case_when(
grepl("MICROSOFT", parts[1], ignore.case = TRUE) ~ "MSFT",
grepl("ALPHABET|GOOGLE", parts[1], ignore.case = TRUE) ~ "GOOGL",
grepl("AMAZON", parts[1], ignore.case = TRUE) ~ "AMZN",
grepl("APPLE", parts[1], ignore.case = TRUE) ~ "AAPL",
grepl("META|FACEBOOK", parts[1], ignore.case = TRUE) ~ "META",
TRUE ~ NA_character_
)
year <- parts[2]
section <- parts[4]
if (is.na(company)) next
cat("Przetwarzam:", company, year, "- sekcja:", section, "\n")
text <- paste(readLines(file, warn = FALSE), collapse = " ")
if (nchar(text) == 0) next
ai_count <- count_terms(text, ALL_AI_TERMS_SORTED)
word_count <- count_words(text)
density <- calculate_density(ai_count, word_count)
results[[length(results) + 1]] <- data.frame(
company = company, year = year, section = section,
ai_count = ai_count, word_count = word_count, density = density,
stringsAsFactors = FALSE
)
cat(" → AI:", ai_count, "| gęstość:", density, "\n")
}
if (length(results) == 0) return(NULL)
df <- bind_rows(results)
cat("\n--- TABELA 7: Średnia gęstość w poszczególnych sekcjach ---\n")
table_sections <- df %>% group_by(section, year) %>%
summarise(srednia_gestosc = round(mean(density), 2), .groups = "drop") %>%
pivot_wider(names_from = year, values_from = srednia_gestosc, values_fill = 0)
print(table_sections)
for (rok in c("2022", "2023", "2024", "2025")) {
dane_rok <- df %>% filter(year == rok)
if (nrow(dane_rok) >= 3 && length(unique(dane_rok$section)) >= 3) {
kw_test <- kruskal.test(density ~ section, data = dane_rok)
cat(paste("Rok", rok, "- p-value =", round(kw_test$p.value, 4)))
if (kw_test$p.value < 0.05) cat(" ✅ Istotne różnice\n") else cat(" ❌ Brak istotnych różnic\n")
}
}
narrative_sum <- df %>% group_by(company, year) %>%
summarise(narrative_ai = sum(ai_count), narrative_words = sum(word_count),
narrative_density = calculate_density(narrative_ai, narrative_words), .groups = "drop")
h1_data <- results_full_10k %>% select(company, year, total_ai, total_words, density) %>%
left_join(narrative_sum, by = c("company", "year")) %>%
mutate(
other_ai = total_ai - narrative_ai,
other_words = total_words - narrative_words,
other_density = calculate_density(other_ai, other_words)
)
cat("\n--- TABELA 8: Porównanie sekcji narracyjnych vs finansowa ---\n")
h1_summary <- h1_data %>% group_by(year) %>%
summarise(
narrative_avg = round(mean(narrative_density, na.rm = TRUE), 2),
other_avg = round(mean(other_density, na.rm = TRUE), 2),
total_avg = round(mean(density, na.rm = TRUE), 2)
)
print(h1_summary)
narrative_2025 <- h1_summary %>% filter(year == 2025) %>% pull(narrative_avg)
other_2025 <- h1_summary %>% filter(year == 2025) %>% pull(other_avg)
cat("\n✅ Hipoteza H1: Gęstość w sekcjach narracyjnych (", narrative_2025,
") > finansowa (", other_2025, ") → POTWIERDZONA\n", sep="")
return(list(sections = df, h1 = h1_summary))
}
# =====================================================================
# 5. ANALIZA RAPORTÓW 10-Q
# =====================================================================
analyze_10q_full <- function(folder_path) {
cat("\n", strrep("=", 70), "\n")
cat("ZAŁĄCZNIK 3 – ANALIZA RAPORTÓW 10-Q\n")
cat(strrep("=", 70), "\n")
clean_text <- function(text) {
text %>%
tolower() %>%
str_replace_all("[\r\n]", " ") %>%
str_replace_all("\\s+", " ") %>%
str_trim()
}
read_pdf_text_improved <- function(pdf_path) {
pages <- pdftools::pdf_text(pdf_path)
pages <- pages[nchar(pages) > 20]
text <- paste(pages, collapse = " ")
text <- gsub("([a-zA-Z])-\\s+([a-zA-Z])", "\\1\\2", text)
text <- gsub("([a-zA-Z])-\\n+([a-zA-Z])", "\\1\\2", text)
text <- gsub("[\r\n\t]", " ", text)
text <- gsub("\\s+", " ", text)
text <- iconv(text, from = "UTF-8", to = "ASCII", sub = " ")
text <- clean_text(text)
return(text)
}
count_terms_10q <- function(text, terms_list) {
text_clean <- clean_text(text)
total_count <- 0
for (term in terms_list) {
if (grepl("\\\\b", term)) {
pattern <- term
} else {
term_regex <- str_replace_all(term, " ", "\\\\s+")
pattern <- paste0("\\b", term_regex, "\\b")
}
count <- str_count(text_clean, regex(pattern, ignore_case = TRUE))
total_count <- total_count + count
text_clean <- str_remove_all(text_clean, regex(pattern, ignore_case = TRUE))
}
return(total_count)
}
count_words_10q <- function(text) {
text_clean <- clean_text(text)
words <- str_split(text_clean, "\\s+")[[1]]
words <- words[words != ""]
return(length(words))
}
extract_calendar_period <- function(filename, company) {
name <- basename(filename)
fy <- as.numeric(str_extract(name, "202[2-6]"))
fq <- str_extract(name, "Q[1-4]")
if (is.na(fq)) fq <- "Q1"
cal_year <- fy
cal_quarter <- fq
if (company == "MSFT") {
if (fq == "Q1") { cal_quarter <- "Q3"; cal_year <- fy - 1 }
else if (fq == "Q2") { cal_quarter <- "Q4"; cal_year <- fy - 1 }
else if (fq == "Q3") { cal_quarter <- "Q1" }
else if (fq == "Q4") { cal_quarter <- "Q2" }
} else if (company == "AAPL") {
if (fq == "Q1") { cal_quarter <- "Q4"; cal_year <- fy - 1 }
else if (fq == "Q2") { cal_quarter <- "Q1" }
else if (fq == "Q3") { cal_quarter <- "Q2" }
else if (fq == "Q4") { cal_quarter <- "Q3" }
}
return(list(year = as.character(cal_year), quarter = cal_quarter))
}
extract_company_10q <- function(filename) {
name <- toupper(basename(filename))
if (grepl("META", name)) return("META")
if (grepl("GOOGL|GOOG|ALPHABET", name)) return("GOOGL")
if (grepl("MSFT|MICROSOFT", name)) return("MSFT")
if (grepl("AMZN|AMAZON", name)) return("AMZN")
if (grepl("AAPL|APPLE", name)) return("AAPL")
return("UNKNOWN")
}
files <- list.files(folder_path, pattern = "\\.pdf$", full.names = TRUE, ignore.case = TRUE)
results <- list()
for (file in files) {
company <- extract_company_10q(file)
if (company == "UNKNOWN") next
period <- extract_calendar_period(file, company)
year <- period$year
quarter <- period$quarter
if (is.na(year) || !year %in% c("2022", "2023", "2024", "2025")) next
cat("Przetwarzam:", company, "→ CY", year, quarter, "-", basename(file), "\n")
text <- read_pdf_text_improved(file)
if (nchar(text) < 100) next
mentions <- count_terms_10q(text, ALL_AI_TERMS_SORTED)
words <- count_words_10q(text)
density <- ifelse(words > 0, round((mentions / words) * 1000, 2), 0)
results[[length(results) + 1]] <- data.frame(
company = company, year = year, quarter = quarter,
total_mentions = mentions, word_count = words, density = density,
stringsAsFactors = FALSE
)
cat(" → AI:", mentions, "| gęstość:", density, "\n")
}
if (length(results) == 0) return(NULL)
df <- bind_rows(results)
cat("\n=== 10-Q: Wczytano", nrow(df), "plików ===\n")
annual <- df %>%
filter(quarter %in% c("Q1", "Q2", "Q3")) %>%
group_by(company, year) %>%
summarise(
total_mentions = sum(total_mentions),
word_count = sum(word_count),
density = round((sum(total_mentions) / sum(word_count)) * 1000, 2),
.groups = "drop"
)
cat("\n--- TABELA 10: Gęstość 10-Q (agregacja roczna Q1-Q3) ---\n")
table_9 <- annual %>% select(company, year, density) %>%
pivot_wider(names_from = year, values_from = density, values_fill = 0) %>%
mutate(
avg = round((`2022` + `2023` + `2024` + `2025`) / 4, 2),
change_pp = round(`2025` - `2022`, 2),
change_pct = round(((`2025` - `2022`) / `2022`) * 100, 1)
)
print(table_9)
cat("\n--- TABELA 10.1: Średnia GAMAM (10-Q) ---\n")
table_10 <- annual %>% group_by(year) %>% summarise(gamam_avg_density = round(mean(density), 2))
print(table_10)
return(list(raw = df, annual = annual))
}
# =====================================================================
# 6. ANALIZA EARNINGS CALLS
# =====================================================================
analyze_earnings_calls_full <- function(folder_path, results_10k, results_10q_annual) {
cat("\n", strrep("=", 70), "\n")
cat("ZAŁĄCZNIK 4 – ANALIZA EARNINGS CALLS (+ presentation/Q&A)\n")
cat(strrep("=", 70), "\n")
files <- list.files(folder_path, pattern = "\\.txt$", full.names = TRUE)
results <- list()
for (file in files) {
name <- basename(file)
name_clean <- str_replace(name, "\\.txt$", "")
parts <- str_split(name_clean, "_")[[1]]
company_raw <- parts[1]
company <- case_when(
toupper(company_raw) == "ALPHABET" ~ "GOOGL",
toupper(company_raw) == "AMAZON" ~ "AMZN",
toupper(company_raw) == "APPLE" ~ "AAPL",
toupper(company_raw) == "META" ~ "META",
toupper(company_raw) == "MICROSOFT" ~ "MSFT",
TRUE ~ NA_character_
)
if (is.na(company)) next
fiscal_year <- parts[2]
fiscal_quarter <- if (length(parts) > 2) parts[3] else NA
if (is.na(fiscal_quarter)) next
cal <- sync_calendar(fiscal_year, fiscal_quarter, company)
if (is.na(cal$year) || !cal$year %in% c("2022", "2023", "2024", "2025")) next
cat("Przetwarzam:", company, "FY", fiscal_year, fiscal_quarter, "→ CY", cal$year, cal$quarter, "-", name, "\n")
tekst <- paste(readLines(file, warn = FALSE), collapse = " ")
if (nchar(tekst) == 0) next
qa_start <- str_locate(tekst, "Questions & Answers:")[1, "start"]
if (!is.na(qa_start)) {
presentation <- str_sub(tekst, 1, qa_start - 1)
qa <- str_sub(tekst, qa_start, nchar(tekst))
} else {
presentation <- tekst
qa <- ""
}
result_caly <- analyze_qualitative(tekst, company, cal$year, "Earnings Call")
result_caly$quarter <- cal$quarter
result_caly$part <- "caly"
result_caly$total_words <- result_caly$words
result_prez <- analyze_qualitative(presentation, company, cal$year, "Earnings Call")
result_prez$quarter <- cal$quarter
result_prez$part <- "presentation"
result_qa <- analyze_qualitative(qa, company, cal$year, "Earnings Call")
result_qa$quarter <- cal$quarter
result_qa$part <- "qa"
results[[length(results) + 1]] <- result_caly
results[[length(results) + 1]] <- result_prez
results[[length(results) + 1]] <- result_qa
cat(" → AI całość:", result_caly$total_ai, "| gęstość:", result_caly$density,
"| Future:", result_caly$pct_future, "% | Risk:", result_caly$pct_risk, "%\n")
}
if (length(results) == 0) return(NULL)
df <- bind_rows(results)
cat("\n--- TABELA 13: Gęstość Earnings Calls (średnia roczna) ---\n")
table_13 <- df %>%
filter(part == "caly") %>%
group_by(company, year) %>%
summarise(
total_ai = sum(AI_Total),
total_words = sum(total_words),
srednia_gestosc = round((total_ai / total_words) * 1000, 2),
.groups = "drop"
) %>%
pivot_wider(
id_cols = company,
names_from = year,
values_from = srednia_gestosc,
values_fill = 0
)
print(table_13)
cat("\n--- TABELA 13.1: Średnia GAMAM (Earnings Calls) ---\n")
table_14 <- df %>%
filter(part == "caly") %>%
group_by(year) %>%
summarise(
total_ai = sum(AI_Total),
total_words = sum(total_words),
srednia_gestosc_EC = round((total_ai / total_words) * 1000, 2),
.groups = "drop"
)
print(table_14)
cat("\n--- TABELA 13.2: Podział earnings calls na presentation i Q&A ---\n")
table_15_raw <- df %>%
filter(part != "caly") %>%
group_by(year, part) %>%
summarise(
total_words = sum(total_words, na.rm = TRUE),
total_ai = sum(AI_Total, na.rm = TRUE),
gestosc = round((total_ai / total_words) * 1000, 2),
.groups = "drop"
)
udzial_prez <- table_15_raw %>%
group_by(year) %>%
summarise(
udzial_prezentacji = round(
total_words[part == "presentation"] /
(total_words[part == "presentation"] + total_words[part == "qa"]) * 100,
1
),
.groups = "drop"
)
table_15_wide <- table_15_raw %>%
select(year, part, gestosc) %>%
pivot_wider(
id_cols = year,
names_from = part,
values_from = gestosc,
values_fill = 0
)
table_15 <- table_15_wide %>%
left_join(udzial_prez, by = "year") %>%
select(year, presentation, qa, udzial_prezentacji)
print(table_15)
cat("\n--- TABELA 13.3 PREZENTACJA vs Q&A DLA KAŻDEJ SPÓŁKI W 2025 ROKU ---\n")
table_15_by_company <- df %>%
filter(year == "2025", part != "caly") %>%
group_by(company, part) %>%
summarise(
total_ai = sum(AI_Total),
total_words = sum(total_words),
gestosc = round((total_ai / total_words) * 1000, 2),
.groups = "drop"
) %>%
pivot_wider(
id_cols = company,
names_from = part,
values_from = gestosc,
values_fill = 0
)
print(table_15_by_company)
# === KORELACJA SPEARMANA PRESENTATION vs Q&A ===
cat("\n--- KORELACJA SPEARMANA: PRESENTATION vs Q&A ---\n")
df_wide_qa <- df %>%
filter(part %in% c("presentation", "qa")) %>%
select(company, year, quarter, part, density) %>%
pivot_wider(names_from = part, values_from = density)
valid_rows <- df_wide_qa %>% filter(!is.na(presentation) & !is.na(qa))
if (nrow(valid_rows) >= 3) {
cor_test_qa <- cor.test(valid_rows$presentation, valid_rows$qa, method = "spearman", exact = FALSE)
cat(paste("Współczynnik korelacji (rho):", round(cor_test_qa$estimate, 3), "\n"))
cat(paste("p-value:", round(cor_test_qa$p.value, 4), "\n"))
if (cor_test_qa$p.value < 0.05) {
cat("✅ Istnieje statystycznie istotny związek między gęstością AI w Prezentacji a w Q&A.\n")
} else {
cat("❌ Brak statystycznie istotnego związku między Prezentacją a Q&A.\n")
}
} else {
cat("⚠️ Zbyt mało kompletnych par (Prezentacja + Q&A) do obliczenia korelacji.\n")
}
# === PORÓWNANIE EC VS 10-K ===
gest_10k <- results_10k %>%
filter(year %in% c("2022", "2023", "2024", "2025")) %>%
group_by(year) %>%
summarise(gest_10K = round(mean(density), 2), .groups = "drop")
comparison <- table_14 %>%
rename(rok = year) %>%
left_join(gest_10k, by = c("rok" = "year")) %>%
mutate(iloraz = round(srednia_gestosc_EC / gest_10K, 1))
cat("\n--- Tabela 14: PORÓWNANIE EARNINGS CALLS VS 10-K ---\n")
print(comparison)
# === WERYFIKACJA H2 ===
if (!is.null(results_10q_annual)) {
h2_ec <- mean(comparison$srednia_gestosc_EC, na.rm = TRUE)
h2_10k <- mean(comparison$gest_10K, na.rm = TRUE)
h2_10q <- mean(results_10q_annual$density, na.rm = TRUE)
cat("\n--- WERYFIKACJA HIPOTEZY H2 ---\n")
cat(paste("Średnia gęstość EC: ", round(h2_ec, 2), "| 10-K:", round(h2_10k, 2), "| 10-Q:", round(h2_10q, 2), "\n"))
if(h2_ec > h2_10k && h2_10k > h2_10q) {
cat("✅ Hipoteza H2 POTWIERDZONA: Earnings Calls > 10-K\n")
} else {
cat("❌ Hipoteza H2 NIE POTWIERDZONA\n")
}
}
return(list(raw = df, annual = table_13, gamam = table_14, split = table_15))
}
# =====================================================================
# 7. KORELACJE Z R&D I CAPEX
# =====================================================================
analyze_rd_capex_full <- function(results_10k, results_ec = NULL) {
cat("\n", strrep("=", 70), "\n")
cat("ZAŁĄCZNIK 5 – KORELACJE Z R&D I CAPEX (H3)\n")
cat(strrep("=", 70), "\n")
df_rd_capex <- data.frame(
spolka = c(rep("Alphabet",4), rep("Amazon",4), rep("Apple",4), rep("Meta",4), rep("Microsoft",4)),
rok = rep(2022:2025, 5),
rd = c(13.97,14.78,14.09,15.16, 14.24,14.90,13.83,15.14,
6.66,7.80,8.02,8.30, 30.30,28.53,26.67,28.55, 12.36,12.83,12.04,11.53),
capex = c(11.13,10.49,15.01,22.70, 12.38,9.17,12.96,18.39,
2.72,2.86,2.42,3.06, 26.95,20.05,22.65,34.68, 12.05,13.26,18.14,22.91)
)
df_10k_mapped <- results_10k %>%
mutate(spolka = case_when(
company == "GOOGL" ~ "Alphabet",
company == "AMZN" ~ "Amazon",
company == "AAPL" ~ "Apple",
company == "META" ~ "Meta",
company == "MSFT" ~ "Microsoft"
), rok = as.numeric(year))
df <- df_10k_mapped %>%
left_join(df_rd_capex, by = c("spolka", "rok")) %>%
mutate(
log_ai = log(density + 0.01),
log_rd = log(rd + 0.01),
log_capex = log(capex + 0.01)
)
cat("\n--- TABELA 16.1: KORELACJE SPEARMANA (globalne) ---\n")
cor_test_rd <- cor.test(df$rd, df$density, method = "spearman", exact = FALSE)
cor_test_capex <- cor.test(df$capex, df$density, method = "spearman", exact = FALSE)
cat(paste("R&D vs AI density: ρ =", round(cor_test_rd$estimate, 2),
"p-value =", round(cor_test_rd$p.value, 4), "\n"))
cat(paste("CAPEX vs AI density: ρ =", round(cor_test_capex$estimate, 2),
"p-value =", round(cor_test_capex$p.value, 4), "\n"))
cat("\n--- TABELA 16.2: KORELACJE WEWNĄTRZ SPÓŁEK ---\n")
for(comp in unique(df$spolka)) {
dane_comp <- df[df$spolka == comp, ]
if (nrow(dane_comp) >= 3) {
cor_rd_comp <- cor(dane_comp$rd, dane_comp$density, method = "spearman", use = "complete.obs")
cor_capex_comp <- cor(dane_comp$capex, dane_comp$density, method = "spearman", use = "complete.obs")
cat(paste(comp, ": R&D =", round(cor_rd_comp, 2), "| CAPEX =", round(cor_capex_comp, 2), "\n"))
}
}
cat("\n--- TABELA 17: REGRESJA PANELOWA 10-K (Fixed Effects + CR2) ---\n")
p_df <- pdata.frame(df, index = c("spolka", "rok"))
fe_capex <- plm(density ~ capex, data = p_df, model = "within")
fe_rd <- plm(density ~ rd, data = p_df, model = "within")
fe_full <- plm(density ~ capex + rd, data = p_df, model = "within")
cat("\nModel CAPEX (surowy):\n")
print(clubSandwich::coef_test(fe_capex, vcov = "CR2", cluster = "individual"))
cat("\nModel R&D (surowy):\n")
print(clubSandwich::coef_test(fe_rd, vcov = "CR2", cluster = "individual"))
cat("\nModel łączny CAPEX + R&D:\n")
print(clubSandwich::coef_test(fe_full, vcov = "CR2", cluster = "individual"))
fe_log_capex <- plm(log_ai ~ log_capex, data = p_df, model = "within")
fe_log_rd <- plm(log_ai ~ log_rd, data = p_df, model = "within")
cat("\n--- MODEL CAPEX (log-log, CR2) ---\n")
print(clubSandwich::coef_test(fe_log_capex, vcov = "CR2", cluster = "individual"))
cat("\n--- MODEL R&D (log-log, CR2) ---\n")
print(clubSandwich::coef_test(fe_log_rd, vcov = "CR2", cluster = "individual"))
cat("\n--- MODEL CAPEX + EFEKTY CZASOWE (robustness check, CR2) ---\n")
tryCatch({
fe_capex_time <- plm(density ~ capex + factor(rok), data = p_df, model = "within")
print(clubSandwich::coef_test(fe_capex_time, vcov = "CR2", cluster = "individual"))
}, error = function(e) {
cat("⚠️ Algorytm CR2 nie mógł obliczyć macierzy dla modelu z efektami czasu.\n")
cat("Powód: Zbyt mała liczba klastrów (N=5) w stosunku do liczby estymowanych parametrów.\n")
})
# Test Hausmana (FE vs RE)
re_model <- plm(density ~ capex, data = p_df, model = "random")
hausman_test <- phtest(fe_capex, re_model)
cat("\n--- TEST HAUSMANA ---\n")
print(hausman_test)
cat("Uwaga: Zastosowano model FE niezależnie od wyniku testu Hausmana.\n")
cat("Uzasadnienie: próba nielosowa (celowy dobór Big Tech) wyklucza\n")
cat("założenie losowości efektów indywidualnych wymagane przez RE.\n")
# Test F (FE vs Pooled OLS)
pooled_model <- plm(density ~ capex, data = p_df, model = "pooling")
f_test <- pFtest(fe_capex, pooled_model)
cat("\n--- TEST F (FE vs POOLED OLS) ---\n")
print(f_test)
# ===== DIAGNOSTYKA MODELU PANELOWEGO =====
cat("\n", strrep("=", 70), "\n")
cat("DIAGNOSTYKA MODELU PANELOWEGO (10-K)\n")
cat(strrep("=", 70), "\n")
# VIF
if (requireNamespace("car", quietly = TRUE)) {
lm_full <- lm(density ~ capex + rd + factor(spolka) + factor(rok), data = df)
vif_vals <- car::vif(lm_full)
cat("\n--- VIF (współliniowość) ---\n")
print(vif_vals)
if(any(vif_vals > 5)) cat("⚠️ Uwaga: VIF > 5 – współliniowość\n") else cat("✅ Brak istotnej współliniowości\n")
}
# Test Breuscha-Pagana (heteroskedastyczność
bp_test <- lmtest::bptest(fe_full)
cat("\n--- Test Breuscha-Pagana (heteroskedastyczność) ---\n")
print(bp_test)
if(bp_test$p.value < 0.05) cat("✅ Heteroskedastyczność – uzasadnienie dla CR2\n")
# Test Wooldridge'a (autokorelacja w panelu)
if (requireNamespace("plm", quietly = TRUE)) {
w_test <- plm::pwartest(fe_full)
cat("\n--- Test Wooldridge'a (autokorelacja) ---\n")
print(w_test)
if(w_test$p.value < 0.05) cat("⚠️ Autokorelacja w panelu\n") else cat("✅ Brak autokorelacji\n")
}
# Analiza Earnings Calls ===
if (!is.null(results_ec) && !is.null(results_ec$raw)) {
df_ec_mapped <- results_ec$raw %>%
filter(part == "caly") %>%
mutate(spolka = case_when(
company == "GOOGL" ~ "Alphabet",
company == "AMZN" ~ "Amazon",
company == "AAPL" ~ "Apple",
company == "META" ~ "Meta",
company == "MSFT" ~ "Microsoft"
), rok = as.numeric(year)) %>%
group_by(spolka, rok) %>%
summarise(ec_density = mean(density, na.rm = TRUE), .groups = "drop")
# Optymalizacja przekształceń dla EC
df_ec_merged <- df_ec_mapped %>%
inner_join(df_rd_capex, by = c("spolka", "rok")) %>%
mutate(
log_ec = log(ec_density + 0.01),
log_capex = log(capex + 0.01),
log_rd = log(rd + 0.01)
)
cat("\n--- TABELA 16.3: KORELACJE SPEARMANA DLA EARNINGS CALLS ---\n")
get_p <- function(d, col1, col2) {
d_sub <- d[!is.na(d[[col1]]) & !is.na(d[[col2]]), ]
if (nrow(d_sub) < 3) return(NA)
return(round(cor.test(d_sub[[col1]], d_sub[[col2]], method = "spearman", exact = FALSE)$p.value, 4))
}
tab18 <- data.frame(
Zakres = c("Globalna", unique(df_ec_merged$spolka)),
R_vs_EC_rho = sapply(c("Globalna", unique(df_ec_merged$spolka)), function(x) {
d <- if(x == "Globalna") df_ec_merged else df_ec_merged[df_ec_merged$spolka == x, ]
if(nrow(d[!is.na(d$rd) & !is.na(d$ec_density), ]) < 3) return(NA)
round(cor(d$rd, d$ec_density, method = "spearman", use = "complete.obs"), 2)
}),
R_vs_EC_p = sapply(c("Globalna", unique(df_ec_merged$spolka)), function(x) {
d <- if(x == "Globalna") df_ec_merged else df_ec_merged[df_ec_merged$spolka == x, ]
get_p(d, "rd", "ec_density")
}),
CAPEX_vs_EC_rho = sapply(c("Globalna", unique(df_ec_merged$spolka)), function(x) {
d <- if(x == "Globalna") df_ec_merged else df_ec_merged[df_ec_merged$spolka == x, ]
if(nrow(d[!is.na(d$capex) & !is.na(d$ec_density), ]) < 3) return(NA)
round(cor(d$capex, d$ec_density, method = "spearman", use = "complete.obs"), 2)
}),
CAPEX_vs_EC_p = sapply(c("Globalna", unique(df_ec_merged$spolka)), function(x) {
d <- if(x == "Globalna") df_ec_merged else df_ec_merged[df_ec_merged$spolka == x, ]
get_p(d, "capex", "ec_density")
})
)
print(tab18)
cat("\n--- TABELA 16.4: MODELE REGRESJI PANELOWEJ FE DLA EARNINGS CALLS (CR2) ---\n")
p_df_ec <- pdata.frame(df_ec_merged, index = c("spolka", "rok"))
fe_c_ec <- plm(ec_density ~ capex, data = p_df_ec, model = "within")
fe_f_ec <- plm(ec_density ~ capex + rd, data = p_df_ec, model = "within")
fe_rd_ec <- plm(ec_density ~ rd, data = p_df_ec, model = "within")
cat("\n--- MODEL R&D (EC) ---\n")
print(clubSandwich::coef_test(fe_rd_ec, vcov = "CR2", cluster = "individual"))
fe_log_capex_ec <- plm(log_ec ~ log_capex, data = p_df_ec, model = "within")
cat("\n--- MODEL LOG-LOG CAPEX (EC) ---\n")
print(clubSandwich::coef_test(fe_log_capex_ec, vcov = "CR2", cluster = "individual"))
fe_log_rd_ec <- plm(log_ec ~ log_rd, data = p_df_ec, model = "within")
cat("\n--- MODEL LOG-LOG R&D (EC) ---\n")
print(clubSandwich::coef_test(fe_log_rd_ec, vcov = "CR2", cluster = "individual"))
cat("\n--- MODEL CAPEX + CZAS (EC) ---\n")
tryCatch({
fe_capex_time_ec <- plm(ec_density ~ capex + factor(rok), data = p_df_ec, model = "within")
print(clubSandwich::coef_test(fe_capex_time_ec, vcov = "CR2", cluster = "individual"))
}, error = function(e) {
cat("⚠️ Ominięto CR2 dla modelu z czasem ze względu na brak stopni swobody.\n")
})
tab19 <- data.frame(
Model = c("CAPEX (EC)", "CAPEX + R&D (EC)"),
Wsp_CAPEX = c(round(coef(fe_c_ec)["capex"], 4), round(coef(fe_f_ec)["capex"], 4)),
P_val_CR2 = c(
round(clubSandwich::coef_test(fe_c_ec, vcov = "CR2", cluster = "individual")["capex", "p_Satt"], 4),
round(clubSandwich::coef_test(fe_f_ec, vcov = "CR2", cluster = "individual")["capex", "p_Satt"], 4)
),
R2_Adj = c(round(summary(fe_c_ec)$r.squared[1], 3), round(summary(fe_f_ec)$r.squared[1], 3))
)
print(tab19)
}
res_cr2_capex <- clubSandwich::coef_test(fe_capex, vcov = "CR2", cluster = "individual")
p_val_capex <- res_cr2_capex["capex", "p_Satt"]
coef_capex <- coef(fe_capex)["capex"]
res_cr2_rd <- clubSandwich::coef_test(fe_rd, vcov = "CR2", cluster = "individual")
p_val_rd <- res_cr2_rd["rd", "p_Satt"]
coef_rd <- coef(fe_rd)["rd"]
cat("\n", strrep("=", 70), "\n")
cat("WERYFIKACJA WYNIKÓW DLA NAKŁADÓW NA INNOWACJE (estymator CR2)\n")
cat(strrep("=", 70), "\n")
cat("--- Wpływ CAPEX na gęstość AI ---\n")
if (p_val_capex < 0.05 && coef_capex > 0) {
cat(sprintf("✅ ISTOTNY POZYTYWNY wpływ (beta = %.4f | p-value = %.4f)\n", coef_capex, p_val_capex))
} else if (p_val_capex < 0.05 && coef_capex < 0) {
cat(sprintf("❌ ISTOTNY NEGATYWNY wpływ (beta = %.4f | p-value = %.4f)\n", coef_capex, p_val_capex))
} else {
cat(sprintf("❌ BRAK ISTOTNEGO WPŁYWU statystycznie (beta = %.4f | p-value = %.4f)\n", coef_capex, p_val_capex))
}
cat("\n--- Wpływ R&D na gęstość AI ---\n")
if (p_val_rd < 0.05 && coef_rd > 0) {
cat(sprintf("✅ ISTOTNY POZYTYWNY wpływ (beta = %.4f | p-value = %.4f)\n", coef_rd, p_val_rd))
} else if (p_val_rd < 0.05 && coef_rd < 0) {
cat(sprintf("❌ ISTOTNY NEGATYWNY wpływ (beta = %.4f | p-value = %.4f)\n", coef_rd, p_val_rd))
} else {
cat(sprintf("❌ BRAK ISTOTNEGO WPŁYWU statystycznie (beta = %.4f | p-value = %.4f)\n", coef_rd, p_val_rd))
}
cat("\n")
fe_capex <<- fe_capex
fe_rd <<- fe_rd
fe_full <<- fe_full
p_val_capex <<- p_val_capex
coef_capex <<- coef_capex
p_val_rd <<- p_val_rd
coef_rd <<- coef_rd
return(df)
}
# =====================================================================
# 8. ANALIZA JAKOŚCIOWA
# =====================================================================
qualitative_summary_full <- function(results_10k, results_ec) {
cat("\n", strrep("=", 70), "\n")
cat("ZAŁĄCZNIK 6 – ANALIZA JAKOŚCIOWA (Future/Risk, General/Specific)\n")
cat(strrep("=", 70), "\n")
all_results <- bind_rows(
results_10k,
results_ec$raw %>% filter(part == "caly")
)
cat("\n--- TABELA 22: ŚREDNIA DLA GRUPY GAMAM (ważona) ---\n")
summary_weighted <- all_results %>% group_by(doc_type) %>%
summarise(
Pct_General = round(sum(AI_General_Count, na.rm = TRUE) / sum(AI_Total, na.rm = TRUE) * 100, 1),
Pct_Specific = round(sum(AI_Specific_Count, na.rm = TRUE) / sum(AI_Total, na.rm = TRUE) * 100, 1),
Pct_Future = round(sum(Future_Count, na.rm = TRUE) / sum(AI_Sentences_Count, na.rm = TRUE) * 100, 1),
Pct_Risk = round(sum(Risk_Count, na.rm = TRUE) / sum(AI_Sentences_Count, na.rm = TRUE) * 100, 1)
)
print(summary_weighted)
cat("\n--- TABELA 22.1: DLA KAŻDEJ SPÓŁKI (ważona) ---\n")
by_company_weighted <- all_results %>% group_by(company, doc_type) %>%
summarise(
Pct_General = round(sum(AI_General_Count, na.rm = TRUE) / sum(AI_Total, na.rm = TRUE) * 100, 1),
Pct_Specific = round(sum(AI_Specific_Count, na.rm = TRUE) / sum(AI_Total, na.rm = TRUE) * 100, 1),
Pct_Future = round(sum(Future_Count, na.rm = TRUE) / sum(AI_Sentences_Count, na.rm = TRUE) * 100, 1),
Pct_Risk = round(sum(Risk_Count, na.rm = TRUE) / sum(AI_Sentences_Count, na.rm = TRUE) * 100, 1),
.groups = "drop"
) %>% arrange(company, doc_type)
print(by_company_weighted, n = Inf)
return(all_results)
}
# =====================================================================
# 9. EVENT STUDY
# =====================================================================
calculate_car <- function(event_date, firm, prices_wide, start_shift = -1, end_shift = 1) {
if (!firm %in% colnames(prices_wide)) return(NA)
idx_pub <- which(prices_wide$data >= event_date)
if (length(idx_pub) == 0) return(NA)
idx_pub <- min(idx_pub)
if (abs(prices_wide$data[idx_pub] - event_date) > 3) return(NA)
event_idx <- idx_pub + 1
if (event_idx < 2 || event_idx > nrow(prices_wide)) return(NA)
est_start <- max(1, idx_pub - 130)
est_end <- idx_pub - 11
if (est_end <= est_start || est_end > nrow(prices_wide)) return(NA)
est_data <- prices_wide[est_start:est_end, ]
firm_returns <- diff(log(est_data[[firm]]))
market_returns <- diff(log(est_data$SPX))
valid <- !is.na(firm_returns) & !is.na(market_returns)
if (sum(valid) < 10) return(NA)
model <- lm(firm_returns[valid] ~ market_returns[valid])
alpha <- coef(model)[1]
beta <- coef(model)[2]
ev_start_idx <- max(2, event_idx + start_shift)
ev_end_idx <- min(nrow(prices_wide), event_idx + end_shift)
if (ev_start_idx >= ev_end_idx) return(NA)
ev_data <- prices_wide[(ev_start_idx - 1):ev_end_idx, ]
ar <- c()
for (i in 2:nrow(ev_data)) {
firm_ret <- log(ev_data[[firm]][i] / ev_data[[firm]][i-1])
market_ret <- log(ev_data$SPX[i] / ev_data$SPX[i-1])
if (!is.na(firm_ret) && !is.na(market_ret)) {
ar <- c(ar, firm_ret - (alpha + beta * market_ret))
}
}
return(sum(ar, na.rm = TRUE))
}
calculate_car_t0 <- function(event_date, firm, prices_wide) {
if (!firm %in% colnames(prices_wide)) return(NA)
idx_pub <- which(prices_wide$data >= event_date)
if (length(idx_pub) == 0) return(NA)
idx_pub <- min(idx_pub)
if (abs(prices_wide$data[idx_pub] - event_date) > 3) return(NA)
event_idx <- idx_pub + 1
if (event_idx < 2 || event_idx > nrow(prices_wide)) return(NA)
est_start <- max(1, idx_pub - 130)
est_end <- idx_pub - 11
if (est_end <= est_start || est_end > nrow(prices_wide)) return(NA)
est_data <- prices_wide[est_start:est_end, ]
firm_returns <- diff(log(est_data[[firm]]))
market_returns <- diff(log(est_data$SPX))
valid <- !is.na(firm_returns) & !is.na(market_returns)
if (sum(valid) < 10) return(NA)
model <- lm(firm_returns[valid] ~ market_returns[valid])
alpha <- coef(model)[1]
beta <- coef(model)[2]
firm_ret <- log(prices_wide[[firm]][event_idx] / prices_wide[[firm]][event_idx - 1])
market_ret <- log(prices_wide$SPX[event_idx] / prices_wide$SPX[event_idx - 1])
if (!is.na(firm_ret) && !is.na(market_ret)) {
return(firm_ret - (alpha + beta * market_ret))
}
return(NA)
}
calculate_sar <- function(event_date, firm, prices_wide, start_shift = -1, end_shift = 1) {
if (!firm %in% colnames(prices_wide)) return(NA)
idx_pub <- which(prices_wide$data >= event_date)
if (length(idx_pub) == 0) return(NA)
idx_pub <- min(idx_pub)
if (abs(prices_wide$data[idx_pub] - event_date) > 3) return(NA)
event_idx <- idx_pub + 1
if (event_idx < 2 || event_idx > nrow(prices_wide)) return(NA)
est_start <- max(1, idx_pub - 130)
est_end <- idx_pub - 11
if (est_end <= est_start || est_end > nrow(prices_wide)) return(NA)
est_data <- prices_wide[est_start:est_end, ]
firm_returns <- diff(log(est_data[[firm]]))
market_returns <- diff(log(est_data$SPX))
valid <- !is.na(firm_returns) & !is.na(market_returns)
if (sum(valid) < 10) return(NA)
model <- lm(firm_returns[valid] ~ market_returns[valid])
alpha <- coef(model)[1]
beta <- coef(model)[2]
sigma_est <- summary(model)$sigma
T_est <- length(firm_returns[valid])
m_avg <- mean(market_returns[valid])
m_sum_sq <- sum((market_returns[valid] - m_avg)^2)
ev_start_idx <- max(2, event_idx + start_shift)
ev_end_idx <- min(nrow(prices_wide), event_idx + end_shift)
if (ev_start_idx >= ev_end_idx) return(NA)
ev_data <- prices_wide[(ev_start_idx - 1):ev_end_idx, ]
sar_vec <- c()
for (i in 2:nrow(ev_data)) {
firm_ret <- log(ev_data[[firm]][i] / ev_data[[firm]][i-1])
market_ret <- log(ev_data$SPX[i] / ev_data$SPX[i-1])
if (!is.na(firm_ret) && !is.na(market_ret)) {
ar_it <- firm_ret - (alpha + beta * market_ret)
C_it <- sqrt(1 + 1/T_est + ((market_ret - m_avg)^2 / m_sum_sq))
sar_it <- ar_it / (sigma_est * C_it)
sar_vec <- c(sar_vec, sar_it)
}
}
return(sum(sar_vec, na.rm = TRUE))
}
calculate_volume_change <- function(event_row, volumes_wide, ev_start = -1, ev_end = 1, shift = 1) {
event_date <- as.Date(event_row$event_date)
firm <- event_row$spolka
vol_col <- firm
if (!vol_col %in% colnames(volumes_wide)) return(NA)
idx_pub <- which(volumes_wide$data >= event_date)
if (length(idx_pub) == 0) return(NA)
idx_pub <- min(idx_pub)
if (abs(volumes_wide$data[idx_pub] - event_date) > 3) return(NA)
event_idx <- idx_pub + shift
if (event_idx < 1 || event_idx > nrow(volumes_wide)) return(NA)
base_start <- max(1, idx_pub - 30)
base_end <- idx_pub - 11
if (base_end <= base_start || base_end > nrow(volumes_wide)) return(NA)
base_vol <- mean(volumes_wide[[vol_col]][base_start:base_end], na.rm = TRUE)
if (base_vol == 0 || is.na(base_vol)) return(NA)
ev_start_idx <- max(1, event_idx + ev_start)
ev_end_idx <- min(nrow(volumes_wide), event_idx + ev_end)
if (ev_start_idx > ev_end_idx) return(NA)
ev_vol <- mean(volumes_wide[[vol_col]][ev_start_idx:ev_end_idx], na.rm = TRUE)
return((ev_vol - base_vol) / base_vol * 100)
}
load_price_data <- function(folder_prices) {
spolki <- c("AAPL", "MSFT", "GOOGL", "AMZN", "META", "SPX")
ceny <- list()
for (s in spolki) {
csv_file <- file.path(folder_prices, paste0(s, "_US.csv"))
if (file.exists(csv_file)) {
d <- read.csv(csv_file)
colnames(d) <- c("data", "open", "high", "low", "close", "volume")
d$data <- as.Date(d$data)
ceny[[s]] <- d[, c("data", "close", "volume")]
}
}
prices_wide <- ceny[["SPX"]] %>% select(data, close) %>% rename(SPX = close)
for (s in spolki[spolki != "SPX"]) {
if (!is.null(ceny[[s]])) {
prices_wide <- prices_wide %>% left_join(ceny[[s]] %>% select(data, close) %>% rename(!!s := close), by = "data")
}
}
volumes_wide <- data.frame(data = prices_wide$data)
for (s in spolki[spolki != "SPX"]) {
if (!is.null(ceny[[s]])) {
volumes_wide <- volumes_wide %>% left_join(ceny[[s]] %>% select(data, volume) %>% rename(!!s := volume), by = "data")
}
}
return(list(prices = prices_wide, volumes = volumes_wide))
}
# === Testy alternatywne dla Załącznika 7 ===
run_alternative_tests <- function(df_all) {
cat("\n", strrep("=", 70), "\n")
cat("ZAŁĄCZNIK 7.1 – ALTERNATYWNE TESTY STATYSTYCZNE DLA HIPOTEZY H4\n")
cat(strrep("=", 70), "\n")
# Sprawdź czy df_all istnieje
if (!exists("df_all")) {
cat("❌ Brak df_all - najpierw uruchom event study\n")
return(NULL)
}
# ===== 1. PRZYGOTOWANIE DANYCH =====
ec_data <- df_all %>% filter(typ == "Earnings Call",
year_calendar %in% c("2022","2023","2024","2025"),
!is.na(CAR_m1_1))
cat("\n=== LICZBA OBSERWACJI ===\n")
cat("EC:", nrow(ec_data), "\n")
cat("HIGH:", sum(ec_data$ai_intensity == "HIGH"), "\n")
cat("LOW:", sum(ec_data$ai_intensity == "LOW"), "\n\n")
# ===== 2. TEST PERMUTACYJNY (bez założeń) =====
cat("=== TEST PERMUTACYJNY ===\n")
obs_diff <- mean(ec_data$CAR_m1_1[ec_data$ai_intensity == "HIGH"]) -
mean(ec_data$CAR_m1_1[ec_data$ai_intensity == "LOW"])
set.seed(123)
n_perm <- 10000
perm_diffs <- replicate(n_perm, {
perm_intensity <- sample(ec_data$ai_intensity)
mean(ec_data$CAR_m1_1[perm_intensity == "HIGH"]) -
mean(ec_data$CAR_m1_1[perm_intensity == "LOW"])
})
p_perm <- mean(abs(perm_diffs) >= abs(obs_diff))
cat("Obserwowana różnica:", round(obs_diff, 6), "\n")
cat("p-value (permutacyjny):", p_perm, "\n")
if(p_perm < 0.05) cat("✅ Istotne\n") else cat("❌ Nieistotne\n\n")
# ===== 3. TEST BAYESA (Bayes Factor) =====
cat("=== Bayes Factor ===\n")
if (requireNamespace("BayesFactor", quietly = TRUE)) {
library(BayesFactor)
bf_result <- ttestBF(formula = CAR_m1_1 ~ ai_intensity, data = ec_data)
bf <- extractBF(bf_result)$bf
cat("Bayes Factor:", round(bf, 3), "\n")
if(bf > 3) {
cat("✅ Dowód za różnicą (istotne)\n")
} else if(bf < 1/3) {
cat("✅ Dowód za BRAKIEM różnicy\n")
} else {
cat("❌ Dowód niejednoznaczny\n")
}
cat("Interpretacja: BF > 3 = dowód za H1, BF < 1/3 = dowód za brakiem H1\n\n")
} else {
cat("⚠️ Pakiet BayesFactor nie jest zainstalowany\n")
cat("Pomijam ten test\n\n")
}
# ===== 4. REGRESJA KWANTYLOWA (odporna na outliery) =====
cat("=== REGRESJA KWANTYLOWA (mediana) ===\n")
if (requireNamespace("quantreg", quietly = TRUE)) {
library(quantreg)
# Przygotuj dane
qr_data <- ec_data
qr_data$ai_binary <- ifelse(qr_data$ai_intensity == "HIGH", 1, 0)
qr_data$year_num <- as.numeric(qr_data$year_calendar)
# Model z binarną zmienną
qr_model <- suppressWarnings(rq(CAR_m1_1 ~ ai_binary + year_num, data = qr_data, tau = 0.5))
qr_sum <- summary(qr_model, se = "boot", R = 1000)
# Sprawdź współczynnik dla ai_binary
if ("ai_binary" %in% rownames(qr_sum$coefficients)) {
qr_coef <- qr_sum$coefficients["ai_binary", 1]
qr_p <- qr_sum$coefficients["ai_binary", 4]
cat("Różnica median (HIGH vs LOW):", round(qr_coef, 6), "\n")
cat("p-value:", round(qr_p, 4), "\n")
if(qr_p < 0.05) cat("✅ Istotne\n") else cat("❌ Nieistotne\n\n")
} else {
cat("Brak współczynnika w modelu\n")
cat("Dostępne współczynniki:", paste(rownames(qr_sum$coefficients), collapse=", "), "\n\n")
}
} else {
cat("⚠️ Pakiet quantreg nie jest zainstalowany\n")
cat("Pomijam ten test\n\n")
}
# ===== 5. BOOTSTRAPOWY PRZEDZIAŁ UFNOŚCI =====
cat("=== BOOTSTRAPOWY PRZEDZIAŁ UFNOŚCI ===\n")
set.seed(123)
n_boot <- 5000
boot_diffs <- replicate(n_boot, {
boot_idx <- sample(1:nrow(ec_data), replace = TRUE)
boot_df <- ec_data[boot_idx, ]
mean(boot_df$CAR_m1_1[boot_df$ai_intensity == "HIGH"]) -
mean(boot_df$CAR_m1_1[boot_df$ai_intensity == "LOW"])
})
ci_boot <- quantile(boot_diffs, c(0.025, 0.975))
cat("95% przedział ufności (bootstrap): [", round(ci_boot[1], 6), ", ", round(ci_boot[2], 6), "]\n")
if(ci_boot[1] > 0 || ci_boot[2] < 0) {
cat("✅ Przedział nie zawiera 0 – istotne\n\n")
} else {
cat("❌ Przedział zawiera 0 – nieistotne\n\n")
}
# ===== 5. ANALIZA ZMIANY INTENSYWNOŚCI AI (delta_density) =====
cat("=== ANALIZA ZMIANY INTENSYWNOŚCI AI (delta_density) ===\n")
cat("Hipoteza: rynek reaguje na WZROST ujawnień AI, nie na ich poziom\n\n")
p_matched <- NA
t_test_matched_result <- NULL
# Przygotowanie danych – tylko Earnings Calls
delta_data <- df_all %>%
filter(typ == "Earnings Call",
year_calendar %in% c("2022", "2023", "2024", "2025"),
!is.na(CAR_m1_1), !is.na(density)) %>%
distinct(spolka, event_date, .keep_all = TRUE) %>%
arrange(spolka, event_date) %>%
group_by(spolka) %>%
mutate(
density_lag = dplyr::lag(density),
delta_density = density - density_lag
) %>%
ungroup() %>%
filter(!is.na(delta_density)) %>%
mutate(period_id = as.numeric(factor(event_date))) # unikalny ID okresu dla pdata.frame
cat("Obserwacji po usunięciu pierwszego okresu:", nrow(delta_data), "\n")
cat("Firm:", length(unique(delta_data$spolka)), "\n\n")
# --- Rozkład kierunku zmian (informacyjnie) ---
delta_data <- delta_data %>%
mutate(delta_direction = ifelse(delta_density > 0, "WZROST", "SPADEK"))
cat("--- Rozkład kierunku zmian ---\n")
print(table(delta_data$delta_direction, delta_data$year_calendar))
cat("\n")
# --- MODEL 1: FE + CR2, delta_density ciągła ---
cat("--- MODEL 1: CAR ~ delta_density (FE + CR2) ---\n")
p_delta <- pdata.frame(delta_data, index = c("spolka", "period_id"))
fe_delta_1 <- plm(CAR_m1_1 ~ delta_density,
data = p_delta,
model = "within")
cr2_delta_1 <- clubSandwich::coef_test(fe_delta_1, vcov = "CR2", cluster = "individual")
cat("Współczynnik delta_density:", round(cr2_delta_1["delta_density", "beta"], 6), "\n")
cat("p-value (Satterthwaite):", round(cr2_delta_1["delta_density", "p_Satt"], 4), "\n")
if (cr2_delta_1["delta_density", "p_Satt"] < 0.05) {
cat("✅ Istotne – rynek reaguje na zmianę intensywności AI\n\n")
} else {
cat("❌ Nieistotne\n\n")
}
# --- MODEL 2: FE + CR2, delta_density + eps_surprise ---
cat("--- MODEL 2: CAR ~ delta_density + eps_surprise (FE + CR2) ---\n")
fe_delta_2 <- plm(CAR_m1_1 ~ delta_density + eps_surprise,
data = p_delta,
model = "within")
cr2_delta_2 <- clubSandwich::coef_test(fe_delta_2, vcov = "CR2", cluster = "individual")
cat("Współczynnik delta_density:", round(cr2_delta_2["delta_density", "beta"], 6), "\n")
cat("p-value (Satterthwaite):", round(cr2_delta_2["delta_density", "p_Satt"], 4), "\n")
cat("Współczynnik eps_surprise:", round(cr2_delta_2["eps_surprise", "beta"], 6), "\n")
cat("p-value eps_surprise:", round(cr2_delta_2["eps_surprise", "p_Satt"], 4), "\n")
if (cr2_delta_2["delta_density", "p_Satt"] < 0.05) {
cat("✅ Istotne po kontroli EPS surprise\n\n")
} else {
cat("❌ Nieistotne po kontroli EPS surprise\n\n")
}
# --- Tabela podsumowująca modele ---
cat("--- Podsumowanie modeli FE (delta_density) ---\n")
summary_delta <- data.frame(
Model = c("M1: CAR ~ delta_density",
"M2: CAR ~ delta_density + EPS"),
Beta_delta = round(c(cr2_delta_1["delta_density", "beta"],
cr2_delta_2["delta_density", "beta"]), 6),
SE = round(c(cr2_delta_1["delta_density", "SE"],
cr2_delta_2["delta_density", "SE"]), 6),
p_Satt = round(c(cr2_delta_1["delta_density", "p_Satt"],
cr2_delta_2["delta_density", "p_Satt"]), 4),
Istotne = ifelse(c(cr2_delta_1["delta_density", "p_Satt"],
cr2_delta_2["delta_density", "p_Satt"]) < 0.05, "✅", "❌")
)
print(summary_delta)
# --- Średni CAR według kierunku zmiany i roku (opisowo) ---
cat("\n--- Średni CAR według kierunku zmiany i roku ---\n")
delta_summary <- delta_data %>%
group_by(year_calendar, delta_direction) %>%
summarise(
mean_CAR = round(mean(CAR_m1_1, na.rm = TRUE), 5),
n = n(),
.groups = "drop"
) %>%
pivot_wider(names_from = delta_direction,
values_from = c(mean_CAR, n),
values_fill = list(mean_CAR = NA, n = 0))
print(delta_summary)
# Zapisz p-value do podsumowania
p_matched <- cr2_delta_2["delta_density", "p_Satt"]
# ===== PODSUMOWANIE =====
cat("\n", strrep("=", 70), "\n")
cat("PODSUMOWANIE ALTERNATYWNYCH TESTÓW\n")
cat(strrep("=", 70), "\n")
# Test permutacyjny
cat("Test permutacyjny: p =", round(p_perm, 4), if(p_perm < 0.05) " ✅" else " ❌", "\n")
# Bayes Factor
if (exists("bf")) {
cat("Bayes Factor: BF =", round(bf, 3),
if(bf > 3) " ✅ (za H1)" else if(bf < 1/3) " ✅ (za brakiem H1)" else " ❌ (niejednoznaczny)", "\n")
}
# Regresja kwantylowa
if (exists("qr_p")) {
cat("Regresja kwantylowa: p =", round(qr_p, 4), if(qr_p < 0.05) " ✅" else " ❌", "\n")
}
# Bootstrap
cat("Bootstrap CI: ", if(ci_boot[1] > 0 || ci_boot[2] < 0) "✅ (nie zawiera 0)" else "❌ (zawiera 0)", "\n")
#delta intensity
cat("Analiza delta_density:",
if (!is.na(p_matched)) {
paste0("p = ", round(p_matched, 4), if (p_matched < 0.05) " ✅" else " ❌")
} else "❌ brak wyników", "\n")
# Zwróć wyniki
return(list(
obs_diff = obs_diff,
p_perm = p_perm,
bf = if(exists("bf")) bf else NA,
qr_p = if(exists("qr_p")) qr_p else NA,
ci_boot = ci_boot
))
}
analyze_event_study <- function(folder_7, ai_terms_sorted) {
cat("\n", strrep("=", 70), "\n")
cat("ZAŁĄCZNIK 7 – EVENT STUDY (CAR, BMP, wolumen, H4, T+0, bez 2022)\n")
cat("UWAGA: Czytanie plików bezpośrednio z folderu:", folder_7, "\n")
cat(strrep("=", 70), "\n")
pliki <- list.files(folder_7, pattern = "\\.pdf$|\\.txt$", full.names = TRUE, recursive = FALSE)
cat("Znaleziono plików:", length(pliki), "\n")
wyniki <- list()
# LICZNIK POSTĘPU
total_files <- length(pliki)
processed_files <- 0
for (plik in pliki) {
processed_files <- processed_files + 1
nazwa <- basename(plik)
# 1. Ekstrakcja danych (Regex)
if (grepl("10-K", nazwa, ignore.case = TRUE)) { typ <- "10-K"
} else if (grepl("10-Q", nazwa, ignore.case = TRUE)) { typ <- "10-Q"
} else if (grepl("earnings", nazwa, ignore.case = TRUE) || grepl("Earnings", nazwa)) { typ <- "Earnings Call"
} else { next }
if (grepl("Alphabet|GOOGL", nazwa, ignore.case = TRUE)) { spolka <- "GOOGL"
} else if (grepl("Amazon|AMZN", nazwa, ignore.case = TRUE)) { spolka <- "AMZN"
} else if (grepl("Apple|AAPL", nazwa, ignore.case = TRUE)) { spolka <- "AAPL"
} else if (grepl("Meta|META|Facebook", nazwa, ignore.case = TRUE)) { spolka <- "META"
} else if (grepl("Microsoft|MSFT", nazwa, ignore.case = TRUE)) { spolka <- "MSFT"
} else { next }
rok <- str_extract(nazwa, "202[0-6]")
if (is.na(rok)) next
kwartal <- str_extract(nazwa, "Q[1-4]")
if (is.na(kwartal)) {
kwartal <- str_extract(nazwa, "(?<=10-Q)[1-4]")
if (!is.na(kwartal)) kwartal <- paste0("Q", kwartal)
}
if (is.na(kwartal)) kwartal <- "unknown"
# 2. Wczytywanie tekstu (PDF / TXT)
if (grepl("\\.pdf$", nazwa, ignore.case = TRUE)) {
text <- tryCatch({
pages <- pdftools::pdf_text(plik)
pages <- pages[nchar(pages) > 20]
text <- paste(pages, collapse = " ")
text <- gsub("([a-zA-Z])-\\s+([a-zA-Z])", "\\1\\2", text)
text <- gsub("([a-zA-Z])-\\n+([a-zA-Z])", "\\1\\2", text)
text <- gsub("[\r\n\t]", " ", text)
text <- gsub("\\s+", " ", text)
text <- iconv(text, from = "UTF-8", to = "ASCII", sub = " ")
clean_text(text)
}, error = function(e) { "" })
} else {
text <- tryCatch({
text <- paste(readLines(plik, warn = FALSE), collapse = " ")
clean_text(text)
}, error = function(e) { "" })
}
if (nchar(text) < 50) next
# 3. Obliczenia
mentions <- count_terms(text, ai_terms_sorted)
words <- count_words(text)
density <- ifelse(words > 0, round((mentions / words) * 1000, 2), 0)
# 4. WYŚWIETLANIE POSTĘPU (Teraz zmienne 'typ', 'rok' i 'density' już istnieją!)
cat(sprintf("\r[%d/%d] %s | %s %s %s | AI: %d (%.2f)",
processed_files, total_files, spolka, typ, rok, kwartal, mentions, density), flush = TRUE)
flush.console()
wyniki[[length(wyniki) + 1]] <- data.frame(
plik = nazwa, spolka = spolka, typ = typ,
rok = rok, kwartal = kwartal, density = density,
stringsAsFactors = FALSE
)
}
cat("\n")
df_documents <- bind_rows(wyniki)
cat("\n=== Wczytano dokumentów:", nrow(df_documents), "===\n")
df_documents <- df_documents %>%
mutate(
kwartal = ifelse(typ == "10-K", "Q4", kwartal),
kwartal = ifelse(kwartal == "unknown", NA, kwartal),
rok = as.character(rok)
) %>%
filter(!is.na(kwartal))
excel_file <- file.path(folder_7, "mag_tabele_i_wykresy.xlsx")
if (!file.exists(excel_file)) {
cat("⚠️ Brak pliku Excel z datami zdarzeń – pomijam event study\n")
return(NULL)
}
events <- read_excel(excel_file) %>%
mutate(event_date = as.Date(event_date, format = "%d.%m.%Y"),
firm_symbol = str_remove(firm_symbol, "\\.US$"),
group = case_when(
grepl("Earnings", group, ignore.case = TRUE) ~ "Earnings Call",
TRUE ~ group
),
year_fiscal = as.character(year),
quarter_fiscal = as.character(quarter),
eps_surprise = as.numeric(eps_surprise))
assign("df_documents", df_documents, envir = .GlobalEnv)
assign("events", events, envir = .GlobalEnv)
df_all <- df_documents %>%
inner_join(events, by = c("spolka" = "firm_symbol", "typ" = "group",
"rok" = "year_fiscal", "kwartal" = "quarter_fiscal")) %>%
mutate(year_calendar = as.character(year(ymd(event_date))))
cat("Połączono zdarzeń:", nrow(df_all), "\n")
if (nrow(df_all) == 0) return(NULL)
price_vol <- load_price_data(folder_7)
prices_wide <- price_vol$prices
volumes_wide <- price_vol$volumes
windows <- list(
list(name = "m1_1", start = -1, end = 1, label = "[-1,+1]"),
list(name = "m2_2", start = -2, end = 2, label = "[-2,+2]"),
list(name = "m3_3", start = -3, end = 3, label = "[-3,+3]"),
list(name = "m5_5", start = -5, end = 5, label = "[-5,+5]")
)
cat("\n", strrep("-", 70), "\n")
cat("OBLICZAM CAR DLA RÓŻNYCH OKIEN\n")
cat(strrep("-", 70), "\n")
total_events <- nrow(df_all)
bar_width <- 40 # Szerokość paska postępu
for (w in windows) {
col_name <- paste0("CAR_", w$name)
cat(sprintf("\n→ Okno %s (%d zdarzeń)\n", w$label, total_events), flush = TRUE)
# Inicjalizacja paska postępu
cat(" [", paste(rep(" ", bar_width), collapse = ""), "] 0%", sep = "", flush = TRUE)
df_all[[col_name]] <- sapply(1:nrow(df_all), function(i) {
if (i %% max(1, round(total_events/20)) == 0 || i == total_events) {
pct <- round(i/total_events * 100)
filled <- round(pct/100 * bar_width)
cat(sprintf("\r [%s%s] %3d%%",
paste(rep("=", filled), collapse = ""),
paste(rep(" ", bar_width - filled), collapse = ""),
pct), flush = TRUE)
flush.console()
}
calculate_car(df_all$event_date[i], df_all$spolka[i], prices_wide, w$start, w$end)
})
cat("\n", flush = TRUE)
completed <- sum(!is.na(df_all[[col_name]]))
cat(sprintf(" ✅ %d/%d obliczeń CAR\n", completed, total_events), flush = TRUE)
}
df_all$CAR <- df_all$CAR_m1_1
# === PODZIAŁ NA GRUPY HIGH/LOW ===
medians <- df_all %>% group_by(typ) %>% summarise(med = median(density, na.rm = TRUE))
df_all <- df_all %>% left_join(medians, by = "typ") %>%
mutate(ai_intensity = ifelse(density > med, "HIGH", "LOW")) %>%
select(-med)
cat("\n--- MEDIANY GĘSTOŚCI AI (podział HIGH/LOW) ---\n")
for(doc_type in c("10-K", "10-Q", "Earnings Call")) {
med_val <- medians %>% filter(typ == doc_type) %>% pull(med)
cat(paste0(doc_type, ": ", round(med_val, 4), "\n"))
}
cat("\n")
# === TABELA 23: CAAR (Średnie CAR) ===
cat("\n--- TABELA 23: CAAR (Średnie CAR) ---\n")
for(doc_type in c("10-K", "10-Q", "Earnings Call")) {
df_type <- df_all %>% filter(typ == doc_type)
if(nrow(df_type) == 0) next
cat(paste0("\n", doc_type, ":\n"))
for (w in windows) {
col_name <- paste0("CAR_", w$name)
mean_car <- mean(df_type[[col_name]], na.rm = TRUE)
sd_car <- sd(df_type[[col_name]], na.rm = TRUE)
n_car <- sum(!is.na(df_type[[col_name]]))
t_stat <- mean_car / (sd_car / sqrt(n_car))
p_value <- 2 * pt(-abs(t_stat), df = n_car - 1)
cat(paste(w$label, "- Średni CAR:", round(mean_car, 5),
"(t =", round(t_stat, 3), ", p =", round(p_value, 4), ")\n"))
}
}
# === TABELA 24: TEST H4 Porównanie CAR między HIGH a LOW ===
cat("\n--- TABELA 24: TEST HIPOTEZY H4 – Porównanie CAR między HIGH a LOW ---\n")
ev_summary <- list()
for(doc_type in c("10-K", "10-Q", "Earnings Call")) {
df_type <- df_all %>% filter(typ == doc_type)
if(nrow(df_type) == 0) next
for (w in windows) {
col_name <- paste0("CAR_", w$name)
df_clean <- df_type %>% filter(!is.na(.data[[col_name]]))
if (nrow(df_clean) >= 10 && length(unique(df_clean$ai_intensity)) == 2) {
df_clean$ai_intensity <- relevel(factor(df_clean$ai_intensity), ref = "LOW")
model <- lm(as.formula(paste(col_name, "~ ai_intensity + factor(year_calendar)")), data = df_clean)
wilcox_t <- wilcox.test(as.formula(paste(col_name, "~ ai_intensity")), data = df_clean)
if ("ai_intensityHIGH" %in% rownames(summary(model)$coefficients)) {
# ZMIANA: Zastosowanie estymatora CR2
res_cr2 <- clubSandwich::coef_test(model, vcov = "CR2", cluster = df_clean$spolka)
ev_summary[[length(ev_summary)+1]] <- data.frame(
Typ = doc_type, Okno = w$label,
Mean_HIGH = round(mean(df_clean[[col_name]][df_clean$ai_intensity == "HIGH"]), 5),
Mean_LOW = round(mean(df_clean[[col_name]][df_clean$ai_intensity == "LOW"]), 5),
SD_HIGH = round(sd(df_clean[[col_name]][df_clean$ai_intensity == "HIGH"]), 5),
SD_LOW = round(sd(df_clean[[col_name]][df_clean$ai_intensity == "LOW"]), 5),
Median_HIGH = round(median(df_clean[[col_name]][df_clean$ai_intensity == "HIGH"]), 5),
Median_LOW = round(median(df_clean[[col_name]][df_clean$ai_intensity == "LOW"]), 5),
T_stat = round(res_cr2["ai_intensityHIGH", "tstat"], 3),
P_val_T_test = round(res_cr2["ai_intensityHIGH", "p_Satt"], 4), # Pobiera p-value Satterthwaite'a
P_val_Wilcoxon = round(wilcox_t$p.value, 4),
N_HIGH = sum(df_clean$ai_intensity == "HIGH"),
N_LOW = sum(df_clean$ai_intensity == "LOW")
)
}
}
}
}
if(length(ev_summary) > 0) {
final_table <- bind_rows(ev_summary)
rownames(final_table) <- NULL
print(final_table)
}
cat("\n--- TABELA 26: TEST BMP ---\n")
for(doc_type in c("10-K", "10-Q", "Earnings Call")) {
df_type <- df_all %>% filter(typ == doc_type, !is.na(CAR_m1_1))
if(nrow(df_type) < 10) next
# ===== BMP dla całej próby (przed podziałem) =====
scars_all <- sapply(1:nrow(df_type), function(i) {
calculate_sar(df_type$event_date[i], df_type$spolka[i], prices_wide, -1, 1)
})
scars_all <- scars_all[!is.na(scars_all)]
n_all <- length(scars_all)
z_all <- mean(scars_all) / (sd(scars_all) / sqrt(n_all))
p_all <- 2 * pt(-abs(z_all), df = n_all - 1)
cat(paste0("\n--- BMP: ", doc_type, " (cała próba) ---\n"))
cat(paste("Mean_SCAR =", round(mean(scars_all), 4),
"| Z =", round(z_all, 3),
"| p =", round(p_all, 4),
"| n =", n_all, "\n"))
# ===== BMP dla grup HIGH/LOW =====
df_type$SCAR <- scars_all
df_type <- df_type[!is.na(df_type$SCAR), ]
if(nrow(df_type) > 0 && length(unique(df_type$ai_intensity)) == 2) {
bmp_results <- df_type %>% group_by(ai_intensity) %>%
summarise(
Mean_SCAR = round(mean(SCAR), 4),
SD_SCAR = round(sd(SCAR), 3),
n = n(),
BMP_Z = round(mean(SCAR) / (sd(SCAR) / sqrt(n())), 3),
p_value = round(2 * pt(-abs(mean(SCAR) / (sd(SCAR) / sqrt(n()))), df = n() - 1), 4),
.groups = "drop"
)
cat(paste0("\n--- BMP: ", doc_type, " (podział HIGH/LOW) ---\n"))
print(bmp_results)
}
}
cat("\n--- ANALIZA WOLUMENU ---\n")
for(doc_type in c("10-K", "10-Q", "Earnings Call")) {
df_type <- df_all %>% filter(typ == doc_type, !is.na(ai_intensity))
if(nrow(df_type) == 0) next
df_type$Volume_Change <- sapply(1:nrow(df_type), function(i) {
calculate_volume_change(df_type[i, ], volumes_wide, -1, 1, 1)
})
df_clean <- df_type %>% filter(abs(Volume_Change) <= 200, !is.na(Volume_Change))
if(nrow(df_clean) > 0 && length(unique(df_clean$ai_intensity)) == 2) {
vol_high <- mean(df_clean$Volume_Change[df_clean$ai_intensity == "HIGH"], na.rm = TRUE)
vol_low <- mean(df_clean$Volume_Change[df_clean$ai_intensity == "LOW"], na.rm = TRUE)
vol_test <- t.test(Volume_Change ~ ai_intensity, data = df_clean)
cat(paste0("\n--- WOLUMEN: ", doc_type, " ---\n"))
cat(paste("Średnia zmiana HIGH:", round(vol_high, 1), "% | LOW:", round(vol_low, 1), "%\n"))
cat(paste("p-value:", round(vol_test$p.value, 4)))
if(vol_test$p.value < 0.05) cat(" ✅ Istotna różnica\n") else cat(" ❌ Brak istotnej różnicy\n")
}
}
df_all$CAR_t0 <- sapply(1:nrow(df_all), function(i) {
calculate_car_t0(df_all$event_date[i], df_all$spolka[i], prices_wide)
})
cat("\n--- SPECYFIKACJA T+0 (dzień publikacji) dla 10-K ---\n")
k10_t0 <- df_all %>% filter(typ == "10-K", year_calendar %in% c("2022","2023","2024","2025"),
!is.na(CAR_t0), !is.na(ai_intensity))
k10_t0_clean <- k10_t0
if (nrow(k10_t0_clean) >= 10 && length(unique(k10_t0_clean$ai_intensity)) == 2) {
k10_t0_clean$ai_intensity <- relevel(factor(k10_t0_clean$ai_intensity), ref = "LOW")
model_k10_t0 <- lm(CAR_t0 ~ ai_intensity + factor(year_calendar), data = k10_t0_clean)
coef_high_k10 <- summary(model_k10_t0)$coefficients["ai_intensityHIGH", ]
wilcox_k10_t0 <- wilcox.test(CAR_t0 ~ ai_intensity, data = k10_t0_clean)
cat(paste("Różnica HIGH vs LOW:", round(coef_high_k10[1], 5), "\n"))
cat(paste("p-value (t):", round(coef_high_k10[4], 4), "\n"))
cat(paste("p-value (Mann-Whitney):", round(wilcox_k10_t0$p.value, 4), "\n"))
} else {
cat("Za mało obserwacji (n =", nrow(k10_t0_clean), ")\n")
}
cat("\n--- SPECYFIKACJA T+0 (dzień publikacji) dla Earnings Calls ---\n")
ec_t0 <- df_all %>% filter(typ == "Earnings Call", year_calendar %in% c("2022","2023","2024","2025"),
!is.na(CAR_t0), !is.na(ai_intensity))
ec_t0_clean <- ec_t0
if (nrow(ec_t0_clean) >= 10 && length(unique(ec_t0_clean$ai_intensity)) == 2) {
ec_t0_clean$ai_intensity <- relevel(factor(ec_t0_clean$ai_intensity), ref = "LOW")
model_t0 <- lm(CAR_t0 ~ ai_intensity + factor(year_calendar), data = ec_t0_clean)
coef_high_t0 <- summary(model_t0)$coefficients["ai_intensityHIGH", ]
wilcox_t0 <- wilcox.test(CAR_t0 ~ ai_intensity, data = ec_t0_clean)
cat(paste("Różnica HIGH vs LOW:", round(coef_high_t0[1], 5), "\n"))
cat(paste("p-value (t):", round(coef_high_t0[4], 4), "\n"))
cat(paste("p-value (Mann-Whitney):", round(wilcox_t0$p.value, 4), "\n"))
}
cat("\n--- SPECYFIKACJA T+0 (dzień publikacji) dla 10-Q ---\n")
k10q_t0 <- df_all %>% filter(typ == "10-Q", year_calendar %in% c("2022","2023","2024","2025"),
!is.na(CAR_t0), !is.na(ai_intensity))
k10q_t0_clean <- k10q_t0
if (nrow(k10q_t0_clean) >= 10 && length(unique(k10q_t0_clean$ai_intensity)) == 2) {
k10q_t0_clean$ai_intensity <- relevel(factor(k10q_t0_clean$ai_intensity), ref = "LOW")
model_k10q_t0 <- lm(CAR_t0 ~ ai_intensity + factor(year_calendar), data = k10q_t0_clean)
coef_high_k10q <- summary(model_k10q_t0)$coefficients["ai_intensityHIGH", ]
wilcox_k10q_t0 <- wilcox.test(CAR_t0 ~ ai_intensity, data = k10q_t0_clean)
cat(paste("Różnica HIGH vs LOW:", round(coef_high_k10q[1], 5), "\n"))
cat(paste("p-value (t):", round(coef_high_k10q[4], 4), "\n"))
cat(paste("p-value (Mann-Whitney):", round(wilcox_k10q_t0$p.value, 4), "\n"))
} else {
cat("Za mało obserwacji (n =", nrow(k10q_t0_clean), ")\n")
}
cat("\n--- 10-K BEZ ROKU 2022 ---\n")
k10_no2022 <- df_all %>% filter(typ == "10-K", year_calendar %in% c("2023","2024","2025"),
!is.na(CAR_m1_1), !is.na(ai_intensity))
if (nrow(k10_no2022) >= 10 && length(unique(k10_no2022$ai_intensity)) == 2) {
k10_no2022$ai_intensity <- relevel(factor(k10_no2022$ai_intensity), ref = "LOW")
model_k10_no2022 <- lm(CAR_m1_1 ~ ai_intensity + factor(year_calendar), data = k10_no2022)
coef_high_k10_no2022 <- summary(model_k10_no2022)$coefficients["ai_intensityHIGH", ]
wilcox_k10_no2022 <- wilcox.test(CAR_m1_1 ~ ai_intensity, data = k10_no2022)
cat(paste("Różnica HIGH vs LOW:", round(coef_high_k10_no2022[1], 5), "\n"))
cat(paste("p-value (t):", round(coef_high_k10_no2022[4], 4), "\n"))
cat(paste("p-value (Mann-Whitney):", round(wilcox_k10_no2022$p.value, 4), "\n"))
} else {
cat("Za mało obserwacji (n =", nrow(k10_no2022), ")\n")
}
cat("\n--- EARNINGS CALLS BEZ ROKU 2022 ---\n")
ec_no2022 <- df_all %>% filter(typ == "Earnings Call", year_calendar %in% c("2023","2024","2025"),
!is.na(CAR_m1_1), !is.na(ai_intensity))
if (nrow(ec_no2022) >= 10 && length(unique(ec_no2022$ai_intensity)) == 2) {
ec_no2022$ai_intensity <- relevel(factor(ec_no2022$ai_intensity), ref = "LOW")
model_no2022 <- lm(CAR_m1_1 ~ ai_intensity + factor(year_calendar), data = ec_no2022)
coef_high_no2022 <- summary(model_no2022)$coefficients["ai_intensityHIGH", ]
wilcox_no2022 <- wilcox.test(CAR_m1_1 ~ ai_intensity, data = ec_no2022)
cat(paste("Różnica HIGH vs LOW:", round(coef_high_no2022[1], 5), "\n"))
cat(paste("p-value (t):", round(coef_high_no2022[4], 4), "\n"))
cat(paste("p-value (Mann-Whitney):", round(wilcox_no2022$p.value, 4), "\n"))
}
cat("\n--- 10-Q BEZ ROKU 2022 ---\n")
k10q_no2022 <- df_all %>% filter(typ == "10-Q", year_calendar %in% c("2023","2024","2025"),
!is.na(CAR_m1_1), !is.na(ai_intensity))
if (nrow(k10q_no2022) >= 10 && length(unique(k10q_no2022$ai_intensity)) == 2) {
k10q_no2022$ai_intensity <- relevel(factor(k10q_no2022$ai_intensity), ref = "LOW")
model_k10q_no2022 <- lm(CAR_m1_1 ~ ai_intensity + factor(year_calendar), data = k10q_no2022)
coef_high_k10q_no2022 <- summary(model_k10q_no2022)$coefficients["ai_intensityHIGH", ]
wilcox_k10q_no2022 <- wilcox.test(CAR_m1_1 ~ ai_intensity, data = k10q_no2022)
cat(paste("Różnica HIGH vs LOW:", round(coef_high_k10q_no2022[1], 5), "\n"))
cat(paste("p-value (t):", round(coef_high_k10q_no2022[4], 4), "\n"))
cat(paste("p-value (Mann-Whitney):", round(wilcox_k10q_no2022$p.value, 4), "\n"))
} else {
cat("Za mało obserwacji (n =", nrow(k10q_no2022), ")\n")
}
# ============================================================
# PLACEBO TEST (walidacja metody)
# ============================================================
cat("\n", strrep("=", 70), "\n")
cat("PLACEBO TEST – LOSOWE PRZESUNIĘCIE DAT ZDARZEŃ\n")
cat(strrep("=", 70), "\n")
set.seed(123)
# Dla Earnings Calls (najwięcej obserwacji)
df_placebo <- df_all %>% filter(typ == "Earnings Call")
# Losowe przesunięcie dat o -60, -30, +30, +60 dni
shifts <- sample(c(-60, -30, 30, 60), nrow(df_placebo), replace = TRUE)
df_placebo$placebo_date <- df_placebo$event_date + shifts
# Oblicz CAR dla placebo
df_placebo$CAR_placebo <- sapply(1:nrow(df_placebo), function(i) {
calculate_car(df_placebo$placebo_date[i], df_placebo$spolka[i], prices_wide, -1, 1)
})
# Test t dla CAR placebo
mean_placebo <- mean(df_placebo$CAR_placebo, na.rm = TRUE)
sd_placebo <- sd(df_placebo$CAR_placebo, na.rm = TRUE)
n_placebo <- sum(!is.na(df_placebo$CAR_placebo))
t_placebo <- mean_placebo / (sd_placebo / sqrt(n_placebo))
p_placebo <- 2 * pt(-abs(t_placebo), df = n_placebo - 1)
cat("\n--- Placebo test (losowe przesunięcie dat o ±30-60 dni) ---\n")
cat(paste("Średni CAR placebo:", round(mean_placebo, 6), "\n"))
cat(paste("t-stat:", round(t_placebo, 3), "\n"))
cat(paste("p-value:", round(p_placebo, 4), "\n"))
if(p_placebo < 0.05) {
cat("⚠️ UWAGA: Placebo CAR jest istotne – metoda może być błędna!\n")
} else {
cat("✅ Placebo CAR nieistotne – metoda event study działa poprawnie.\n")
}
# Dodatkowo: powtórz 100 razy
cat("\n--- Placebo test – wielokrotny (100 powtórzeń) ---\n")
set.seed(123)
p_values_placebo <- replicate(100, {
shifts_rep <- sample(c(-60, -30, 30, 60), nrow(df_placebo), replace = TRUE)
placebo_date_rep <- df_placebo$event_date + shifts_rep
car_placebo_rep <- sapply(1:nrow(df_placebo), function(i) {
calculate_car(placebo_date_rep[i], df_placebo$spolka[i], prices_wide, -1, 1)
})
t_test_rep <- t.test(car_placebo_rep[!is.na(car_placebo_rep)])
t_test_rep$p.value
})
cat(paste("Średnia p-value z 100 placebo testów:", round(mean(p_values_placebo), 4), "\n"))
cat(paste("Odsetek istotnych (p < 0.05):", round(mean(p_values_placebo < 0.05) * 100, 1), "%\n"))
if(mean(p_values_placebo < 0.05) < 5) {
cat("✅ Mniej niż 5% placebo testów istotnych – metoda działa poprawnie.\n")
} else {
cat("⚠️ Ponad 5% placebo testów istotnych – potencjalny problem.\n")
}
# ============================================================
# ROZSZERZONE MODELE REGRESYJNE H4 (z kontrolami i FE)
# ============================================================
# Przygotowanie danych dla EC
dane_reg <- df_all %>%
filter(typ == "Earnings Call",
year_calendar %in% c("2022","2023","2024","2025"),
!is.na(CAR_m1_1)) %>%
mutate(
AI_Intensity = density,
AI_HIGH = ifelse(ai_intensity == "HIGH", 1, 0),
SUE = eps_surprise,
firm_id = as.factor(spolka),
year_id = as.factor(year_calendar)
)
# ===== DIAGNOSTYKA MODELU REGRESYJNEGO (EC) =====
cat("\n", strrep("=", 70), "\n")
cat("DIAGNOSTYKA MODELU REGRESYJNEGO (Earnings Calls)\n")
cat(strrep("=", 70), "\n")
# 1. Test normalności (Shapiro-Wilk) dla CAR
car_values <- dane_reg$CAR_m1_1[!is.na(dane_reg$CAR_m1_1)]
if(length(car_values) >= 3 && length(car_values) <= 5000) {
sw_test <- shapiro.test(car_values)
cat("\n--- Test Shapiro-Wilka (normalność CAR) ---\n")
print(sw_test)
if(sw_test$p.value < 0.05) cat("⚠️ Rozkład CAR nie jest normalny – uzasadnienie dla testu Manna-Whitneya\n")
}
# 2. Test Levene'a (równość wariancji między HIGH a LOW)
if (requireNamespace("car", quietly = TRUE)) {
lev_test <- suppressWarnings(car::leveneTest(CAR_m1_1 ~ ai_intensity, data = dane_reg))
cat("\n--- Test Levene'a (równość wariancji HIGH vs LOW) ---\n")
print(lev_test)
if(!is.na(lev_test$`Pr(>F)`[1]) && lev_test$`Pr(>F)`[1] < 0.05) {
cat("⚠️ Wariancje różne – test t może być nieodpowiedni\n")
} else {
cat("✅ Wariancje równe – test t odpowiedni\n")
}
}
# 3. VIF (współliniowość AI i SUE)
m2_vif <- lm(CAR_m1_1 ~ AI_Intensity + SUE, data = dane_reg)
if (requireNamespace("car", quietly = TRUE)) {
vif_vals <- car::vif(m2_vif)
cat("\n--- VIF (współliniowość AI i SUE) ---\n")
print(vif_vals)
if(any(vif_vals > 5)) cat("⚠️ Współliniowość między zmiennymi\n") else cat("✅ Brak istotnej współliniowości\n")
}
# 4. Test Breuscha-Pagana (heteroskedastyczność)
bp_test <- lmtest::bptest(m2_vif)
cat("\n--- Test Breuscha-Pagana (heteroskedastyczność) ---\n")
print(bp_test)
if(bp_test$p.value < 0.05) cat("✅ Heteroskedastyczność – uzasadnienie dla HC3")
cat("\n", strrep("=", 70), "\n")
cat("ROZSZERZONE MODELE REGRESYJNE H4 (z kontrolami i FE)\n")
cat(strrep("=", 70), "\n")
# ===== MODEL 1: samo AI =====
cat("\n--- MODEL 1: CAR ~ AI (HC3) ---\n")
m1_lin <- lm(CAR_m1_1 ~ AI_Intensity, data = dane_reg)
m1_bin <- lm(CAR_m1_1 ~ AI_HIGH, data = dane_reg)
# HC3 z sandwich + lmtest
cr2_m1_lin <- lmtest::coeftest(m1_lin, vcov = sandwich::vcovHC(m1_lin, type = "HC3"))
cr2_m1_bin <- lmtest::coeftest(m1_bin, vcov = sandwich::vcovHC(m1_bin, type = "HC3"))
cat("Zmienna ciągła (HC3):\n")
print(cr2_m1_lin["AI_Intensity", , drop=FALSE])
cat("Zmienna binarna (HIGH vs LOW) (HC3):\n")
print(cr2_m1_bin["AI_HIGH", , drop=FALSE])
# ===== MODEL 2: AI + SUE =====
cat("\n--- MODEL 2: CAR ~ AI + SUE (HC3) ---\n")
m2_lin <- lm(CAR_m1_1 ~ AI_Intensity + SUE, data = dane_reg)
m2_bin <- lm(CAR_m1_1 ~ AI_HIGH + SUE, data = dane_reg)
cr2_m2_lin <- lmtest::coeftest(m2_lin, vcov = sandwich::vcovHC(m2_lin, type = "HC3"))
cr2_m2_bin <- lmtest::coeftest(m2_bin, vcov = sandwich::vcovHC(m2_bin, type = "HC3"))
cat("Zmienna ciągła + SUE (HC3):\n")
print(cr2_m2_lin[c("AI_Intensity", "SUE"), ])
cat("Zmienna binarna + SUE (HC3):\n")
print(cr2_m2_bin[c("AI_HIGH", "SUE"), ])
# ===== MODEL 3: AI + SUE + FE (firma + rok) z CR2 =====
cat("\n--- MODEL 3: CAR ~ AI + SUE + FE(firma, rok) + CR2 ---\n")
m3_lin <- lm(CAR_m1_1 ~ AI_Intensity + SUE + firm_id + year_id, data = dane_reg)
m3_bin <- lm(CAR_m1_1 ~ AI_HIGH + SUE + firm_id + year_id, data = dane_reg)
if (requireNamespace("clubSandwich", quietly = TRUE)) {
# Obliczamy i przypisujemy CR2 do zmiennych dla modelu 3
cr2_m3_lin <- clubSandwich::coef_test(m3_lin, vcov = "CR2", cluster = dane_reg$firm_id)
cr2_m3_bin <- clubSandwich::coef_test(m3_bin, vcov = "CR2", cluster = dane_reg$firm_id)
cat("Zmienna ciągła + FE (CR2):\n")
df_cr2_lin <- as.data.frame(cr2_m3_lin)
print(df_cr2_lin[rownames(df_cr2_lin) %in% c("AI_Intensity", "SUE"), c("beta", "SE", "p_Satt")])
cat("Zmienna binarna + FE (CR2):\n")
df_cr2_bin <- as.data.frame(cr2_m3_bin)
print(df_cr2_bin[rownames(df_cr2_bin) %in% c("AI_HIGH", "SUE"), c("beta", "SE", "p_Satt")])
# ===== PODSUMOWANIE MODELI – WSPÓŁCZYNNIK DLA AI =====
cat("\n", strrep("=", 70), "\n")
cat("PODSUMOWANIE MODELI – WSPÓŁCZYNNIK DLA AI\n")
cat(strrep("=", 70), "\n")
# Funkcja pomocnicza do wyciągania wartości z coeftest
get_coef_hc3 <- function(obj, var_name) {
if (var_name %in% rownames(obj)) {
return(list(
beta = round(obj[var_name, "Estimate"], 5),
p = round(obj[var_name, "Pr(>|t|)"], 4)
))
} else {
return(list(beta = NA, p = NA))
}
}
# Dla clubSandwich (CR2)
get_coef_cr2 <- function(obj, var_name) {
if (var_name %in% rownames(obj)) {
return(list(
beta = round(obj[var_name, "beta"], 5),
p = round(obj[var_name, "p_Satt"], 4)
))
} else {
return(list(beta = NA, p = NA))
}
}
# Pobierz wartości
c1_lin <- get_coef_hc3(cr2_m1_lin, "AI_Intensity")
c1_bin <- get_coef_hc3(cr2_m1_bin, "AI_HIGH")
c2_lin <- get_coef_hc3(cr2_m2_lin, "AI_Intensity")
c2_bin <- get_coef_hc3(cr2_m2_bin, "AI_HIGH")
c3_lin <- get_coef_cr2(cr2_m3_lin, "AI_Intensity")
c3_bin <- get_coef_cr2(cr2_m3_bin, "AI_HIGH")
summary_h4 <- data.frame(
Model = c("M1: Samo AI (ciągłe)", "M1: Samo AI (binarne)",
"M2: + SUE (ciągłe)", "M2: + SUE (binarne)",
"M3: + FE (ciągłe, CR2)", "M3: + FE (binarne, CR2)"),
Wspolczynnik = round(c(c1_lin$beta, c1_bin$beta, c2_lin$beta, c2_bin$beta, c3_lin$beta, c3_bin$beta), 5),
P_value = round(c(c1_lin$p, c1_bin$p, c2_lin$p, c2_bin$p, c3_lin$p, c3_bin$p), 4)
)
summary_h4$Istotne <- ifelse(summary_h4$P_value < 0.05, "✅", "❌")
print(summary_h4)
if(any(summary_h4$P_value < 0.05, na.rm = TRUE)) {
cat("\n✅ β1 JEST ISTOTNE w co najmniej jednym modelu – rynek reaguje na AI\n")
} else {
cat("\n❌ β1 NIE JEST ISTOTNE w żadnym modelu – brak dowodu na reakcję rynku na AI\n")
}
# ============================================================
# TEST CORRADO
# ============================================================
cat("\n", strrep("=", 70), "\n")
cat("TEST CORRADO\n")
cat(strrep("=", 70), "\n")
corrado_test_proper <- function(event_dates, firms,
est_window = 120,
ev_start = -1, ev_end = 1) {
n <- length(event_dates)
Z_avg <- NA
p_avg <- NA
if (n < 5) return(list(day_results = NA, Z_sum = NA, p_sum = NA, n = n))
ev_days <- ev_start:ev_end
n_ev <- length(ev_days)
all_ar <- matrix(NA, nrow = n, ncol = est_window + n_ev)
colnames(all_ar) <- c(paste0("est_", 1:est_window), paste0("ev_", ev_days))
for (i in 1:n) {
event_date <- event_dates[i]
firm <- firms[i]
idx_pub <- which(prices_wide$data >= event_date)
if (length(idx_pub) == 0) next
idx_pub <- min(idx_pub)
if (abs(prices_wide$data[idx_pub] - event_date) > 3) next
event_idx <- idx_pub + 1
if (event_idx < 2 || event_idx > nrow(prices_wide)) next
est_start <- event_idx - est_window
est_end <- event_idx - 1
if (est_start < 2) next
est_returns <- data.frame(
firm = diff(log(prices_wide[[firm]][(est_start-1):est_end])),
market = diff(log(prices_wide$SPX[(est_start-1):est_end]))
)
est_returns <- est_returns[!is.na(est_returns$firm) & !is.na(est_returns$market), ]
if (nrow(est_returns) < 10) next
model <- lm(firm ~ market, data = est_returns)
alpha <- coef(model)[1]
beta <- coef(model)[2]
for (d in 1:est_window) {
day_idx <- est_start + d - 1
if (day_idx < 2 || day_idx > nrow(prices_wide)) next
firm_ret <- log(prices_wide[[firm]][day_idx] / prices_wide[[firm]][day_idx - 1])
market_ret <- log(prices_wide$SPX[day_idx] / prices_wide$SPX[day_idx - 1])
if (!is.na(firm_ret) && !is.na(market_ret)) {
all_ar[i, paste0("est_", d)] <- firm_ret - (alpha + beta * market_ret)
}
}
for (j in 1:n_ev) {
d <- ev_days[j]
day_idx <- event_idx + d
if (day_idx < 2 || day_idx > nrow(prices_wide)) next
firm_ret <- log(prices_wide[[firm]][day_idx] / prices_wide[[firm]][day_idx - 1])
market_ret <- log(prices_wide$SPX[day_idx] / prices_wide$SPX[day_idx - 1])
if (!is.na(firm_ret) && !is.na(market_ret)) {
all_ar[i, paste0("ev_", d)] <- firm_ret - (alpha + beta * market_ret)
}
}
}
results <- data.frame(Dzien = ev_days, Z = NA, p = NA, N = NA)
K_matrix <- matrix(NA, nrow = n, ncol = n_ev)
for (j in 1:n_ev) {
day_col <- paste0("ev_", ev_days[j])
valid_rows <- which(!is.na(all_ar[, day_col]))
if (length(valid_rows) < 5) next
K_vals <- numeric(length(valid_rows))
for (k in 1:length(valid_rows)) {
i <- valid_rows[k]
est_cols <- grep("^est_", colnames(all_ar), value = TRUE)
est_ars <- all_ar[i, est_cols]
est_ars <- est_ars[!is.na(est_ars)]
if (length(est_ars) < 10) {
K_vals[k] <- NA
next
}
ar_t <- all_ar[i, day_col]
all_ars <- c(est_ars, ar_t)
T_total <- length(all_ars)
rank_t <- rank(all_ars, na.last = "keep")[T_total]
K_vals[k] <- (rank_t - (T_total + 1) / 2) / sqrt(((T_total - 1) * (T_total + 1)) / 12)
K_matrix[i, j] <- K_vals[k]
}
K_vals <- K_vals[!is.na(K_vals)]
if (length(K_vals) >= 5) {
L_t <- mean(K_vals)
Z_t <- L_t * sqrt(length(K_vals))
p_t <- 2 * (1 - pnorm(abs(Z_t)))
results[j, "Z"] <- round(Z_t, 4)
results[j, "p"] <- round(p_t, 4)
results[j, "N"] <- length(K_vals)
}
}
cat("\n--- Wyniki dla poszczególnych dni ---\n")
print(results)
cat("\n--- Test łączny dla całego okna ---\n")
K_sum <- apply(K_matrix, 1, function(row) {
if (all(is.na(row))) return(NA)
row_clean <- row[!is.na(row)]
if (length(row_clean) == 0) return(NA)
return(mean(row_clean))
})
K_sum <- K_sum[!is.na(K_sum)]
if (length(K_sum) >= 5) {
L_avg <- mean(K_sum)
Z_avg <- L_avg * sqrt(length(K_sum))
p_avg <- 2 * (1 - pnorm(abs(Z_avg)))
cat(sprintf("Z = %.4f, p = %.4f, n = %d\n", Z_avg, p_avg, length(K_sum)))
if (p_avg < 0.05) cat("✅ Istotne\n") else cat("❌ Nieistotne\n")
} else {
cat("Za mało obserwacji do testu łącznego\n")
}
return(list(day_results = results, Z_sum = Z_avg, p_sum = p_avg))
}
for(doc_type in c("10-K", "10-Q", "Earnings Call")) {
cat(sprintf("\n=== %s ===\n", doc_type))
df_doc <- df_all %>%
filter(typ == doc_type,
year_calendar %in% c("2022", "2023", "2024", "2025"),
!is.na(event_date), !is.na(spolka))
if (nrow(df_doc) >= 10) {
corrado_test_proper(
event_dates = df_doc$event_date,
firms = df_doc$spolka,
est_window = 120,
ev_start = -1,
ev_end = 1
)
} else {
cat(sprintf("Za mało obserwacji: n = %d\n", nrow(df_doc)))
}
}
}
# ===== URUCHOMIENIE ALTERNATYWNYCH TESTÓW =====
alt_test_results <- run_alternative_tests(df_all)
assign("df_all", df_all, envir = .GlobalEnv)
summary_h4 <<- summary_h4
alt_test_results <<- alt_test_results
prices_wide <<- prices_wide
return(list(events_all = df_all, alt_tests = alt_test_results))
}
# =====================================================================
# 10. FUNKCJA GŁÓWNA
# =====================================================================
main <- function() {
cat("\n")
cat("████████████████████████████████████████████████████████████████████\n")
cat("██ MASTER ANALYSIS SCRIPT – WSZYSTKIE ZAŁĄCZNIKI ██\n")
cat("██ Analiza ujawnień AI w raportach 10-K, 10-Q, EC ██\n")
cat("████████████████████████████████████████████████████████████████████\n")
# ===== ZAŁĄCZNIK 2 =====
results_10k <- analyze_10k_full(folder_10k)
# ===== ZAŁĄCZNIK 2.1 =====
if (!is.null(results_10k)) {
narrative_results <- analyze_narrative_sections(folder_narrative, results_10k)
}
# ===== ZAŁĄCZNIK 3 =====
results_10q_obj <- analyze_10q_full(folder_10q)
if (!is.null(results_10q_obj)) {
results_10q_raw <- results_10q_obj$raw
results_10q_annual <- results_10q_obj$annual
} else {
results_10q_raw <- NULL
results_10q_annual <- NULL
}
# ===== ZAŁĄCZNIK 4 =====
results_ec <- analyze_earnings_calls_full(folder_ec, results_10k, results_10q_annual)
# ===== ZAŁĄCZNIK 5 (Zintegrowane z wynikami EC) =====
if (!is.null(results_10k)) {
rd_capex_results <- analyze_rd_capex_full(results_10k, results_ec)
}
# ===== ZAŁĄCZNIK 6 =====
if (!is.null(results_10k) && !is.null(results_ec)) {
qualitative_results <- qualitative_summary_full(results_10k, results_ec)
}
# ===== ZAŁĄCZNIK 7 =====
if (!is.null(results_10k) && !is.null(results_10q_raw) && !is.null(results_ec)) {
event_results <- analyze_event_study(folder_prices, ALL_AI_TERMS_SORTED)
}
# ===== PODSUMOWANIE KOŃCOWE =====
cat("\n", strrep("=", 70), "\n")
cat("PODSUMOWANIE HIPOTEZ\n")
cat(strrep("=", 70), "\n")
cat("H1: Sekcje narracyjne gęstsze niż finansowa ✅\n")
cat("H2: Earnings Calls > 10-K > 10-Q ✅\n")
cat("H3: CAPEX istotny, R&D nie ❌\n")
cat("H4: AI nie wpływa na CAR ❌\n")
cat(strrep("=", 70), "\n")
cat("\n", strrep("=", 70), "\n")
cat("WSZYSTKIE ANALIZY ZAKOŃCZONE POMYŚLNIE!\n")
cat(strrep("=", 70), "\n")
assign("results_10k", results_10k, envir = .GlobalEnv)
if (exists("results_10q_annual")) assign("results_10q_annual", results_10q_annual, envir = .GlobalEnv)
if (exists("results_10q_raw")) assign("results_10q_raw", results_10q_raw, envir = .GlobalEnv)
assign("results_ec", results_ec, envir = .GlobalEnv)
if (exists("narrative_results")) assign("narrative_results", narrative_results, envir = .GlobalEnv)
if (exists("rd_capex_results")) assign("rd_capex_results", rd_capex_results, envir = .GlobalEnv)
if (exists("qualitative_results")) assign("qualitative_results", qualitative_results, envir = .GlobalEnv)
if (exists("event_results")) assign("event_results", event_results, envir = .GlobalEnv)
# Zapisz wszystkie kluczowe obiekty do pliku
save(
results_10k,
results_10q_raw,
results_10q_annual,
results_ec,
narrative_results,
rd_capex_results,
qualitative_results,
event_results,
fe_capex, fe_rd, fe_full,
summary_h4, alt_test_results,
file = "wyniki_analizy.RData"
)
cat("\n✅ Zapisano wyniki do pliku: wyniki_analizy.RData\n")
}
# URUCHOMIENIE CAŁOŚCI
main()
Konsola serwera
Konsola gotowa.