R data.table слияние/полное внешнее соединение с na.fill/nomatch на основе формулы

Что мне нужно, так это выполнить полное внешнее соединение с каким-то умным na.fill/nomatch эффективным способом. Я уже сделал это с помощью цикла, но я хотел бы использовать матричную алгебру или операции data.table для ускорения процесса.

Данные ниже являются образцом информации об открытых ордерах на акции, полное внешнее соединение выполняется между наборами данных открытых ордеров на продажу и открытых ордеров на покупку. Набор данных — это запросы, B — заявки. Оба набора данных хранят атомарные порядки и их совокупные суммы. Задача состоит в том, чтобы сопоставить все ордера Ask с ордерами Bid по совокупному значению и наоборот. Заполните примерные данные:

price = c(11.25,11.26,11.35,12.5,14.2)
amount = c(1.2,0.4,2.75,6.5,15.2)
A <- data.table(ask_price = price, ask_amount = amount, ask_cum_amount = cumsum(amount), cum_value = cumsum(price*amount), ask_avg_price = cumsum(price*amount)/cumsum(amount))
price = c(11.18,11.1,10.55,10.25,9.7)
amount = c(0.15,0.6,10.2,3.5,12)
B <- data.table(bid_price = price, bid_amount = amount, bid_cum_amount = cumsum(amount), cum_value = cumsum(price*amount), bid_avg_price = cumsum(price*amount)/cumsum(amount))

обычное полное внешнее соединение и его результаты:

setkey(A, cum_value)
setkey(B, cum_value)
C <- merge(A,B,all=TRUE)
print(C)

Формула na.fill / nomatch псевдокод для каждой строки (аск или бид), где cum_value не соответствует (имейте в виду, что любое другое поле, кроме cum_value, связано с аском ИЛИ бидом):

avg_price["current NA"] <- cum_value["last non NA"]/cum_value["current NA"] * avg_price["last non NA"] + (1-cum_value["last non NA"]/cum_value["current NA"]) * price["next non NA"]
cum_amount["current NA"] <- cum_value["current NA"] / avg_price["current NA"]

Ожидаемые результаты:

D <- data.table(
  cum_value = c(1.677,8.337,13.5,18.004,49.2165,115.947,130.4665,151.822,268.222,346.3065),
  ask_price = c(NA,NA,11.25,11.26,11.35,NA,12.5,NA,NA,14.2),
  ask_amount = c(NA,NA,1.2,0.4,2.75,NA,6.5,NA,NA,15.2),
  ask_cum_amount = c(0.149066666666667,0.741066666666667,1.2,1.6,4.35,9.66496172396059,10.85,12.3126600707381,20.4097766460076,26.05),
  ask_avg_price = c(11.25,11.25,11.25,11.2525,11.31414,11.9966331281534,12.02456,12.3305605066459,13.1418390633132,13.29392),
  bid_price = c(11.18,11.1,NA,NA,NA,10.55,NA,10.25,9.7,NA),
  bid_amount = c(0.15,0.6,NA,NA,NA,10.2,NA,3.5,12,NA),
  bid_cum_amount = c(0.15,0.75,1.23858478466587,1.66517233847558,4.6230572556498,10.95,12.3652404387114,14.45,26.45,NA),
  bid_avg_price = c(11.18,11.116,10.8995364444444,10.8120940902022,10.6458772362927,10.58877,10.5510685899445,10.50671,10.14072,NA)
)
print(D)

Обратите внимание, что в ожидаемых результатах последний NA по-прежнему является NA, потому что противоположный ордер не может быть сопоставлен, потому что глубины рынка недостаточно для выполнения ордера по любой цене.

Можно ли получить ожидаемые результаты, используя матричную алгебру или операции data.table или любой другой эффективный способ избежать зацикливания на полном наборе данных?

заранее спасибо


person jangorecki    schedule 19.08.2013    source источник
comment
В вашей формуле используются avg_price и price, ни один из которых не присутствует ни в одном из ваших data.table. Не могли бы вы уточнить?   -  person Arun    schedule 19.08.2013
comment
@Arun, формула для расчета ask_avg_price использует ask_, формула для расчета bid_avg_price использует bid_, только поле cum_value является общим для обоих наборов и не должно начинаться с префикса ask/bid в формуле.   -  person jangorecki    schedule 19.08.2013


Ответы (1)


Снова объедините его с A и B с roll, чтобы найти последнюю/следующую цену, не относящуюся к Северной Америке.

Например. посмотрите выходные значения bid_avg_price для этих двух слияний:

B[merge(A, B, all = T), roll = Inf]
B[merge(A, B, all = T), roll = -Inf]

Это должно дать вам всю информацию, необходимую для вычисления этих величин.

person eddi    schedule 19.08.2013
comment
Спасибо, используя ваше предложение, я смог: 1. объединить A и B с уникальным (c (A_key, B_key)), 2. выполнить самосоединение для A и B, чтобы получить предыдущий не-NA и следующий не-NA, 3. объединить уже заполненные NA A и B и получить ожидаемые результаты. Процессорное время выдающееся. Код занимает 15 строк и выглядит недостаточно читаемым. Я думаю, что его еще можно улучшить. После нескольких недель перерыва читать будет тяжело. В любом случае спасибо, новые навыки приобрел! - person jangorecki; 20.08.2013
comment
@MusX Я бы понял эту операцию, если бы книга ордеров пересекалась (как на аукционе), и вы находили цену, которая максимизировала объем исполнения (цена непересечения), например. Но в примере книга не перечеркнута: лучшая цена ‹ лучшая цена, как обычно в непрерывном сеансе. Я что-то пропустил? - person Matt Dowle; 20.08.2013
comment
@MatthewDowle, как и в примере, запросы/заявки из книги ордеров не пересекаются, если бы они пересекались, они были бы перечислены не в книге ордеров, а в прошлых транзакциях (заполненных ордерах). Суть операции состоит в том, чтобы сопоставить запросы с предложениями и предложения с запросами по суммарному значению. Результатом этой операции является avg_price(cum_value) в виде формулы (ask_avg_price(cum_value)+bid_avg_price(cum_value))/2, и эта avg_price показывает распределение открытых ордеров в своих кумулятивных значениях. Я буду рад услышать комментарий о моей логике, это своего рода сделай сам без каких-либо финансовых знаний. - person jangorecki; 20.08.2013
comment
@MusX Да, перекрестная книга (где предложение>аск) возможна и наблюдается каждый день ... на аукционе (внутридневной аукцион обычно по менее ликвидным акциям или аукцион закрытия для всех акций, в зависимости от рынка). Кажется, я понимаю, что вы хотите сделать, но я не понимаю, почему вы хотите это сделать. Цена закрытия аукциона (непересекающаяся цена) очень похожа на то, что вы описываете (но в перечеркнутой части книги на аукционе). Вы уверены, что не хотите этого делать? - person Matt Dowle; 20.08.2013
comment
@MatthewDowle, 1. я предполагаю, что перекрестная книга невозможна (я не могу наблюдать такой случай на рынке биткойнов - своего рода обмен валюты). 2. почему: я хотел бы использовать avg_price(cum_value) в качестве индикатора/фактора для сигналов покупки/продажи. Следующий график тесно связан с моей логикой: i.imgur.com/jnOenMx.png Ось X : цена, ось Y: совокупное значение, оранжевая линия: bid_avg_price, синяя линия: ask_avg_price, зеленая линия: прошлая транзакция - игнорировать это, На графике есть только ask_avg_price и bid_avg_price без avg_price обоих из них. - person jangorecki; 20.08.2013