Известны ли методы создания реалистичных фальшивых данных запаса?
Недавно я написал код Javascript для генерации случайных фальшивых данных о запасах, так как я хотел показать диаграмму, которая сначала выглядела как настоящие данные о запасах, но все, что я придумал, было довольно простак. Мне просто интересно, есть ли какие-то ресурсы, объясняющие, как это можно сделать "правильно", т.е. Вы получите реалистичные данные, которые имеют те же шаблоны, которые вы видите в реальных данных запаса?
Ответы
Ответ 1
У меня была книга Фрактальный анализ рынка (недавно избавилась от нее), в которой говорилось о статистических свойствах цен на акции. Не очень полезно для инвестиций, но он, возможно, смог вам помочь.
Вам понадобится что-то, что моделирует случайный процесс с требуемыми статистическими свойствами. Два примера случайных процессов: гауссовский белый шум и процесс Wiener (последний, который моделирует броуновское движение, а также является пределом случайного блуждания с малыми шагами).
Если я помню прямо из книги анализа фрактального рынка, было утверждение, что логарифм цен на акции имел характеристики, аналогичные так называемым "шумом 1/f" или "розовый шум" , поэтому вы можете попробовать искать статьи о генерации розового шума в программном обеспечении. (а затем взять результаты и вставить их в e ^ x) (изменить: oops, я забыл. Похоже, это больше дробное броуновское движение)
(Здесь хороший читаемый эссе, в котором рассказывается об истории изучения фрактальных случайных процессов - и о том, как происходит наводнение Нила к фондовому рынку - к сожалению, он не попадает в технические данные, но, возможно, есть поисковые термины, такие как показатель Hurst, который может вас начать. )
Проблема становится более сложной, если вам нужна несколько серий данных запаса. (в этом случае существует некоторая корреляция между запасами, которые зависят от различных общих факторов, например, национальной экономики, типа отрасли и т.д.). Я не уверен, как вы могли это сделать, но сначала начните с одного случайного процесса.
Ответ 2
Простым алгоритмом является использование простого числа волатильности, которое ограничивает количество акций в течение определенного периода (скажем, за один день). Чем выше число, тем более изменчивым. Поэтому каждый день вы можете вычислить новую цену:
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% продемонстрировала бы довольно большие колебания.
Не идеально, но может показаться довольно реалистичным.
Образцы
![enter image description here]()
Ответ 3
# 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)
}
![The plot of the output from this program looks very much like a stock price path:]()
Ответ 4
Есть несколько ответов, которые дают довольно учебный ответ: используйте геометрическое движение буриунов для моделирования цен на акции. Но есть одна серьезная причина считать это неправильным. Реальные цены на акции не ведут себя как геометрическое движение коричневого цвета (GBM). Я объясню это немного.
Причина, по которой GBM используется в учебниках для моделирования процесса цен на акции, является для простоты. Это помогает вам получить теорию с нуля и получить некоторые основные результаты, которые кажутся "по существу" правильными. Это не значит, что вам следует подумать, что цены на акции "выглядят". Это было бы похоже на выработку уравнения движения, пренебрегающего трением (что теоретически очень полезно), а затем думая, что это то, что движение выглядит в реальной жизни, например. все катятся на своих туфлях, как коньки для льда.
Одним из теоретически наиболее полезных свойств GBM является то, что будущие изменения не зависят от прошлых изменений. Это касается цен на акции? Неа. Не за что. Последовательная корреляция происходит повсеместно. Не только это, как правило, значительное уменьшение обычно сопровождается повышенной волатильностью, в то время как значительное увеличение обычно сопровождается сниженной летучестью.
Полагаю, меня могут обвинить в придирчивости, но эти стилизованные факты широко известны инвесторам и экономистам, поэтому я считаю справедливым сказать, что GBM не выглядит реалистичным для любого, кто знаком с поведением на фондовом рынке.
Эконометристы придумали множество моделей для цен на акции. Тот, который, кажется, работает во многих ситуациях, является авторегрессивной моделью условного среднего в сочетании с моделью типа А (G) для волатильности. Для модели волатильности асимметричный GARCH с распределением жира-хвоста (например, Student t), по-видимому, наилучшим образом подходит для различных финансовых рынков.
Ответ 5
Я написал быстро грязную версию javascript, вдохновленную ответом Питера П. здесь. Мне нужно было создавать еженедельные, годовые и общие тенденции, поэтому он принимает массив параметров и накладывает их на более сложную (фальшивую) тенденцию.
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/
Ответ 6
Взгляните на yahoo finance, они предлагают бесплатные отложенные данные из биржи и диаграмм.
Вот статья об использовании фида:
http://www.codeproject.com/KB/aspnet/StockQuote.aspx
Вам понадобится JQuery, или вы можете просто использовать XMLHttpRequest для использования службы. FYI, есть плагин для JQuery для обработки CSV: http://code.google.com/p/js-tables/
Ответ 7
Я хотел ответить на пост Джима Мишеля выше (fooobar.com/questions/371110/...), но так как я хотел включить код, я вынужден ответить здесь.
Основываясь на Jim Mischel alorithm, я сделал следующую реализацию Java, и она хорошо работала для моих нужд, генерируя числа, которые при графике создавали визуально привлекательные реалистичные цены биржевых котировок.
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;
}
Обратите внимание, что, как отмечали в своем комментарии, как мне кажется, мне нужно было разделить процент на 100 при объявлении переменной changeAmount.
Ответ 8
Мне нужно было создать некоторые фиктивные рыночные данные для симовой игры, над которой я работал. Мне нужны данные, чтобы они выглядели как рыночные данные, но оставались в определенных диапазонах, поэтому они были предсказуемы с точки зрения стартовой цены, максимума/минимума в течение дня.
В конце я объединил синусоидальные волны с различными частотами, а затем добавил в какой-то случайности, и результаты не просто выглядят хорошо, но согласуются (вы не получаете ничего, что выглядит странно). Даже там, где синус-волновой рисунок можно воспринимать, он все еще выглядит хорошо.
Произвольные рыночные данные
Код написан на языке сценариев 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#
Ответ 9
Здесь моя попытка в рубине!:) Это выведет строку, которую вы можете скопировать и вставить в диаграммы Google. Я допускаю положительные, отрицательные или отсутствующие тренды данных. Возможно, этот код можно было бы оптимизировать и/или настроить на случайность/регулярность.
Графики Google: 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
Ответ 10
Джейсон С. был близок, хотя.
Рынки являются естественными и, следовательно, фрактальными.
Вот лучший способ создания фондовых рынков:
![enter image description here]()
источник
Ответ 11
Вот код, который я создал для моего использования. Цены создаются для новой свечной палочки, которая включает в себя Open, High, Low, Close и Volume. Новые цены генерируются на основе% волатильности. Я использовал всего 5% для цен.
Код основан на С#.
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 с новыми значениями.
Ответ 12
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. Интересно видеть, как это похоже на реальные данные о запасах.