ruby - 我应如何为CouchDB/Rails3应用程序生成交易统计信息?

标签 ruby statistics couchdb ruby-on-rails-3

我的问题是:我正试图为外汇交易员开发一个web应用程序这个应用程序允许交易者输入或上传他们的交易信息,我想根据用户输入的数据计算各种各样的统计数据。
现在,通常我会使用关系数据库来实现这一点,但是我有两个需求不适合关系数据库,所以我尝试使用couchdb。这两个问题是:1)首先,我有一个配套的桌面应用程序,用户可以使用couchdb令人敬畏的复制功能进行工作并复制到站点;2)我希望用户能够定义自己的自定义内容,以跟踪交易并根据输入的内容生成结果。沙发的无模式特性在这里看起来很完美,但最终可能比听起来更难。(我已经知道couch需要预先定义视图,所以我只是计划将所有自定义属性粘贴到一个数组中,然后在视图中发出数组并从中进行进一步处理。)
我所做的:现在我只是发送每个用户系统键入的沙发交易,并使用系统的密钥进行查询,以获得每个系统的交易数组很简单我目前没有使用reduce函数来计算任何统计数据,因为我不知道如何在不出现reduce溢出错误的情况下获得所需的所有数据。
下面是一个从沙发上发出的行的示例:

{"total_rows":134,"offset":0,"rows":[
{"id":"5b1dcd47221e160d8721feee4ccc64be",
"key":["80e40ba2fa43589d57ec3f1d19db41e6","2010/05/14 04:32:37 +0000"], null,
"doc":{
     "_id":"5b1dcd47221e160d8721feee4ccc64be",
     "_rev":"1-bc9fe763e2637694df47d6f5efb58e5b",
     "couchrest-type":"Trade",
     "system":"80e40ba2fa43589d57ec3f1d19db41e6",
     "pair":"EUR/USD",
     "direction":"Buy",
     "entry":12600,
     "exit":12700,
     "stop_loss":12500,
     "profit_target":12700,
     "status":"Closed",                  
     "slug":"101332132375",
     "custom_tracking": [{"name":"signal", "value":"Pin Bar"}]
     "updated_at":"2010/05/14 04:32:37 +0000",
     "created_at":"2010/05/14 04:32:37 +0000",
     "result":100}}
]}

在我的rails 3控制器中,我基本上只是填充一个交易数组,比如上面的一个,然后将相关数据提取到更小的数组中,我可以计算我的统计数据。
以下是我要显示统计信息和所有交易的页面的显示操作:
def show
  @trades = Trade.by_system(:startkey => [@system.id], :endkey => [@system.id, Time.now ])

  @trades.each do |trade|

  if trade.result > 0
    @winning_trades << trade.result
  elsif trade.result < 0
    @losing_trades << trade.result
  else
    @breakeven_trades << trade.result 
  end 

  if trade.direction == "Buy"
    @long_trades << trade.result
  else
    @short_trades << trade.result
  end

  if trade["custom_tracking"] != nil
      @custom_tracking << {"result" => trade.result, "variables" => trade["custom_tracking"]}  
  end 

end
end 

我省略了一些其他正在发生的事情,但这是我正在做的要点然后我计算视图层中的内容以产生一些结果:
<% winning_long_trades = @long_trades.reject {|trade| trade <= 0 } %>
<% winning_short_trades = @short_trades.reject {|trade| trade <= 0 } %>

<ul>
  <li>Total Trades: <%= @trades.count %></li>
  <li>Winners: <%= @winning_trades.size %></li>
  <li>Biggest Winner (Pips): <%= @winning_trades.max %></li>
  <li>Average Win(Pips): <%= @winning_trades.sum/@winning_trades.size %></li>
  <li>Losers: <%= @losing_trades.size %></li>
  <li>Biggest Loser (Pips): <%= @losing_trades.min %></li>
  <li>Average Loss(Pips): <%= @losing_trades.sum/@losing_trades.size %></li>
  <li>Breakeven Trades: <%= @breakeven_trades.size %></li>
  <li>Long Trades: <%= @long_trades.size %></li>
  <li>Winning Long Trades: <%= winning_long_trades.size %></li>
  <li>Short Trades: <%= @short_trades.size %></li>
  <li>Winning Short Trades: <%= winning_short_trades.size %></li>
  <li>Total Pips: <%= @winning_trades.sum + @losing_trades.sum %></li>
  <li>Win Rate (%): <%= @winning_trades.size/@trades.count.to_f * 100 %></li>
</ul>

这会产生以下结果,除了一些事情之外,这正是我想要的:
总交易量:134
获奖者:70人
最大赢家(PIP):1488
平均赢(点):440
失败者:58
最大输家(PIP):-516
平均损失(PIP):-225
盈亏平衡交易:6
长交易:125
赢得长交易:67
空头交易:9
赢得空头交易:3
总分:17819
中奖率(%):52.23880597014925
我想知道的是——最后是实际的问题:我开始怀疑当一个用户有5000笔交易而不是像这个例子中的134笔交易时,这个方法会有多好。我预计大多数用户每年的交易量只有200笔以下,但有些用户每年可能有几千笔交易每年大概不超过5000人现在看起来还可以,但是页面加载时间已经有点高了。(根据rails日志生成页面的时间大约为800ms,而在视图层的时间大约为250ms。)我确信,我最终会缓存此页面,但每次更新交易时,我仍然需要重新生成页面,我不能让这太慢。所以。。。。。
使用一个直接的couchdb reduce函数可以做类似的事情吗我想把这个交给couch可能有助于处理更大的数据集。我不知道怎么做,但我想这并不意味着这是不可能的。如果可能的话,任何提示都会有帮助。
如果由于reduce约束而导致reduce不可用,我可以使用list函数吗?couchdb list函数适合这种类型的计算吗?有人知道列表函数是否运行良好吗?有什么暗示,我想达到的计算类型是什么样的?
我考虑了其他的选择,比如在每次交易被保存的时候运行计算,或者如果必须的话每晚运行计算,并将结果保存到一个统计文档中,然后我可以查询,以便提前完成所有的处理。我希望这是最后的办法,因为这样我就不能像我希望的那样,按时间段动态地过滤掉交易(我想要一个滑动条,如果可以的话,用户可以使用couchdb中的startkey和endkey滑动该滑动条,只显示该时间段内的交易。)
如果我应该在页面视图时继续在rails应用程序中运行计算,我可以做些什么来改进当前的实现。我对rails、couch和编程都不熟悉。我相信我能在这里做得更好我需要为每个属性创建一个数组,还是有更好的方法来实现这个目的。
我想我只是想听听如何解决这个问题的建议。我想保持网页生成时间最少,因为我预计这些是一些最高流量的网页。我的直觉是,我需要将统计数据计算卸载到沙发上,或者在调用之前运行统计数据,但我不确定。
最后:就像我前面提到的,使用couch的一个主要原因是允许用户定义他们自己的东西来跟踪每笔交易。将数据放入couch中不是问题,但是我如何能够获取自定义的_跟踪数组并找到每个命名跟踪属性的获胜交易数。如果有人能给我任何暗示,说明这样做的可能性,那就太好了。
多谢非常感谢你的帮助如果有人想帮我解决这个问题,愿意掏点$$(不知道是否允许堆栈溢出。)

最佳答案

首先,如果你想提供所有交易(由用户)的统计数据,那么是的,reduce视图可能很棒。因为缩减后的结果实际上存储在视图索引中的磁盘上,所以这应该能够大大加快视图的速度。
其次,CouchDB中默认的reduce_限制只是限制如果你知道你在做什么,你应该禁用它,让reduce函数返回更多信息。(值得注意的是,我认为这就是您遇到的问题,默认的reduce_limit对返回的json结构有一个固定的大小限制;但是,如果返回的结构的大小在处理的行数中或多或少是恒定的,那么实际的大小并不是一个真正的问题——尽管它可能不会很大。)
我不认为使用list函数会有帮助,但是我没有太多的经验。
如果你愿意的话,我可能会帮你更多的钱,或者你可以去freenode上的couchdb问问问题。那里通常有很多知识渊博的人。

关于ruby - 我应如何为CouchDB/Rails3应用程序生成交易统计信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2842128/

相关文章:

couchdb - CouchDB 2 是否跨节点同步用户 session ?

ruby-on-rails - 如何向 Rails 应用程序发送 json 请求

ruby - Ruby 1.9 中更自然的 Proc 调用方式

ruby-on-rails - Ruby on Rails 中 protected 共享链接

ruby - 获取 Rails 项目中包含的所有 gem 的变更日志

erlang - CouchDB:Erlang中的map-reduce

statistics - 使用 Google Analytics 获取数据以显示在我们的网页上?

r - 在 R 中组合两个 Weibull 分布

python - 创建相关的 pandas 系列

CouchDB 索引以连接文档之间的点