2

我正在玩 Perl 中的历史股票市场分析。一方面涉及分析研究公司过去股票评级的准确性。最基本的评级量表是买入、持有、卖出。然而,这些公司中的许多使用不同的术语,有些公司的规模超过 3 分。

我所拥有的是由数百家不同公司(来自雅虎财经)发布的数千个升级/降级列表,看起来像这样:

Action      From      To
==================================================
Upgrade     Add           Buy
Downgrade   Add           Hold
Upgrade     Hold          Add
Downgrade   Buy           Outperform
Upgrade     Hold          Outperform
Downgrade   Hold          Reduce
Upgrade     Add           Outperform

所以基本上它是一个比较列表,如 A > B、D < C、B > C、D < A

对于每家研究公司,我需要一个长长的这些比较列表,是一个如下所示的有序列表:

A > B > C > D > E

我已经对这个问题进行了很多思考,但无法提出解决方案。如果每次升级/降级只跳跃一个增量,我想我可以做到,但我无法理解如何插入像 C < A 这样的比较,它会跳跃两个增量。

有人有什么想法吗?




更新:

谢谢@ikegami。我用原始数据测试过,你是对的。

我还通过 Graph::Easy 运行了一些数据,它可以呈现图形。

代码:

use Graph::Easy;
my $graph = Graph::Easy->new( );

# Note that these are all in 'Upgrade' direction
$graph->add_edge ('Hold', 'Add');
$graph->add_edge ('Hold', 'Buy');
$graph->add_edge ('Hold', 'Outperform');
$graph->add_edge ('Buy', 'Outperform');
$graph->add_edge ('Reduce', 'Hold');
$graph->add_edge ('Add', 'Buy');

print $graph->as_ascii( );

输出:

               +------------------------+
               |                        v
+--------+     +------+     +-----+     +-----+     +------------+
| Reduce | --> | Hold | --> | Add | --> | Buy | --> | Outperform |
+--------+     +------+     +-----+     +-----+     +------------+
               |                                    ^
               +------------------------------------+

这是一个带有一些明显歧义的图表。也许我可以以某种方式使用这两个模块(或 Graph 的某些功能)来测试歧义。

+------------------------------+
|                              v
+--------+     +---------+     +-----+
| Reduce | --> | Neutral | --> | Buy |
+--------+     +---------+     +-----+
                 ^               ^
                 |               |
                 |               |
               +---------+       |
               |  Sell   | ------+
               +---------+
4

1 回答 1

5

我不经常使用图表,但是这段代码(使用Graph模块)似乎可以完成这项工作:

use Graph;
use strict;

my $graph = Graph->new;

while (<DATA>) {
    my ($dir, $x, $y) = split;
    if ($dir eq 'Downgrade') {
        ($x, $y) = ($y, $x);
    } elsif ($dir ne 'Upgrade') {
        die qq(Unknown direction "$dir"\n);
    }
    $graph->add_edge($x, $y);
}

$graph->is_dag
    or die "Graph has a cycle--unable to analyze\n";
$graph->is_weakly_connected
    or die "Graph is not weakly connected--unable to analyze\n";

print join(' < ', $graph->topological_sort), "\n";

__DATA__
Upgrade     Add           Buy
Downgrade   Add           Hold
Upgrade     Hold          Add
Downgrade   Buy           Outperform
Upgrade     Hold          Outperform
Downgrade   Hold          Reduce
Upgrade     Add           Outperform

这打印Reduce < Hold < Add < Outperform < Buy

于 2012-01-20T00:32:58.410 回答