24

我最近编写了一些 Javascript 代码来生成随机的虚假股票数据,因为我想展示一个乍看之下看起来像真实股票数据的图表 - 但我想出的只是点头。我只是想知道是否有一些资源可以解释如何“正确”完成此操作,即您可以获得与真实股票数据具有相同模式的逼真数据?

4

11 回答 11

68

一个简单的算法是使用一个简单的波动率数字来限制股票在给定时期(例如,一天)内的变化幅度。数字越高,波动性越大。因此,您每天都可以通过以下方式计算新价格:

rnd = Random_Float(); // generate number, 0 <= x < 1.0
change_percent = 2 * volatility * rnd;
if (change_percent > volatility)
    change_percent -= (2 * volatility);
change_amount = old_price * change_percent;
new_price = old_price + change_amount;

一只稳定的股票可能会有 2% 的波动率。10% 的波动率将显示一些相当大的波动。

不完美,但看起来很逼真。

样品

在此处输入图像描述

于 2011-12-21T23:53:44.613 回答
10

我有一本书《分形市场分析》 (最近才摆脱它),它谈到了股票价格的统计特性。对投资不是很有用,但它可能对你有帮助。

您将需要一些东西来模拟具有所需统计属性的随机过程。随机过程的两个例子是高斯白噪声维纳过程(后者模拟布朗运动,也是小步长随机游走的极限)。

如果我记得在 Fractal Market Analysis 书中,有人断言股票价格的对数具有类似于所谓的“1/f 噪声”或“粉红噪声”的特征,因此您可以尝试寻找有关粉红噪声的文章软件中的生成。(然后将结果插入 e^x)(编辑:哎呀,我记错了。看起来它更像是分数布朗运动

(这是一篇很好读的文章,讨论了分形随机过程研究背后的历史——以及尼罗河泛滥与股市的关系——不幸的是,它没有涉及技术数据,但也许有搜索词像赫斯特指数可以让你开始。)

如果您需要多个系列的股票数据,问题就会变得更加困难。(在这种情况下,股票之间存在一些相关性,这取决于各种共同因素,例如国民经济、行业类型等。)我不知道你该怎么做,但首先从一个随机过程开始。

于 2011-12-21T23:49:51.033 回答
8
# The following is an adaptation from a program shown at page 140 in
# "Stochastic Simulations and Applications in Finance",
# a book written by Huynh, Lai and Soumaré.
# That program was written in MatLab and this one was written in R by me.
# That program produced many price paths and this one produces one.
# The latter is also somewhat simpler and faster.

# Y is the time period in years, for instance 1 (year)
# NbSteps is the number of steps in the simulation,
# for instance 250 (trading days in a year).
# DeltaY is the resulting time step.

# The computations shown implement the exact solution
# to the stochastic differential equation for
# the geometric Brownian motion modelling stock prices,
# with mean mu and volatility sigma, thus generating a stochastic price path
# such as that exhibited by stock prices when price jumps are rare.

PricePath <- function(Y,NbSteps,mu,sigma,InitPrice) {
    DeltaY <- Y/NbSteps; SqrtDeltaY <- sqrt(DeltaY)
    DeltaW <- SqrtDeltaY * rnorm(NbSteps)
    Increments <- (mu-sigma*sigma/2)*DeltaY + sigma*DeltaW
    ExpIncr <- exp(Increments)
    PricePath <- cumprod(c(InitPrice,ExpIncr))
    return(PricePath)
}

该程序的输出图看起来非常像股票价格路径:

于 2011-12-22T20:44:07.460 回答
7

有几个答案给出了一个相当教科书的答案:使用几何布朗运动来模拟股票价格。但是有一个主要原因认为这是错误的。实际股票价格的表现与几何布朗运动 (GBM) 不同。我会稍微解释一下。

教科书中使用 GBM 来模拟股票价格过程的原因是为了简单。它可以帮助您使理论脱离实际并得出一些似乎“基本上”正确的基本结果。然而,这并不意味着你应该认为这就是股票价格“看起来”的样子。这就像推导出一个忽略摩擦的运动方程(这在理论上非常有用),然后认为这就是现实生活中的运动,例如每个人都像溜冰鞋一样穿着鞋子滑来滑去。

GBM 理论上最有用的特性之一是未来的变化独立于过去的变化。股票价格是这样吗?没有。一点也不。序列相关无处不在。不仅如此,大幅下跌之后通常伴随着波动性的增加,而大幅上涨之后通常伴随着波动性的下降。

我想我可能会被指责吹毛求疵,但这些程式化的事实对投资者和经济学家来说是众所周知的,所以我认为可以公平地说 GBM 对于任何熟悉股市行为的人来说都不现实。

计量经济学家提出了许多股票价格模型。似乎在很多情况下都有效的是条件均值的自回归模型与波动率的 (G)Arch 类型模型相结合。对于波动率模型,具有肥尾分布(如学生 t)的不对称 GARCH 似乎最适用于各种金融市场。

于 2013-11-25T06:33:22.727 回答
6

我快速写了一个肮脏的 javascript 版本,灵感来自 Peter P. 的回复。我需要创建每周、每年和总体趋势,以便接受一系列参数并将这些参数叠加起来以获得更复杂(假)的趋势。

  function getRandomData(numPoints, center, min, max, cycles)
{
    var result = [];
    var phase = Math.random() * Math.PI;
    var y = center;

    function randomPlusMinus() { return (Math.random() * 2) - 1; }

    $.each(cycles, function(i,thisCycle) {
        thisCycle.phase = Math.random() * Math.PI;
        thisCycle.increment = Math.PI / thisCycle.length;
    });

    for (var i = 0; i < numPoints; i++)
    {
        $.each(cycles, function(i,thisCycle) {
            thisCycle.phase += thisCycle.increment * randomPlusMinus();
            y += (Math.sin(thisCycle.phase) * (thisCycle.variance / thisCycle.length) * (randomPlusMinus() * thisCycle.noise)) + (thisCycle.trend / thisCycle.length);

        });
        if (min) y = Math.max(y,min);
        if (max) y = Math.min(y,max);
        result.push(y);
    }

    return result;
}

var data = getRandomData(365,80,20,100,
                      [{ length: 7, variance: 50, noise: 1, trend: 0},
                       { length: 365, variance: 30, noise: 1, trend: 0},
                       { length: 700, variance: 2, noise: 0, trend: 100}]);

我在那里放了一张图表来显示结果:http: //jsfiddle.net/z64Jr/3/

于 2014-01-07T18:34:22.117 回答
3

我想回复 Jim Mischel 上面的帖子 ( https://stackoverflow.com/a/8597889/1360592 ) 但由于我想包含代码,我不得不将我的回复放在这里。

基于 Jim Mischel 的算法,我执行了以下 Java 实现,它很好地满足了我的需求,生成的数字在绘制时生成了具有视觉吸引力、逼真的股票行情价格。

爪哇:

private float getNextPrice(float oldPrice)
{
    // Instead of a fixed volatility, pick a random volatility
    // each time, between 2 and 10.
    float volatility = _random.nextFloat() * 10 + 2;

    float rnd = _random.nextFloat();

    float changePercent = 2 * volatility * rnd;

    if (changePercent > volatility) {
        changePercent -= (2 * volatility);
    }
    float changeAmount = oldPrice * changePercent/100;
    float newPrice = oldPrice + changeAmount;

    // Add a ceiling and floor.
    if (newPrice < MIN_PRICE) {
        newPrice += Math.abs(changeAmount) * 2;
    } else if (newPrice > MAX_PRICE) {
        newPrice -= Math.abs(changeAmount) * 2;
    }

    return newPrice;

}

请注意,正如 wiggles 在他的评论中指出的那样,在声明 changeAmount 变量时,我需要将百分比除以 100。

于 2014-03-12T15:12:02.223 回答
1

看看雅虎财经,他们提供来自证券交易所和图表的免费延迟数据。

这是一篇关于使用提要的文章:http: //www.codeproject.com/KB/aspnet/StockQuote.aspx

您将需要 JQuery,或者您可以只使用 XMLHttpRequest 来使用该服务。仅供参考,有一个用于处理 CSV 的 JQuery 插件:http ://code.google.com/p/js-tables/

于 2011-12-21T23:53:28.170 回答
1

我需要为我正在开发的模拟游戏创建一些虚拟市场数据。我需要这些数据看起来像市场数据,但要保持在一定范围内,以便在起始价格、当天的最大值/最小值方面可以预测。

最后,我组合了不同频率的正弦波,然后添加了一些随机性,结果不仅看起来不错,而且是一致的(你不会得到任何看起来奇怪的东西)。即使在可以感知正弦波模式的地方,它看起来仍然没问题。

随机生成的市场数据

代码是用 BASIC 脚本语言编写的,但应该很容易理解并转换为您想要的任何语言。获得标准化数据数组后,将这些值乘以您想要获得有界数据集的任何最大值。

dim values[] as float
dim offsets[] as integer
dim frequencies[] as float

function GetPoint(x#, f#, a#, o#)

    f# = 360.0 / f#

    x# = FMod(x# + o#, f#)
    angle# = (x# / f#) * 360.0

    r# = Sin(angle#) * a#

endfunction r#

function Generate()

    // Empty arrays
    offsets.Length = -1
    frequencies.Length = -1
    values.Length = -1

    offsets.Insert(Random(0, 359))
    offsets.Insert(Random(0, 359))
    offsets.Insert(Random(0, 359))

    f# = Random(100, 300)
    f# = f# / 1000.0
    frequencies.Insert(f#)
    f# = Random(500, 1000)
    f# = f# / 1000.0
    frequencies.Insert(f#)
    f# = Random(2000, 4000)
    f# = f# / 1000.0
    frequencies.Insert(f#)

    c# = 0
    for i = 0 to 1919
        v# = 0
        v# = v# + GetPoint(i, frequencies[0], 190, offsets[0])
        v# = v# + GetPoint(i, frequencies[1], 85, offsets[1])
        v# = v# + GetPoint(i, frequencies[2], 40, offsets[2])

        r# = Random(0, 40)
        r# = r# - 20.0

        c# = Clamp(c# + r#, c# - 40, c# + 40)
        v# = v# + c#

        values.Insert(v#)
    next i

    start# = values[0]
    max# = 0.0
    for i = 0 to values.Length
        values[i] = values[i] - start#
        if Abs(values[i]) > max#
            max# = Abs(values[i])
        endif
    next i

    // Normalize
    for i = 0 to values.Length
        values[i] = (values[i] / max#)
    next i

endfunction

function Clamp(v#, min#, max#)

    if v# < min#
        exitfunction min#
    elseif v# > max#
        exitfunction max#
    endif

endfunction v#
于 2017-05-20T21:02:34.573 回答
0

这是我对红宝石的尝试!:) 这将输出一个字符串,您可以将其复制并粘贴到谷歌图表中。我允许数据的正面、负面或无趋势。该代码可能会针对随机性/规律性进行优化和/或调整。

谷歌图表:https ://code.google.com/apis/ajax/playground/?type=visualization#line_chart

# In order to generate a semi-realistic looking graph behavior
# we use a sine function to generate period behavior.  In order to avoid
# a graph that is too regular, we introduce randomness at two levels:
# The delta between steps across the x-axis is random, but within a range(deltavariance)
# The wavelength of the sine function is varied by randomly incrementing the index we pass
# to the sine function(sine_index)

# CONFIGURATION VARIABLES
yvalue = 1 # start value
range = 100 # y-range
deltavariance = 10 # allowable variance between changes
sine_index, wavelength = 0, 0.33 #index into our sine function that determines whether we change direction or not
i, maxi = 0, 100 # our counter and its maximum
data = {sine_index => yvalue} # seed our data structure with its first value
trend = :positive # :negative, :none # do we want the graph to trend upwards, downwards or neither
periodmin, periodmax = 0, 0 # vars to enforce trending
direction = 1 # start in a positive direction, -1 for negative

# DO NOT EDIT BELOW THIS LINE
while(i < maxi)

  olddirection = direction
  direction = Math.sin(sine_index).to_f
  direction = direction < 0 ? direction.floor : direction.ceil

  delta = rand(deltavariance) 
  yvalue += delta * direction

  if trend == :positive 
    yvalue = periodmin if yvalue < periodmin
    periodmin = yvalue if olddirection < direction
  elsif trend == :negative
    yvalue = periodmax if yvalue > periodmax
    periodmax = yvalue if olddirection > direction

  end

  data[sine_index] = yvalue
  sine_index += Math.sin(rand) # Math.sin(rand) will give random numbers from -1..1
  i += 1
end

code = <<-CODE
function drawVisualization() {
  // Create and populate the data table.
  var data = google.visualization.arrayToDataTable([
    ['x', 'Cats'],
    DATASTR
  ]);

  // Create and draw the visualization.
  new google.visualization.LineChart(document.getElementById('visualization')).
      draw(data, {curveType: "function",
                  width: 500, height: 400,
                  vAxis: {maxValue: 10}}
          );
}
CODE

datastr = data.collect{|k,v|  "[#{k},#{v}]"}.join(",")
code = code.gsub('DATASTR', datastr)
puts code
于 2013-11-20T06:48:12.927 回答
0
double price=2000;
    while (true) {
        double min =  (price*-.02);
        double max =  (price*.02);
        double randomNum = ThreadLocalRandom.current().nextDouble(min, max+1);
        price=price+randomNum;
        System.out.println(price);
    }

它是在java中。只需在 excel 列中绘制结果即可查看图表。使用大量值在 excel 中绘制。有趣的是,它看起来与真实股票数据有多么相似。

于 2017-01-11T04:52:06.053 回答
-1

这是我为我的使用而创建的代码。价格是为新烛台创建的,包括开盘价、最高价、最低价、收盘价和成交量。新价格是根据波动率百分比生成的。我用了总计 5% 的价格。

代码是基于 C# 的。

public class PriceBar
{
    public DateTime Date { get; set; }
    public double Open { get; set; }
    public double High { get; set; }
    public double Low { get; set; }
    public double Close { get; set; }
    public long Volume { get; set; }
}

public static double GetRandomNumber(double minimum, double maximum)
{
    Random random = new Random();
    return random.NextDouble() * (maximum - minimum) + minimum;
}

public static void GenerateRandomBar(PriceBar newBar)
{
    double fluct = 0.025;
    double volFluct = 0.40;

    //Open is equal to the previous close
    newBar.Open = newBar.Close;
    newBar.Close = GetRandomNumber(newBar.Close - newBar.Close * fluct, newBar.Close + newBar.Close * fluct);
    newBar.High = GetRandomNumber(Math.Max(newBar.Close, newBar.Open), Math.Max(newBar.Close, newBar.Open) + Math.Abs(newBar.Close - newBar.Open) * fluct);
    newBar.Low = GetRandomNumber(Math.Min(newBar.Close, newBar.Open), Math.Min(newBar.Close, newBar.Open) - Math.Abs(newBar.Close - newBar.Open) * fluct);
    newBar.Volume = (long)GetRandomNumber(newBar.Volume * volFluct, newBar.Volume);
}

用法:

创建 PriceBar 的实例,填充上一个柱的价格。将 PriceBar 实例提供给函数GenerateRandomBar()。它将返回一个带有新值的 PriceBar。

于 2014-08-05T01:13:50.053 回答