use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[repr(u8)]
pub enum LineStyle {
#[default]
Solid = 0,
Dotted = 1,
Dashed = 2,
LargeDashed = 3,
SparseDotted = 4,
}
impl LineStyle {
pub fn all() -> &'static [Self] {
&[
Self::Solid,
Self::Dotted,
Self::Dashed,
Self::LargeDashed,
Self::SparseDotted,
]
}
pub fn name(&self) -> &'static str {
match self {
Self::Solid => "solid",
Self::Dotted => "dotted",
Self::Dashed => "dashed",
Self::LargeDashed => "large_dashed",
Self::SparseDotted => "sparse_dotted",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::Solid => "Solid",
Self::Dotted => "Dotted",
Self::Dashed => "Dashed",
Self::LargeDashed => "Large Dashed",
Self::SparseDotted => "Sparse Dotted",
}
}
pub fn pattern(&self) -> Vec<f32> {
match self {
Self::Solid => vec![f32::MAX],
Self::Dotted => vec![2.0, 4.0],
Self::Dashed => vec![10.0, 5.0],
Self::LargeDashed => vec![16.0, 6.0],
Self::SparseDotted => vec![2.0, 8.0],
}
}
}
impl fmt::Display for LineStyle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum ChartMode {
#[default]
Linear,
Logarithmic,
Percentage,
IndexedTo100,
}
impl ChartMode {
pub fn all() -> &'static [Self] {
&[
Self::Linear,
Self::Logarithmic,
Self::Percentage,
Self::IndexedTo100,
]
}
pub fn name(&self) -> &'static str {
match self {
Self::Linear => "linear",
Self::Logarithmic => "log",
Self::Percentage => "percentage",
Self::IndexedTo100 => "indexed_to_100",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::Linear => "Linear",
Self::Logarithmic => "Logarithmic",
Self::Percentage => "Percentage",
Self::IndexedTo100 => "Indexed to 100",
}
}
pub fn short_name(&self) -> &'static str {
match self {
Self::Linear => "Lin",
Self::Logarithmic => "Log",
Self::Percentage => "%",
Self::IndexedTo100 => "Idx",
}
}
}
impl fmt::Display for ChartMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Timezone {
#[default]
Local,
Exchange,
UTC,
AmericaNewYork,
AmericaChicago,
AmericaDenver,
AmericaLosAngeles,
EuropeLondon,
EuropeParis,
EuropeBerlin,
AsiaTokyo,
AsiaHongKong,
AsiaSingapore,
AustraliaSydney,
PacificAuckland,
}
impl Timezone {
pub fn all() -> &'static [Self] {
&[
Self::Local,
Self::Exchange,
Self::UTC,
Self::AmericaNewYork,
Self::AmericaChicago,
Self::AmericaDenver,
Self::AmericaLosAngeles,
Self::EuropeLondon,
Self::EuropeParis,
Self::EuropeBerlin,
Self::AsiaTokyo,
Self::AsiaHongKong,
Self::AsiaSingapore,
Self::AustraliaSydney,
Self::PacificAuckland,
]
}
pub fn name(&self) -> &'static str {
match self {
Self::Local => "local",
Self::Exchange => "exchange",
Self::UTC => "UTC",
Self::AmericaNewYork => "America/New_York",
Self::AmericaChicago => "America/Chicago",
Self::AmericaDenver => "America/Denver",
Self::AmericaLosAngeles => "America/Los_Angeles",
Self::EuropeLondon => "Europe/London",
Self::EuropeParis => "Europe/Paris",
Self::EuropeBerlin => "Europe/Berlin",
Self::AsiaTokyo => "Asia/Tokyo",
Self::AsiaHongKong => "Asia/Hong_Kong",
Self::AsiaSingapore => "Asia/Singapore",
Self::AustraliaSydney => "Australia/Sydney",
Self::PacificAuckland => "Pacific/Auckland",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::Local => "Local",
Self::Exchange => "Exchange",
Self::UTC => "UTC",
Self::AmericaNewYork => "New York (EST/EDT)",
Self::AmericaChicago => "Chicago (CST/CDT)",
Self::AmericaDenver => "Denver (MST/MDT)",
Self::AmericaLosAngeles => "Los Angeles (PST/PDT)",
Self::EuropeLondon => "London (GMT/BST)",
Self::EuropeParis => "Paris (CET/CEST)",
Self::EuropeBerlin => "Berlin (CET/CEST)",
Self::AsiaTokyo => "Tokyo (JST)",
Self::AsiaHongKong => "Hong Kong (HKT)",
Self::AsiaSingapore => "Singapore (SGT)",
Self::AustraliaSydney => "Sydney (AEST/AEDT)",
Self::PacificAuckland => "Auckland (NZST/NZDT)",
}
}
pub fn standard_offset_secs(&self) -> i32 {
match self {
Self::Local => 0, Self::Exchange => 0, Self::UTC => 0,
Self::AmericaNewYork => -5 * 3600, Self::AmericaChicago => -6 * 3600, Self::AmericaDenver => -7 * 3600, Self::AmericaLosAngeles => -8 * 3600, Self::EuropeLondon => 0, Self::EuropeParis => 3600, Self::EuropeBerlin => 3600, Self::AsiaTokyo => 9 * 3600, Self::AsiaHongKong => 8 * 3600, Self::AsiaSingapore => 8 * 3600, Self::AustraliaSydney => 10 * 3600, Self::PacificAuckland => 12 * 3600, }
}
}
impl fmt::Display for Timezone {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[repr(u8)]
pub enum PriceScaleMode {
#[default]
Normal = 0,
Logarithmic = 1,
Percentage = 2,
IndexedTo100 = 3,
}
impl PriceScaleMode {
pub fn all() -> &'static [Self] {
&[
Self::Normal,
Self::Logarithmic,
Self::Percentage,
Self::IndexedTo100,
]
}
pub fn name(&self) -> &'static str {
match self {
Self::Normal => "normal",
Self::Logarithmic => "log",
Self::Percentage => "percentage",
Self::IndexedTo100 => "indexedTo100",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::Normal => "Normal",
Self::Logarithmic => "Logarithmic",
Self::Percentage => "Percentage",
Self::IndexedTo100 => "Indexed to 100",
}
}
}
impl fmt::Display for PriceScaleMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum MagnetMode {
#[default]
Off,
Weak,
Strong,
}
impl MagnetMode {
pub fn all() -> &'static [Self] {
&[Self::Off, Self::Weak, Self::Strong]
}
pub fn name(&self) -> &'static str {
match self {
Self::Off => "off",
Self::Weak => "weak",
Self::Strong => "strong",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::Off => "Off",
Self::Weak => "Weak",
Self::Strong => "Strong",
}
}
pub fn snap_distance_px(&self) -> f32 {
match self {
Self::Off => 0.0,
Self::Weak => 20.0,
Self::Strong => 50.0,
}
}
}
impl fmt::Display for MagnetMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Orientation {
#[default]
Horizontal,
Vertical,
Auto,
}
impl Orientation {
pub fn all() -> &'static [Self] {
&[Self::Horizontal, Self::Vertical, Self::Auto]
}
pub fn name(&self) -> &'static str {
match self {
Self::Horizontal => "horizontal",
Self::Vertical => "vertical",
Self::Auto => "auto",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::Horizontal => "Horizontal",
Self::Vertical => "Vertical",
Self::Auto => "Auto",
}
}
}
impl fmt::Display for Orientation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Size {
XSmall,
Small,
#[default]
Medium,
Large,
XLarge,
Auto,
}
impl Size {
pub fn all() -> &'static [Self] {
&[
Self::XSmall,
Self::Small,
Self::Medium,
Self::Large,
Self::XLarge,
Self::Auto,
]
}
pub fn name(&self) -> &'static str {
match self {
Self::XSmall => "xsmall",
Self::Small => "small",
Self::Medium => "medium",
Self::Large => "large",
Self::XLarge => "xlarge",
Self::Auto => "auto",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::XSmall => "Extra Small",
Self::Small => "Small",
Self::Medium => "Medium",
Self::Large => "Large",
Self::XLarge => "Extra Large",
Self::Auto => "Auto",
}
}
pub fn multiplier(&self) -> f32 {
match self {
Self::XSmall => 0.75,
Self::Small => 0.875,
Self::Medium => 1.0,
Self::Large => 1.25,
Self::XLarge => 1.5,
Self::Auto => 1.0,
}
}
}
impl fmt::Display for Size {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Resolution {
#[default]
M1,
M3,
M5,
M15,
M30,
H1,
H2,
H4,
D1,
W1,
MN1,
}
impl Resolution {
pub fn all() -> &'static [Self] {
&[
Self::M1,
Self::M3,
Self::M5,
Self::M15,
Self::M30,
Self::H1,
Self::H2,
Self::H4,
Self::D1,
Self::W1,
Self::MN1,
]
}
pub fn name(&self) -> &'static str {
match self {
Self::M1 => "1",
Self::M3 => "3",
Self::M5 => "5",
Self::M15 => "15",
Self::M30 => "30",
Self::H1 => "60",
Self::H2 => "120",
Self::H4 => "240",
Self::D1 => "1D",
Self::W1 => "1W",
Self::MN1 => "1M",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::M1 => "1 minute",
Self::M3 => "3 minutes",
Self::M5 => "5 minutes",
Self::M15 => "15 minutes",
Self::M30 => "30 minutes",
Self::H1 => "1 hour",
Self::H2 => "2 hours",
Self::H4 => "4 hours",
Self::D1 => "1 day",
Self::W1 => "1 week",
Self::MN1 => "1 month",
}
}
pub fn seconds(&self) -> u64 {
match self {
Self::M1 => 60,
Self::M3 => 3 * 60,
Self::M5 => 5 * 60,
Self::M15 => 15 * 60,
Self::M30 => 30 * 60,
Self::H1 => 60 * 60,
Self::H2 => 2 * 60 * 60,
Self::H4 => 4 * 60 * 60,
Self::D1 => 24 * 60 * 60,
Self::W1 => 7 * 24 * 60 * 60,
Self::MN1 => 30 * 24 * 60 * 60, }
}
pub fn minutes(&self) -> u32 {
match self {
Self::M1 => 1,
Self::M3 => 3,
Self::M5 => 5,
Self::M15 => 15,
Self::M30 => 30,
Self::H1 => 60,
Self::H2 => 120,
Self::H4 => 240,
Self::D1 => 1440,
Self::W1 => 10080,
Self::MN1 => 43200,
}
}
pub fn is_intraday(&self) -> bool {
matches!(
self,
Self::M1 | Self::M3 | Self::M5 | Self::M15 | Self::M30 | Self::H1 | Self::H2 | Self::H4
)
}
pub fn is_daily_or_higher(&self) -> bool {
matches!(self, Self::D1 | Self::W1 | Self::MN1)
}
}
impl fmt::Display for Resolution {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_name())
}
}
impl TryFrom<&str> for Resolution {
type Error = String;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value {
"1" => Ok(Self::M1),
"3" => Ok(Self::M3),
"5" => Ok(Self::M5),
"15" => Ok(Self::M15),
"30" => Ok(Self::M30),
"60" => Ok(Self::H1),
"120" => Ok(Self::H2),
"240" => Ok(Self::H4),
"1D" => Ok(Self::D1),
"D" => Ok(Self::D1),
"1W" => Ok(Self::W1),
"W" => Ok(Self::W1),
"1M" => Ok(Self::MN1),
"M" => Ok(Self::MN1),
_ => Err(format!("Unknown resolution: {value}")),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum ChartTheme {
#[default]
Light,
Dark,
Auto,
}
impl ChartTheme {
pub fn all() -> &'static [Self] {
&[Self::Light, Self::Dark, Self::Auto]
}
pub fn name(&self) -> &'static str {
match self {
Self::Light => "light",
Self::Dark => "dark",
Self::Auto => "auto",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::Light => "Light",
Self::Dark => "Dark",
Self::Auto => "Auto",
}
}
pub fn is_dark(&self, system_is_dark: bool) -> bool {
match self {
Self::Light => false,
Self::Dark => true,
Self::Auto => system_is_dark,
}
}
}
impl fmt::Display for ChartTheme {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum CrosshairMode {
#[default]
Hidden,
Vertical,
Horizontal,
Both,
}
impl CrosshairMode {
pub fn all() -> &'static [Self] {
&[Self::Hidden, Self::Vertical, Self::Horizontal, Self::Both]
}
pub fn name(&self) -> &'static str {
match self {
Self::Hidden => "hidden",
Self::Vertical => "vertical",
Self::Horizontal => "horizontal",
Self::Both => "both",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::Hidden => "Hidden",
Self::Vertical => "Vertical",
Self::Horizontal => "Horizontal",
Self::Both => "Both",
}
}
}
impl fmt::Display for CrosshairMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum PriceLineSource {
#[default]
Close,
Open,
High,
Low,
Typical,
Median,
OHLC,
WeightedClose,
}
impl PriceLineSource {
pub fn all() -> &'static [Self] {
&[
Self::Close,
Self::Open,
Self::High,
Self::Low,
Self::Typical,
Self::Median,
Self::OHLC,
Self::WeightedClose,
]
}
pub fn name(&self) -> &'static str {
match self {
Self::Close => "close",
Self::Open => "open",
Self::High => "high",
Self::Low => "low",
Self::Typical => "typical",
Self::Median => "median",
Self::OHLC => "ohlc",
Self::WeightedClose => "weighted",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::Close => "Close",
Self::Open => "Open",
Self::High => "High",
Self::Low => "Low",
Self::Typical => "Typical Price",
Self::Median => "Median Price",
Self::OHLC => "OHLC Average",
Self::WeightedClose => "Weighted Close",
}
}
}
impl fmt::Display for PriceLineSource {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum ScaleLocation {
#[default]
Right,
Left,
Both,
None,
}
impl ScaleLocation {
pub fn all() -> &'static [Self] {
&[Self::Right, Self::Left, Self::Both, Self::None]
}
pub fn name(&self) -> &'static str {
match self {
Self::Right => "right",
Self::Left => "left",
Self::Both => "both",
Self::None => "none",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::Right => "Right",
Self::Left => "Left",
Self::Both => "Both",
Self::None => "None",
}
}
}
impl fmt::Display for ScaleLocation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum BackgroundType {
#[default]
Solid,
VerticalGradient,
HorizontalGradient,
Transparent,
}
impl BackgroundType {
pub fn all() -> &'static [Self] {
&[
Self::Solid,
Self::VerticalGradient,
Self::HorizontalGradient,
Self::Transparent,
]
}
pub fn name(&self) -> &'static str {
match self {
Self::Solid => "solid",
Self::VerticalGradient => "gradient_vertical",
Self::HorizontalGradient => "gradient_horizontal",
Self::Transparent => "transparent",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::Solid => "Solid",
Self::VerticalGradient => "Vertical Gradient",
Self::HorizontalGradient => "Horizontal Gradient",
Self::Transparent => "Transparent",
}
}
}
impl fmt::Display for BackgroundType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u8)]
#[derive(Default)]
pub enum ChartStyle {
Bar = 0,
#[default]
Candle = 1,
Line = 2,
Area = 3,
Renko = 4,
Kagi = 5,
PnF = 6,
LineBreak = 7,
HeikinAshi = 8,
HollowCandle = 9,
Baseline = 10,
HighLow = 12,
Column = 13,
LineWithMarkers = 14,
Stepline = 15,
HLCArea = 16,
VolCandle = 19,
HLCBars = 21,
}
impl ChartStyle {
pub fn tv_value(&self) -> u8 {
*self as u8
}
pub fn requires_parameters(&self) -> bool {
matches!(
self,
Self::Renko | Self::Kagi | Self::PnF | Self::LineBreak | Self::Baseline
)
}
pub fn tv_id(&self) -> &'static str {
match self {
Self::Bar => "Bar",
Self::Candle => "Candle",
Self::Line => "Line",
Self::Area => "Area",
Self::Renko => "Renko",
Self::Kagi => "Kagi",
Self::PnF => "PnF",
Self::LineBreak => "LineBreak",
Self::HeikinAshi => "HeikinAshi",
Self::HollowCandle => "HollowCandle",
Self::Baseline => "Baseline",
Self::HighLow => "HiLo",
Self::Column => "Column",
Self::LineWithMarkers => "LineWithMarkers",
Self::Stepline => "Stepline",
Self::HLCArea => "HLCArea",
Self::VolCandle => "VolCandle",
Self::HLCBars => "HLCBars",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::Bar => "Bars",
Self::Candle => "Candles",
Self::Line => "Line",
Self::Area => "Area",
Self::Renko => "Renko",
Self::Kagi => "Kagi",
Self::PnF => "Point & Figure",
Self::LineBreak => "Line Break",
Self::HeikinAshi => "Heikin Ashi",
Self::HollowCandle => "Hollow Candles",
Self::Baseline => "Baseline",
Self::HighLow => "High-Low",
Self::Column => "Column",
Self::LineWithMarkers => "Line with Markers",
Self::Stepline => "Step Line",
Self::HLCArea => "HLC Area",
Self::VolCandle => "Volume Candles",
Self::HLCBars => "HLC Bars",
}
}
pub fn all() -> &'static [ChartStyle] {
&[
Self::Bar,
Self::Candle,
Self::Line,
Self::Area,
Self::Renko,
Self::Kagi,
Self::PnF,
Self::LineBreak,
Self::HeikinAshi,
Self::HollowCandle,
Self::Baseline,
Self::HighLow,
Self::Column,
Self::LineWithMarkers,
Self::Stepline,
Self::HLCArea,
Self::VolCandle,
Self::HLCBars,
]
}
}
impl fmt::Display for ChartStyle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_name())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChartStyleParameters {
pub renko_brick_size: Option<f64>,
pub kagi_reversal: Option<f64>,
pub range_bar_size: Option<f64>,
pub pnf_box_size: Option<f64>,
pub pnf_reversal: Option<u32>,
pub line_break_count: Option<u32>,
pub baseline_level: Option<f64>,
}
impl Default for ChartStyleParameters {
fn default() -> Self {
Self {
renko_brick_size: Some(1.0),
kagi_reversal: Some(1.0),
range_bar_size: Some(10.0),
pnf_box_size: Some(1.0),
pnf_reversal: Some(3),
line_break_count: Some(3),
baseline_level: None,
}
}
}
impl ChartStyleParameters {
pub fn validate(&self, style: ChartStyle) -> Result<(), String> {
match style {
ChartStyle::Renko => {
if self.renko_brick_size.is_none_or(|s| s <= 0.0) {
return Err("Renko brick size must be positive".to_string());
}
}
ChartStyle::Kagi => {
if self.kagi_reversal.is_none_or(|r| r <= 0.0) {
return Err("Kagi reversal must be positive".to_string());
}
}
ChartStyle::PnF if self.pnf_box_size.is_none_or(|s| s <= 0.0) => {
return Err("Point & Figure box size must be positive".to_string());
}
_ => {}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_line_style_pattern() {
assert_eq!(LineStyle::Solid.pattern(), vec![f32::MAX]);
assert_eq!(LineStyle::Dotted.pattern(), vec![2.0, 4.0]);
assert_eq!(LineStyle::Dashed.pattern(), vec![10.0, 5.0]);
}
#[test]
fn test_resolution_seconds() {
assert_eq!(Resolution::M1.seconds(), 60);
assert_eq!(Resolution::H1.seconds(), 3600);
assert_eq!(Resolution::D1.seconds(), 86400);
}
#[test]
fn test_resolution_parse() {
assert_eq!(Resolution::try_from("5").unwrap(), Resolution::M5);
assert_eq!(Resolution::try_from("1D").unwrap(), Resolution::D1);
assert!(Resolution::try_from("invalid").is_err());
}
#[test]
fn test_chart_theme_is_dark() {
assert!(!ChartTheme::Light.is_dark(true));
assert!(ChartTheme::Dark.is_dark(false));
assert!(ChartTheme::Auto.is_dark(true));
}
#[test]
fn test_price_line_source_all() {
assert_eq!(PriceLineSource::all().len(), 8);
}
#[test]
fn test_magnet_mode_distance() {
assert_eq!(MagnetMode::Off.snap_distance_px(), 0.0);
assert!(MagnetMode::Strong.snap_distance_px() > MagnetMode::Weak.snap_distance_px());
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
pub enum ColorType {
#[default]
Hex,
Rgb,
Rgba,
Named,
}
impl ColorType {
pub fn all() -> &'static [Self] {
&[Self::Hex, Self::Rgb, Self::Rgba, Self::Named]
}
pub fn name(&self) -> &'static str {
match self {
Self::Hex => "hex",
Self::Rgb => "rgb",
Self::Rgba => "rgba",
Self::Named => "named",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
pub enum OverrideLineStyle {
#[default]
Solid,
Dashed,
Dotted,
LargeDashed,
SparseDotted,
}
impl OverrideLineStyle {
pub fn all() -> &'static [Self] {
&[
Self::Solid,
Self::Dashed,
Self::Dotted,
Self::LargeDashed,
Self::SparseDotted,
]
}
pub fn name(&self) -> &'static str {
match self {
Self::Solid => "solid",
Self::Dashed => "dashed",
Self::Dotted => "dotted",
Self::LargeDashed => "large_dashed",
Self::SparseDotted => "sparse_dotted",
}
}
pub fn tv_value(&self) -> i32 {
match self {
Self::Solid => 0,
Self::Dashed => 1,
Self::Dotted => 2,
Self::LargeDashed => 3,
Self::SparseDotted => 4,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
pub enum OverridePriceAxisLastValueMode {
#[default]
LastValue,
LastValueHidden,
LastValueAndPreviousClose,
}
impl OverridePriceAxisLastValueMode {
pub fn all() -> &'static [Self] {
&[
Self::LastValue,
Self::LastValueHidden,
Self::LastValueAndPreviousClose,
]
}
pub fn name(&self) -> &'static str {
match self {
Self::LastValue => "last_value",
Self::LastValueHidden => "last_value_hidden",
Self::LastValueAndPreviousClose => "last_value_and_previous_close",
}
}
pub fn tv_value(&self) -> i32 {
match self {
Self::LastValue => 0,
Self::LastValueHidden => 1,
Self::LastValueAndPreviousClose => 2,
}
}
}