/ candlesticks.py
candlesticks.py
1 # SPDX-FileCopyrightText: Copyright (c) 2021 Jose David 2 # 3 # SPDX-License-Identifier: MIT 4 """ 5 `candlesticks` 6 ================================================================================ 7 8 Graphical representation of the stock movement in candlestick form 9 10 11 * Author(s): Jose David 12 13 Implementation Notes 14 -------------------- 15 16 * Adafruit CircuitPython firmware for the supported boards: 17 https://github.com/adafruit/circuitpython/releases 18 19 """ 20 21 # pylint: disable=too-many-lines, too-many-instance-attributes, too-many-arguments 22 # pylint: disable=too-many-locals, too-many-statements, invalid-name, too-few-public-methods 23 24 import math 25 import displayio 26 from vectorio import Rectangle 27 28 __version__ = "0.0.0-auto.0" 29 __repo__ = "https://github.com/jposada202020/CircuitPython_Candlesticks.git" 30 31 32 class Candlestick: 33 """A graphical candlestick representation 34 35 :param int dist_x: number of segments in each bar 36 37 :param int openp: Stock open price 38 :param int close: Stock close price 39 :param int high: Stock high price 40 :param int low: Stock low price 41 42 :param int color_green: When stock close price is higher thant the price opening 43 candlestick are representing by a green color. This allows the selection of the 44 color of your choice 45 :param int color_red: When stock close price is lower thant the price opening 46 candlestick are representing by a red color. This allows the selection of the 47 color of your choice 48 49 :param int screen_ref: Distance in pixels from the left to the screem to locate 50 the candlestick. This allows to present different candlesticks in the same screen 51 52 53 **Quickstart: Importing and using Candlestick** 54 55 Here is one way of importing the `Candlestick` class, so you can use it as 56 the name ``my_candle``: 57 58 .. code-block:: python 59 60 from CircuitPython_Candlesticks.candlesticks import Candlestick as Candlestick 61 62 Now you can create a plane at pixel position x=100, open price=60 close price=30 63 high price=80 low price=5 using: 64 65 .. code-block:: python 66 67 my_candle = Candlestick(100, 60, 30, 80, 5) 68 69 Once you set up your display, you can now add ``my_candle`` to your display using: 70 71 .. code-block:: python 72 73 display.show(my_plane) # add the group to the display 74 75 If you want to have multiple display elements, you can create a group and then 76 append the plane and the other elements to the group. Then, you can add the full 77 group to the display as in this example: 78 79 .. code-block:: python 80 81 my_candle = Candlestick(100, 60, 30, 80, 5) 82 my_group = displayio.Group() # make a group 83 my_group.append(my_plane) # Add my_plane to the group 84 85 # 86 # Append other display elements to the group 87 # 88 89 display.show(my_group) # add the group to the display 90 91 92 **Summary: Cartesian Features and input variables** 93 94 The `Candlestick` class has some options for controlling its position, appearance, 95 through a collection of input variables: 96 97 - **position**: ``x`` 98 99 - **color**: ``color_green``, ``color_red`` 100 101 102 .. figure:: candlestick.png 103 :scale: 90 % 104 :alt: Diagram of layout coordinates 105 106 Diagram showing 5 different candlesticks. 107 108 """ 109 110 def __init__( 111 self, 112 dist_x: int, 113 openp: int, 114 close: int, 115 high: int, 116 low: int, 117 color_green: int = 0x00FF00, 118 color_red: int = 0xFF0000, 119 screen_ref: int = 180, 120 ) -> None: 121 122 self._my_group = displayio.Group() 123 self._dist_x = dist_x 124 self.bitmap = displayio.Bitmap(high - low, 12, 5) 125 self._candlestick_palette = displayio.Palette(2) 126 self._candlestick_palette.make_transparent(0) 127 128 self.body_palette = displayio.Palette(2) 129 self.body_palette.make_transparent(0) 130 if openp > close: 131 self.body_palette[1] = color_red 132 self._candlestick_palette[1] = color_red 133 else: 134 self.body_palette[1] = color_green 135 self._candlestick_palette[1] = color_green 136 137 if openp > close: 138 self._top = openp 139 self._bottom = close 140 else: 141 self._top = close 142 self._bottom = openp 143 144 self._high = high 145 self._low = low 146 147 self.screen_ref = screen_ref 148 149 self._draw_lines() 150 151 def _draw_lines(self): 152 top_line_height = int(math.fabs(self._high - self._top)) 153 if top_line_height == 0: 154 top_line_height = 1 155 156 top_line = Rectangle( 157 pixel_shader=self.body_palette, 158 width=1, 159 height=top_line_height, 160 x=self._dist_x, 161 y=self.screen_ref - self._high, 162 color_index=1, 163 ) 164 165 body_height = int(math.fabs(self._top - self._bottom)) 166 167 body = Rectangle( 168 pixel_shader=self.body_palette, 169 width=10, 170 height=body_height, 171 x=self._dist_x - 5, 172 y=self.screen_ref - self._top, 173 color_index=1, 174 ) 175 176 bottom_line_height = int(math.fabs(self._bottom - self._low)) 177 if bottom_line_height == 0: 178 bottom_line_height = 1 179 180 bottom_line = Rectangle( 181 pixel_shader=self.body_palette, 182 width=1, 183 height=bottom_line_height, 184 x=self._dist_x, 185 y=self.screen_ref - self._bottom, 186 color_index=1, 187 ) 188 189 self._my_group.append(top_line) 190 self._my_group.append(body) 191 self._my_group.append(bottom_line) 192 193 self.my_rep = self._my_group