- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我最近写了一个程序,从股市中返回一堆不健康的股票。基本算法是这样的:
查找交易所(NYSE 或 NASDAQ)中每只股票的所有报价
从步骤 1 中找出小于 5 美元的
从第 2 步中找到下跌 3 天且成交量较大的股票(价格昂贵,因为我必须对每只股票提出请求,目前纳斯达克市场大约为 700 股)。
<扫描第 3 步返回的新闻。
我把所有这些都放在一个文件中:
原始实现(https://github.com/EdmundMai/minion/blob/aa14bc3234a4953e7273ec502276c6f0073b459d/lib/minion.rb):
require 'bundler/setup'
require "minion/version"
require "yahoo-finance"
require "business_time"
require 'nokogiri'
require 'open-uri'
module Minion
class << self
def query(exchange)
client = YahooFinance::Client.new
all_companies = CSV.read("#{exchange}.csv")
small_caps = []
ticker_symbols = all_companies.map { |row| row[0] }
ticker_symbols.each_slice(200) do |batch|
data = client.quotes(batch, [:symbol, :last_trade_price, :average_daily_volume])
small_caps << data.select { |stock| stock.last_trade_price.to_f < 5.0 }
end
attractive = []
small_caps.flatten!.each_with_index do |small_cap, index|
begin
data = client.historical_quotes(small_cap.symbol, { start_date: 2.business_days.ago, end_date: Time.now })
closing_prices = data.map(&:close).map(&:to_f)
volumes = data.map(&:volume).map(&:to_i)
negative_3_days_in_a_row = closing_prices == closing_prices.sort
larger_than_average_volume = volumes.reduce(:+) / volumes.count > small_cap.average_daily_volume.to_i
if negative_3_days_in_a_row && larger_than_average_volume
attractive << small_cap.symbol
puts "Qualified: #{small_cap.symbol}, finished with #{index} out of #{small_caps.count}"
else
puts "Not qualified: #{small_cap.symbol}, finished with #{index} out of #{small_caps.count}"
end
rescue => e
puts e.inspect
end
end
final_results = []
attractive.each do |symbol|
rss_feed = Nokogiri::HTML(open("http://feeds.finance.yahoo.com/rss/2.0/headline?s=#{symbol}®ion=US&lang=en-US"))
html_body = rss_feed.css('body')[0].text
diluting = false
['warrant', 'cashless exercise'].each do |keyword|
diluting = true if html_body.match(/#{keyword}/i)
end
final_results << symbol if diluting
end
final_results
end
end
end
这真的很快,可以在一分钟或更短的时间内完成约 700 种库存的处理。
然后,我尝试在完全不更改算法的情况下重构算法并将其拆分为不同的类和文件。我决定使用装饰器模式,因为它看起来很合适。但是,当我现在运行该程序时,它使每个请求都非常缓慢(15 分钟以上)。我知道这一点是因为我的 puts
语句打印出来的速度非常慢。
新的和较慢的实现(https://github.com/EdmundMai/minion/blob/master/lib/minion.rb)
require 'bundler/setup'
require "minion/version"
require "yahoo-finance"
require "minion/dilution_finder"
require "minion/negative_finder"
require "minion/small_cap_finder"
require "minion/market_fetcher"
module Minion
class << self
def query(exchange)
all_companies = CSV.read("#{exchange}.csv")
all_tickers = all_companies.map { |row| row[0] }
short_finder = DilutionFinder.new(NegativeFinder.new(SmallCapFinder.new(MarketFetcher.new(all_tickers))))
short_finder.results
end
end
end
根据我的puts
,它滞后的部分:
require "yahoo-finance"
require "business_time"
require_relative "stock_finder"
class NegativeFinder < StockFinder
def results
client = YahooFinance::Client.new
results = []
finder.results.each_with_index do |stock, index|
begin
data = client.historical_quotes(stock.symbol, { start_date: 2.business_days.ago, end_date: Time.now })
closing_prices = data.map(&:close).map(&:to_f)
volumes = data.map(&:volume).map(&:to_i)
negative_3_days_in_a_row = closing_prices == closing_prices.sort
larger_than_average_volume = volumes.reduce(:+) / volumes.count > stock.average_daily_volume.to_i
if negative_3_days_in_a_row && larger_than_average_volume
results << stock
puts "Qualified: #{stock.symbol}, finished with #{index} out of #{finder.results.count}"
else
puts "Not qualified: #{stock.symbol}, finished with #{index} out of #{finder.results.count}"
end
rescue => e
puts e.inspect
end
end
results
end
end
它滞后于第 3 步(对每只股票提出一个请求)。不确定发生了什么,所以任何建议将不胜感激。如果你想克隆程序并运行它,只需在 lib/minion.rb 的最后一行注释并键入 ruby lib/minion.rb
最佳答案
经过调试,我明白了。这是因为我在循环内部调用了 finder.results
(results 是装饰方法),如下所示:
require 'bundler/setup'
require "minion/version"
require "yahoo-finance"
require "minion/dilution_finder"
require "minion/negative_finder"
require "minion/small_cap_finder"
require "minion/market_fetcher"
module Minion
class << self
def query(exchange)
all_companies = CSV.read("#{exchange}.csv")
all_tickers = all_companies.map { |row| row[0] }
short_finder = DilutionFinder.new(NegativeFinder.new(SmallCapFinder.new(MarketFetcher.new(all_tickers))))
short_finder.results
end
end
end
根据我的puts
,它滞后的部分:
require "yahoo-finance"
require "business_time"
require_relative "stock_finder"
class NegativeFinder < StockFinder
def results
client = YahooFinance::Client.new
results = []
finder.results.each_with_index do |stock, index|
begin
data = client.historical_quotes(stock.symbol, { start_date: 2.business_days.ago, end_date: Time.now })
closing_prices = data.map(&:close).map(&:to_f)
volumes = data.map(&:volume).map(&:to_i)
negative_3_days_in_a_row = closing_prices == closing_prices.sort
larger_than_average_volume = volumes.reduce(:+) / volumes.count > stock.average_daily_volume.to_i
if negative_3_days_in_a_row && larger_than_average_volume
results << stock
// HERE!!!!!!!!!!!!!!!!!!!!!!!!!
puts "Qualified: #{stock.symbol}, finished with #{index} out of #{finder.results.count}" <------------------------------------
else
// AND HERE!!!!!!!!!!!!!!!!!!!!!!!!!
puts "Not qualified: #{stock.symbol}, finished with #{index} out of #{finder.results.count}" <-----------------------------------------------------------
end
rescue => e
puts e.inspect
end
end
results
end
end
每次我遍历 NegativeFinder
中的循环时,这都会导致一连串的请求。删除该调用修复它。经验教训:当使用装饰器模式时,要么只调用一次装饰方法,尤其是当你在每次调用中做一些昂贵的事情时。或者将返回的变量保存在实例变量中,这样您就不必每次都计算它。
另请注意,我决定不使用装饰器模式,因为我认为它在这里不太适用。像 SmallCapFinder.new(SmallCapFinder.new(MarketFetcher.new(all_tickers)))
之类的东西根本不添加功能(使用装饰器模式的主要功能),所以链接装饰器不会做任何事物。因此,我只是让它们成为方法,而不是增加不必要的复杂性。
关于Ruby:装饰器模式大大降低了简单程序的速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32800238/
我在堆栈上创建了这段代码: function increase_brightness(hex, percent){ var r = parseInt(hex.substr(1, 2), 16)
为什么我能够LOWER COALESCE 中的每个项目,但无法LOWER整个COALESCE,否则我会遇到语法错误?例如: SELECT COALESCE(LOWER(google_provider_
我在谷歌上搜索到的所有内容都表明,以下任何一项都会将 double 舍入到小数点后两位。 double roundToFourDecimals(double d) { DecimalForma
我正在开发一个 flexdashboard/storyboard,我想在其中降低每个帧的高度。那可能吗? 示例代码: --- title: "Flex" output: flexdashboard
我在 WPF 中有一个图像控件。我需要减小图像尺寸控件的宽度和高度。但是当我这样做时,图像看起来不太好。数据丢失更多。 所以我想降低图像分辨率而不是仅仅改变图像控件的宽度和高度。 任何人都可以帮助我如
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题?通过 editing this post 添加详细信息并澄清问题. 1年前关闭。 Improve this
我正在扩展 Fluent NHibernate,以便更好地与 F# 一起使用(即引用支持),并希望获得一些关于降低 API 流畅性的反馈。 F# 要求使用返回值,除非它们是单位类型。所以这最终以“|>
我们有一个 BizTalk 2010 接收位置,它将获取一个 70MB 的文件,然后使用入站映射(在接收位置)和出站映射(在发送端口)生成一个 1GB 文件。 执行上述过程时,SQL Server 会
我的代码分析插件提示包含以下代码的方法中的代码复杂性。我注意到以下代码看起来可以组合,但我不知道如何做到这一点: for(Command command : commands) { if (c
我正在寻找一种方法来始终忽略 R 中 float 之间的微小差异(根据 IEC 60559,这些是 double 浮点),通过使用基本 R 工具而不诉诸 C 或 C++。换句话说,我想“四舍五入” d
在 Blazor 中使用 ChartJs.Blazor 的 BarChart 组件时是否可以降低甚至关闭动画速度?我发现这个 NuGet 包非常有用,但我不知道如何在更新条形图时关闭动画。为了更容易忽
所以我为一个游戏编写了这段代码,现在该游戏的速度非常快。我想降低 FPS,让游戏慢一点。 我认为我唯一的出路就是制作一个计时器。但我发现很难找到放置计时器的位置?谁能帮我解决这个问题吗? 所以我为一个
我正在编写一个程序,我担心它运行所需的时间和所占用的空间。 在程序中我使用了一个变量来存储数组的长度: int len=newarray3.length; 现在,我想知道是否能够通过不使用 len 变
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 2 年前。 Improve th
我用Java编写了一个程序,但它的计算时间很长,我不知道为什么。有人可以指点一下以降低复杂性吗?此外,在计算一些值(例如 3,100 之后)后,它会给出空指针异常。代码: public class F
我有下图,由 1 行 2 列的网格组成。我愿意 降低右侧子图的高度(3D PREDICTION),使棋盘平面看起来有点挤压并显示更好的视角。 在左侧子图的顶部添加一些边距(2D PREDICTION)
是否有一种简单的方法可以更改以 RGB 字符串形式给出的颜色的亮度? 例如 in_RGB = '#FF0000' --> out_RGB = '#CC0000' 最佳答案 将十六进制字符串转换为 R
我已经编写了代码来更改对象(不是进程)(在本例中是文件)的完整性级别。据我们所知,我们从中等完整性级别开始,但我想将其降低到“低”。我想运行完整性较低的 .txt 文件而不是默认介质。 我使用 WIN
是否可以在保持原始宽高不变的情况下降低图像分辨率? 我已经使用 BitmapFactoryOptions 尝试了几个选项: 在样本大小 inDensity、inScaled、inTargetDensi
是否有高级(Java)或低级方式(使用 native 代码)将 Android 设备上的蓝牙信号强度更改为最低? 目标是使设备在 20 厘米范围内可被发现?在 Internet 上根本找不到与此相关的
我是一名优秀的程序员,十分优秀!