اختباري العددي لفرضية الأسعار المطلقة

مرحبا يا هبر!

بدا هذا المنشور مثيراً للاهتمام بالنسبة لي: لقد حصلنا على أسعار صرف مطلقة من أسعار صرف العملات المتزاوجة وأردت اختبار القدرة على العثور على سعر صرف aaaabsolute هذا من خلال النمذجة الرقمية ، والتخلي عمومًا عن الجبر الخطي.



وكانت النتائج مثيرة للاهتمام.

ستكون التجربة صغيرة: 4 عملات ، 6 أزواج عملات. لكل زوج ، قياس مسار واحد.

لذلك دعونا نبدأ


الفرضية هي أنه يمكن التعبير عن قيمة أي عملة بقيمة معينة تأخذ في الاعتبار قيمة العملات الأخرى التي يتم نقلها بها ، بينما سيتم التعبير عن العملات الأخرى نفسها بقيمة جميع العملات الأخرى. هذه مهمة تكرارية مثيرة للاهتمام.

هناك 4 عملات:

  • USD
  • يورو
  • فرنك سويسري
  • GBP

بالنسبة لهم ، تم طلب أزواج العملات:

  • اليورو مقابل الدولار الأميركي
  • الجنيه الإسترليني مقابل الدولار
  • اليورو مقابل الفرنك السويسري
  • اليورو مقابل الجنيه الإسترليني
  • GBPCHF
  • الدولار مقابل الفرنك السويسري

يرجى ملاحظة أنه إذا كان عدد العملات هو n = 4 ، فإن عدد الأزواج هو k = (n ^ 2 - n) / 2 = 6. ليس من المنطقي البحث عن usdeur إذا تم اقتباس eurusd ...

في الوقت t ، تم قياس سعر الصرف لأحد مقدمي الخدمات:



سيتم تنفيذ الحسابات لهذه القيم.

الرياضيات


أتمكن من حل المشكلة عن طريق أخذ تدرج دالة الخسارة بشكل تحليلي ، وهو نظام المعادلات بشكل أساسي.

سيكون رمز التجربة باللغة R:

#set.seed(111) usd <- runif(1) eur <- runif(1) chf <- runif(1) gbp <- runif(1) # snapshot of values at time t eurusd <- 1.12012 gbpusd <- 1.30890 eurchf <- 1.14135 eurgbp <- 0.85570 gbpchf <- 1.33373 usdchf <- 1.01896 ## symbolic task ------------ express <- expression( (eurusd - eur / usd) ^ 2 + (gbpusd - gbp / usd) ^ 2 + (eurchf - eur / chf) ^ 2 + (eurgbp - eur / gbp) ^ 2 + (gbpchf - gbp / chf) ^ 2 + (usdchf - usd / chf) ^ 2 ) eval(express) x = 'usd' D(express, x) eval(D(express, x)) 

R يسمح باستخدام stats :: D لأخذ مشتق من دالة. على سبيل المثال ، إذا كنا نريد التمييز حسب عملة الدولار الأمريكي ، فسوف نحصل على التعبير:
2 * (eur / usd ^ 2 * (eurusd - eur / usd)) + 2 * (gbp / usd ^ 2 * (gbpusd -
gbp / usd)) - 2 * (1 / chf * (usdchf - usd / chf))
لتقليل قيمة الدالة Express ، سنؤدي إلى نزول التدرج ومن الواضح على الفور (نرى اختلافات مربعة) أن الحد الأدنى للقيمة سيكون صفرًا ، وهو ما نحتاجه.

 -deriv_vals * lr 

سيتم التحكم في خطوة نزول التدرج بواسطة المعلمة lr ويتم أخذ كل ذلك بعلامة سالبة.

وهذا يعني ، بكلمات بشرية ، تحديد أسعار 4 عملات بحيث تتلقى جميع أزواج العملات في التجربة قيمًا مساوية للقيم الأولية لهذه الأزواج. ط ط ط ، دعونا حل اللغز - في الجبهة!

النتائج


حتى لا تمدد ، سأخبرك فورًا بما يلي: التجربة ككل كانت ناجحة ، تم تنفيذ الشفرة ، اقترب الخطأ ، بالقرب من الصفر. ولكن بعد ذلك لاحظت أن النتائج مختلفة دائما.

سؤال للخبراء: يبدو أن هذه المهمة لها عدد غير محدود من الحلول ، لكن في هذا ، أنا صفرية كاملة ، أعتقد أنهم سيخبرونني في التعليقات.

للتحقق من استقرار (un) الحل ، قمت بمحاكاة 1000 مرة دون إصلاح بذرة PRNG لقيم البدء في قيم العملات.

وهنا تأتي الصورة من الكاتا: يصل الخطأ إلى 0.00001 وأقل (يتم ضبط التحسين بهذه الطريقة) دائمًا ، في حين أن قيم العملات تطفو الشيطان ، تعرف أين. اتضح أن هناك دائما قرار مختلف ، أيها السادة!

مرة أخرى ، هذه الصورة ، المحور ص في الوحدات الأصلية (وليس تسجيل الدخول):



حتى تتمكن من تكرار هذا ، أرفق أدناه الرمز الكامل.

قانون
 # clear environment rm(list = ls()); gc() ## load libs library(data.table) library(ggplot2) library(magrittr) ## set WD -------------------------------- # your dir here ... ## set vars ------------- currs <- c( 'usd', 'eur', 'chf', 'gbp' ) ############ ## RUN SIMULATION LOOP ------------------------------- simuls <- 1000L simul_dt <- data.table() for( s in seq_len(simuls) ) { #set.seed(111) usd <- runif(1) eur <- runif(1) chf <- runif(1) gbp <- runif(1) # snapshot of values at time t eurusd <- 1.12012 gbpusd <- 1.30890 eurchf <- 1.14135 eurgbp <- 0.85570 gbpchf <- 1.33373 usdchf <- 1.01896 ## symbolic task ------------ express <- expression( (eurusd - eur / usd) ^ 2 + (gbpusd - gbp / usd) ^ 2 + (eurchf - eur / chf) ^ 2 + (eurgbp - eur / gbp) ^ 2 + (gbpchf - gbp / chf) ^ 2 + (usdchf - usd / chf) ^ 2 ) ## define gradient and iterate to make descent to zero -------------- iter_max <- 1e+3 lr <- 1e-3 min_tolerance <- 0.00001 rm(grad_desc_func) grad_desc_func <- function( lr, curr_list ) { derivs <- character(length(curr_list)) deriv_vals <- numeric(length(curr_list)) grads <- numeric(length(curr_list)) # symbolic derivatives derivs <- sapply( curr_list, function(x){ D(express, x) } ) # derivative values deriv_vals <- sapply( derivs, function(x){ eval(x) } ) # gradient change values -deriv_vals * lr } ## get gradient values ---------- progress_list <- list() for( i in seq_len(iter_max) ) { grad_deltas <- grad_desc_func(lr, curr_list = currs) currency_vals <- sapply( currs , function(x) { # update currency values current_val <- get(x, envir = .GlobalEnv) new_delta <- grad_deltas[x] if(new_delta > -1 & new_delta < 1) { new_delta = new_delta } else { new_delta = sign(new_delta) } new_val <- current_val + new_delta if(new_val > 0 & new_val < 2) { new_val = new_val } else { new_val = current_val } names(new_val) <- NULL # change values of currencies by gradient descent step in global env assign(x, new_val , envir = .GlobalEnv) # save history of values for later plotting new_val } ) progress_list[[i]] <- c( currency_vals, eval(express) ) if( eval(express) < min_tolerance ) { break('solution was found') } } ## check results ---------- # print( # paste0( # 'Final error: ' # , round(eval(express), 5) # ) # ) # # print( # round(unlist(mget(currs)), 5) # ) progress_dt <- rbindlist( lapply( progress_list , function(x) { as.data.frame(t(x)) } ) ) colnames(progress_dt)[length(colnames(progress_dt))] <- 'error' progress_dt[, steps := 1:nrow(progress_dt)] progress_dt_melt <- melt( progress_dt , id.vars = 'steps' , measure.vars = colnames(progress_dt)[colnames(progress_dt) != 'steps'] ) progress_dt_melt[, simul := s] simul_dt <- rbind( simul_dt , progress_dt_melt ) } ggplot(data = simul_dt) + facet_wrap(~ variable, scales = 'free') + geom_line( aes( x = steps , y = value , group = simul , color = simul ) ) + scale_y_log10() + theme_minimal() 


يعمل رمز 1000 محاكاة لمدة دقيقة تقريبًا.

استنتاج


هنا ما زال غير واضح بالنسبة لي:

  • هل من الممكن تثبيت الحل بطريقة رياضية صعبة؟
  • ما إذا كان هناك تقارب مع المزيد من العملات وأزواج العملات ؛
  • إذا لم يكن هناك استقرار ، فبالنسبة لكل لقطة بيانات جديدة ، ستعمل عملاتنا كما يحلو لهم ، إذا لم تقم بإصلاح بذرة PRNG ، وهذا هو الفشل.

الفكرة كلها تبدو غامضة للغاية في غياب أي شروط وقيود واضحة. لكنها كانت مثيرة للاهتمام!

حسنًا ، أردت أيضًا أن أقول أنه يمكنك الاستغناء عن OLS عندما تكون البيانات صعبة ، أو أن المصفوفات مفردة ، أو جيدة ، أو عندما تكون النظرية غير معروفة (ehh ...).

شكرا eavprog على الرسالة الأولية.

وداعا!

Source: https://habr.com/ru/post/ar450874/


All Articles