43 const auto chart = cal::parse_timeframe(chart_tf);
44 if (!chart || !chart->valid())
return {};
45 std::int64_t seconds = 0;
46 switch (chart->unit()) {
47 case cal::TimeframeUnit::Second: seconds = chart->count();
break;
48 case cal::TimeframeUnit::Minute: seconds = std::int64_t{chart->count()} * 60;
break;
49 case cal::TimeframeUnit::Day: seconds = std::int64_t{chart->count()} * 86400;
break;
50 case cal::TimeframeUnit::Week:
51 case cal::TimeframeUnit::Month:
54 constexpr std::int64_t kMinute = 60;
55 constexpr std::int64_t kDay = 1440 * kMinute;
56 if (seconds < 30)
return "1S";
57 if (seconds < kMinute)
return "5S";
58 if (seconds < 5 * kMinute)
return "10S";
59 if (seconds < 10 * kMinute)
return "30S";
60 if (seconds < 15 * kMinute)
return "1";
61 if (seconds < 30 * kMinute)
return "2";
62 if (seconds < 60 * kMinute)
return "5";
63 if (seconds < 240 * kMinute)
return "10";
64 if (seconds < kDay)
return "30";
65 if (seconds < 3 * kDay)
return "60";
66 if (seconds < 7 * kDay)
return "240";
71 const std::string& input_tf,
72 const std::string& script_tf,
73 const std::string& session,
74 const std::string& timezone) {
75 std::vector<Bar> unchanged;
76 if (!bars || n <= 0)
return unchanged;
77 unchanged.assign(bars, bars + n);
79 const auto input = cal::parse_timeframe(input_tf);
80 const auto chart = cal::parse_timeframe(script_tf);
82 if (!
input || !chart || !intrabar)
return unchanged;
87 const std::int64_t input_ms = fixed_ms(*
input);
88 const std::int64_t intrabar_ms = fixed_ms(*intrabar);
89 if (input_ms <= 0)
return unchanged;
90 if (intrabar_ms != 0 && (intrabar_ms <= input_ms || intrabar_ms % input_ms != 0))
92 for (
int i = 1; i < n; ++i) {
93 if (bars[i].timestamp <= bars[i - 1].timestamp)
return unchanged;
95 const auto calendar = cal::parse_session(session, timezone);
96 if (!calendar)
return unchanged;
97 cal::SessionDayMemo memo;
102 struct Row { std::int64_t chart_open; std::int64_t slot_open; std::int64_t owner_open; };
103 std::vector<Row> rows(
static_cast<std::size_t
>(n));
104 std::optional<cal::NativeInterval> chart_at, slot_at, owner_at;
105 for (
int i = 0; i < n; ++i) {
106 const std::int64_t t = bars[i].
timestamp;
107 if (!chart_at || t < chart_at->open_ms || t >= chart_at->next_period_open_ms) {
108 chart_at = cal::interval_containing(*calendar, *chart, t, memo);
109 if (!chart_at)
return unchanged;
111 if (!slot_at || t < slot_at->open_ms || t >= slot_at->next_period_open_ms) {
112 slot_at = cal::interval_containing(*calendar, *intrabar, t, memo);
113 if (!slot_at || slot_at->last_traded_close_ms <= slot_at->open_ms)
return unchanged;
114 owner_at = cal::interval_containing(*calendar, *chart,
115 slot_at->last_traded_close_ms - 1, memo);
116 if (!owner_at)
return unchanged;
118 rows[
static_cast<std::size_t
>(i)] = {chart_at->open_ms, slot_at->open_ms, owner_at->open_ms};
124 struct Span { std::int64_t key; std::int64_t owner;
int first;
int last; };
125 std::vector<Span> charts, slots;
126 for (
int i = 0; i < n; ++i) {
127 const auto& row = rows[
static_cast<std::size_t
>(i)];
128 if (charts.empty() || charts.back().key != row.chart_open)
129 charts.push_back({row.chart_open, row.chart_open, i, i});
131 charts.back().last = i;
132 if (slots.empty() || slots.back().key != row.slot_open)
133 slots.push_back({row.slot_open, row.owner_open, i, i});
135 slots.back().last = i;
138 std::vector<Bar> path;
139 path.reserve(slots.size() + 2 * charts.size());
140 std::size_t slot = 0;
141 for (
const auto& bar : charts) {
144 while (slot < slots.size() && slots[slot].owner < bar.key) ++slot;
145 const std::size_t owned_begin = slot;
146 while (slot < slots.size() && slots[slot].owner == bar.key) ++slot;
147 if (owned_begin == slot)
continue;
148 const Bar& chart_first = bars[bar.first];
149 const Bar& chart_last = bars[bar.last];
150 std::int64_t floor = chart_first.
timestamp;
151 if (slots[owned_begin].first < bar.first) {
155 path.push_back(one_price(chart_first.
open, floor));
158 for (std::size_t s = owned_begin; s < slot; ++s) {
159 const Span& span = slots[s];
160 Bar intrabar = bars[span.first];
161 for (
int i = span.first + 1; i <= span.last; ++i) {
163 intrabar.
low = std::min(intrabar.
low, bars[i].
low);
169 path.push_back(intrabar);
171 if (slots[slot - 1].last < bar.last) {
174 path.push_back(one_price(chart_last.
close, std::max(chart_last.
timestamp, floor)));
std::vector< Bar > tradingview_magnifier_bars(const Bar *bars, int n, const std::string &input_tf, const std::string &script_tf, const std::string &session, const std::string &timezone)
The lower-timeframe path TradingView's bar magnifier walks for every chart bar of a run whose chart b...