Tjorriemorrie
Tjorriemorrie

Reputation: 17282

How to generate a fractal graph of a market in python

I wish to generate this in python:

http://classes.yale.edu/fractals/RandFrac/Market/TradingTime/Example1/Example1.html

but I'm incredibly stuck and new to this concept. Does anybody know of a library or gist for this?

enter image description here

Edit: From what I can understand is that you need to split the fractal in 2 every time. So you have to calculate the y-axis point from the line between the two middle points. Then the two sections need to be formed according to the fractal?

Upvotes: 3

Views: 5955

Answers (3)

asterio gonzalez
asterio gonzalez

Reputation: 1204

Using @tobias_k solution and pandas, we can translate and scale the normalized fractal to a time-based one.

import arrow
import pandas as pd
import time

depth = 5
# the "geometry" of fractal
turns = [
        (1 / 9, 0.60),
        (5 / 9, 0.30),
        (8 / 9, 0.70),
    ]

# select start / end time 
t0 = arrow.now().floor("hours")
t1 = t0.shift(days=5)
start = (pd.to_datetime(t0._datetime), 1000)
end = (pd.to_datetime(t1._datetime), 2000)

# create a non-dimensionalized [0,0]x[1,1] Fractal
_start, _end = (0, 0), (1, 1)  
graph = set()
make_graph(depth, graph, _start, _end, turns)
# just check graph length
assert len(graph) == (len(turns) + 1) ** depth + 1

# create a pandas dataframe from the normalized Fractal
df = pd.DataFrame(graph)
df.sort_values(0, inplace=True)
df.reset_index(drop=True, inplace=True)

# translate to real coordinates
X = pd.DataFrame(
        data=[(start[0].timestamp(), start[1]), (end[0].timestamp(), end[1])]
        ).T
delta = X[1] - X[0]
Y = df.mul(delta) + X[0]
Y[0] = [*map(lambda x: pd.to_datetime(x, unit="s"), Y[0])]

# now resample and interpolate data according to *grid* size
grid ="min"
Z = Y.set_index(0)
A = Z.resample(grid).mean().interpolate()

# plot both graph to check errors
import matplotlib.pyplot as plt
ax = Z.plot()
A.plot(ax=ax)
plt.show()

showing both graphs:

Both graphs

and zooming to see interpolation and snap-to-grid differences:

enter image description here

Upvotes: 0

hyperstripe50
hyperstripe50

Reputation: 1

I had a similar interest and developed a python3 library to do just what you want.

pip install fractalmarkets

See https://github.com/hyperstripe50/fractal-market-analysis/blob/master/README.md

Upvotes: 0

tobias_k
tobias_k

Reputation: 82899

Not 100% sure what you are asking, but as I understood from your comments, you want to generate a realistically looking stock market curve using the recursion described in the link.

As far as I understood the description in the linked page and some of the parent pages, it works like this:

  1. You are given a start and an end point and a number of turning points in the form (t1, v1), (t2, v2), etc., for example start=(0,0), end=(1,1), turns = [(1/4, 1/2), (3/4, 1/4)], where ti and vi are fractions between 0 and 1.
  2. You determine the actual turning points scaled to that interval between start and end and calculate the differences between those points, i.e. how far to go from pi to reach pi+1.
  3. You shuffle those segments to introduce some randomness; when put together, they still cover exactly the same distance, i.e. they connect the original start and end point.
  4. Repeat by recursively calling the function for the different segments between the new points.

Here's some Python code I just put together:

from __future__ import division
from random import shuffle

def make_graph(depth, graph, start, end, turns):
    # add points to graph
    graph.add(start)
    graph.add(end)

    if depth > 0:   
        # unpack input values
        fromtime, fromvalue = start
        totime, tovalue = end

        # calcualte differences between points
        diffs = []
        last_time, last_val = fromtime, fromvalue
        for t, v in turns:
            new_time = fromtime + (totime - fromtime) * t
            new_val = fromvalue + (tovalue - fromvalue) * v
            diffs.append((new_time - last_time, new_val - last_val))
            last_time, last_val = new_time, new_val

        # add 'brownian motion' by reordering the segments
        shuffle(diffs)

        # calculate actual intermediate points and recurse
        last = start
        for segment in diffs:
            p = last[0] + segment[0], last[1] + segment[1]
            make_graph(depth - 1, graph, last, p, turns)
            last = p
        make_graph(depth - 1, graph, last, end, turns)

from matplotlib import pyplot
depth = 8
graph = set()
make_graph(depth, graph, (0, 0), (1, 1), [(1/9, 2/3), (5/9, 1/3)])
pyplot.plot(*zip(*sorted(graph)))
pyplot.show()

And here some example output:

enter image description here

Upvotes: 9

Related Questions