Страницы: 1 2 След.
RSS
Выбор МАКС и МИН из меняющегося диапазона значений, Нахождение максимального и минимального значения котировок из дневной и вечерней сессии
 
Всем, здравствуйте!
Имеются котировки значений  с интервалом 5 минут на большое количество дней. Каждый день делится 2 сессии на дневную, которая начинается ближе к 09:00 и до 19:00 и на вечерняя с 19:00 до 23:50. В некоторые дни вечерней сессии нет, а в некоторых днях дневная может начинаться ближе к 10:00.

Требуется по каждой сессии из соответствующих колонок выбрать по одному значению:
  • первое значение открытия (колонка <OPEN>)
  • максимальное (<HIGH>)
  • минимальное (<LOW>)
  • последнее значение закрытия (<CLOSE>).
Первое и последнее значение по каждой сессии мне получилось выбрать, а вот выбрать максимальное и минимальное значение каждой сессии пока не получается.
Функции ИНДЕКС, ПОИСКПОЗ, СМЕЩ не могу правильно собрать или может есть еще другой вариант.
Помогите пожалуйста составить формулу. Файл с котировками
 
в свежем Excel есть Минесли() и Максесли()
 
Не все могут качать с Я-диска. Если файл большой - можно его обрезать до приемлимых размеров и положить сюда
Скажи мне, кудесник, любимец ба’гов...
 
Может Сводной подойдет?
Оставил данные за пару дней. Думаю для понимания будет достаточно
Изменено: Sanja - 09.12.2025 18:44:28
Согласие есть продукт при полном непротивлении сторон
 
Цитата
написал:
Если файл большой - можно его обрезать до приемлимых размеров и положить сюда
приложил обрезанный файл
 
Можно добавить название сессии. Формула в ячейке 'H2' и вниз
Код
=ЕСЛИ(И(B2>=80000;B2<=190000);"дневная";"вечерняя")
Изменено: Sanja - 09.12.2025 19:22:39
Согласие есть продукт при полном непротивлении сторон
 
Цитата
написал:
Сводной подойдет
Мне надо по другому.
Нужно всего 4 значения за одну сессию, т.е. за один календарный день 4 значения по дневной сессии и 4 значения по вечерней сессии:
1) первое значение (<OPEN>) открытия с начала сессии;
2) максимальное значение из столбца <HIGH> за всю сессию (например дневная сессия это на 18.09.2025 это с 8:55:00 по 18:45:00);
3) минимальное значение из столбца <LOW> за всю сессию;
4) последнее значение (<CLOSE>)на закрытии сессии.
 
Sanja, очень интересно, надо это вариант проработать
 
power query market data
Пришелец-прораб.
 
Еще вариант современными формулами (2021+). Выбирайте Дату в вып.списке. Данные для Списка дат в ячейке 'J2'
Согласие есть продукт при полном непротивлении сторон
 
Цитата
написал:
power query market data
Спасибо, красиво получилось, но мне непонятно как это сделано.
Предполагаю, что написан макрос.
Эту тему предстоит еще изучить.
 
Цитата
написал:
Выбирайте Дату в вып.списке.
Спасибо хороший вариант, но не совсем то, что нужно.
Мне из всего этого массива данных необходимо выбрать сразу все нужные значения и перенести в другой файл, т.е. не смотреть отдельно каждый день, а сразу вычленить значения по всем дням.
Предыдущее решение с помощью сводной таблицы и введением дополнительной колонки по сессиям как будто решает задачу.
Сейчас буду копать в этом направлении.  
 
Цитата
написал:
Предполагаю, что написан макрос.
Это Power Query
 
Цитата
написал:
Можно добавить название сессии.
Начал пробовать применять сводную таблицу, но столкнулся с такой проблемой.

Как вычленить первое значение из колонки открытие и последнее значение из колонки закрытие по каждой сессии?
Как сделать так, чтобы значения по каждой сессии одного дня были в одной строке?

В конечном итоге мне нужны данные в виде, как представлено в файле "Результат".  
 
Здравствуйте.
Вариант формулами в файле.
 
Вариант макросами.
Код
Option Explicit

Sub Лист_в_умную()
    CloseEmptyWb
    
    Dim sh As Worksheet
    If Cells(1, 1).Value = "<DATE>" Then
        Set sh = ActiveSheet
    Else
        Dim si As Worksheet
        For Each si In ActiveWorkbook.Worksheets
            If si.Cells(1, 1).Value = "<DATE>" Then
                Set sh = si
                GoTo ExitFor
            End If
        Next
        If sh Is Nothing Then
            Dim wb As Workbook
            For Each wb In Application.Workbooks
                For Each si In wb.Worksheets
                    If si.Cells(1, 1).Value = "<DATE>" Then
                        Set sh = si
                        GoTo ExitFor
                    End If
                Next
            Next
        End If
    End If
ExitFor:
    
    MakeListObjectFromPivotSheet sh
End Sub

Sub Сводную_в_умную()
    CloseEmptyWb
    
    Dim pt As PivotTable
    On Error Resume Next
    Set pt = ActiveSheet.PivotTables(1)
    If pt Is Nothing Then
        Dim wb As Workbook
        For Each wb In Application.Workbooks
            wb.Activate
            Set pt = ActiveSheet.PivotTables(1)
            If Not pt Is Nothing Then Exit For
        Next
    End If
    On Error GoTo 0
    
    MakeListObjectFromPivotTable pt
End Sub

Private Sub MakeListObjectFromPivotSheet(sh As Worksheet)
    Dim arr As Variant
    arr = GetArrFromSheet(sh)
    
    PrintArr arr, Workbooks.Add(1).Sheets(1).Cells(1, 1)
End Sub

Private Sub MakeListObjectFromPivotTable(pt As PivotTable)
    Dim arr As Variant
    arr = GetArr(pt)
    
    PrintArr arr, Workbooks.Add(1).Sheets(1).Cells(1, 1)
End Sub

Private Function GetArrFromSheet(sh As Worksheet) As Variant
    Dim arr As Variant
    arr = Intersect(sh.Columns("A:F"), sh.UsedRange).Value
    
    Dim dic As Object
    Set dic = GetDic(arr)
    If dic.Count = 0 Then Exit Function
    
    Dim yd As Long, yb As Long, sm As Long, yt As Long, xs As Long, xf As Long
    Dim brr As Variant, frr As Variant
    brr = dic.Items()(0).Items()(0).Items()(0)
    ReDim arr(1 To dic.Count + 1, 1 To 1 + 2 * (3 + UBound(brr) + 1))
    
    brr = Split("Дата,Сессия,Начало,Окончание,Открытие,Максимум,Минимум,Закрытие,Сессия 2,Начало 3,Окончание 4,Открытие 5,Максимум 6,Минимум 7,Закрытие 8", ",")
    For xs = 1 To UBound(brr)
        arr(1, xs) = brr(xs - 1)
    Next
    brr = Empty
    
    Dim bic As Object, cic As Object
    For yd = 0 To dic.Count - 1
        Set bic = dic.Items()(yd)
        For sm = 0 To bic.Count - 1
            Set cic = bic.Items()(sm)
            frr = cic.Items()(0)
            For yt = 1 To cic.Count - 1
                brr = cic.Items()(yt)
                
                If frr(1) < brr(1) Then frr(1) = brr(1)
                If frr(2) > brr(2) Then frr(2) = brr(2)
                frr(3) = brr(3)
            Next
            If bic.Keys()(sm) = "Дневная" Then
                xs = 2
            ElseIf bic.Keys()(sm) = "Вечерняя" Then
                xs = 2 + 3 + UBound(frr) + 1
            End If
            For xf = 0 To UBound(frr)
                arr(2 + yd, xs + xf + 3) = frr(xf)
            Next
            
            arr(2 + yd, xs + 1) = bic.Items()(sm).Keys()(0)
            arr(2 + yd, xs + 2) = bic.Items()(sm).Keys()(cic.Count - 1)
            arr(2 + yd, xs) = bic.Keys()(sm)
        Next
        arr(2 + yd, 1) = dic.Keys()(yd)
    Next
    GetArrFromSheet = arr
End Function

Private Function GetDic(arr As Variant) As Object
    Dim dic As Object
    Set dic = CreateObject("Scripting.Dictionary")
    
    Dim ya As Long, ss As String, dt As Date, tt As Date
    For ya = 2 To UBound(arr, 1)
        If IsNumeric(arr(ya, 1)) Then
            If IsNumeric(arr(ya, 2)) Then
                dt = 0
                tt = 0
                On Error Resume Next
                ss = Left(arr(ya, 1), 4) & "." & Mid(arr(ya, 1), 5, 2) & "." & Mid(arr(ya, 1), 7, 2)
                dt = DateValue(ss)
                ss = Left(arr(ya, 2), Len(arr(ya, 2)) - 4) & ":" & Mid(arr(ya, 2), Len(arr(ya, 2)) - 3, 2) & ":" & Right(arr(ya, 2), 2)
                tt = TimeValue(ss)
                On Error GoTo 0
                If dt > 0 And tt > 0 Then
                    If arr(ya, 2) >= 60000 And arr(ya, 2) < 190000 Then
                        ss = "Дневная"
                    Else
                        ss = "Вечерняя"
                    End If
                    If Not dic.Exists(dt) Then
                        Set dic(dt) = CreateObject("Scripting.Dictionary")
                    End If
                    If Not dic(dt).Exists(ss) Then
                        Set dic(dt)(ss) = CreateObject("Scripting.Dictionary")
                    End If
                    dic(dt)(ss)(tt) = Array(arr(ya, 3), arr(ya, 4), arr(ya, 5), arr(ya, 6))
                End If
            End If
        End If
    Next
    Set GetDic = dic
End Function

Private Function GetArr(pt As PivotTable) As Variant
    Dim arr As Variant, brr As Variant, ya As Long, yb As Long, xa As Long, xb As Long
    arr = pt.TableRange1.Value
    ReDim brr(1 To UBound(arr, 1), 1 To 2 * (UBound(arr, 2) - 1) + 1)
    
    Dim hrr As Variant
    hrr = Split("Дата Сессия Начало Окончание Открытие Максимум Минимум Закрытие Сессия2 Начало3 Окончание4 Открытие5 Максимум6 Минимум7 Закрытие8", " ")
    For xb = 1 To UBound(brr, 2)
        brr(1, xb) = hrr(xb - 1)
    Next
    
    yb = 1
    For ya = 2 To UBound(arr, 1)
        If Not IsEmpty(arr(ya, 1)) Then
            yb = yb + 1
            xb = 1
            brr(yb, xb) = arr(ya, 1)
            For xa = 2 To UBound(arr, 2)
                xb = xb + 1
                brr(yb, xb) = arr(ya, xa)
            Next
            If ya < UBound(arr, 1) Then
                If IsEmpty(arr(ya + 1, 1)) Then
                    For xa = 2 To UBound(arr, 2)
                        xb = xb + 1
                        brr(yb, xb) = arr(ya + 1, xa)
                    Next
                End If
            End If
        End If
    Next
    brr = ResizeArray(brr, yb)
    
    GetArr = brr
End Function

Private Function ResizeArray(arr, yNew As Long) As Variant
    Dim brr As Variant
    ReDim brr(1 To yNew, 1 To UBound(arr, 2))
    Dim yb As Long, xb As Long
    For yb = 1 To UBound(brr, 1)
    For xb = 1 To UBound(brr, 2)
        brr(yb, xb) = arr(yb, xb)
    Next
    Next
    ResizeArray = brr
End Function

Private Sub PrintArr(arr As Variant, rTarg As Range)
    Set rTarg = rTarg.Resize(UBound(arr, 1), UBound(arr, 2))
    rTarg.Value = arr
    
    Dim xx As Long, dx As Long
    dx = (rTarg.Columns.Count - 3) / 2 + 1
    For xx = 3 To 4
        rTarg.Columns(xx).NumberFormat = "hh:mm:ss;@"
        rTarg.Columns(xx + dx).NumberFormat = "hh:mm:ss;@"
    Next
    For xx = 5 To (rTarg.Columns.Count - 1) / 2 + 1
        rTarg.Columns(xx).NumberFormat = "#,##0"
        rTarg.Columns(xx + dx).NumberFormat = "#,##0"
    Next
    
    Dim sh As Worksheet
    Set sh = rTarg.Parent
    With sh.ListObjects.Add(xlSrcRange, rTarg, , xlYes)
        .Name = "Таблица1"
        .TableStyle = "TableStyleMedium2"
    End With
    Dim tb As ListObject
    Set tb = sh.ListObjects(1)
    rTarg.HorizontalAlignment = xlCenter
    rTarg.EntireColumn.AutoFit
    
'    Workbooks("Результат.xlsx").Sheets(1).UsedRange.Copy rTarg.Cells(rTarg.Rows.Count + 2, 1)
    
    sh.Parent.Saved = True
End Sub

Private Sub CloseEmptyWb()
    Dim wb As Workbook
    For Each wb In Application.Workbooks
        If wb.Path = "" Then wb.Close False
    Next
End Sub

 
Если делать это формулами на большом объёме данных, то лучше, полагаю, менее ресурсоёмким способом
как вариант в файле
 
Цитата
написал:
как вариант в файле
Спасибо за вариант, но вставил побольше данных, и в некоторых ячейках возникли локальные проблемы.
Не понял почему, но во вспомогательных столбцах номера начало вечерней сессии и конец дневной сессии на 6 день выдает некорректно, из-за это неправильные значения МАКС и МИН.
Также есть дни, у которых нет вечерней сессии.
Выделил желтым цветом проблемные ячейки.
Можете прокомментировать?
 
 
Цитата
написал:
Вариант макросами
Спасибо, с макросами не дружу, это направление предстоит освоить.
 
Цитата
написал:
Вариант формулами в файле.
Спасибо, сделано так как надо.
Два дня разбирался, в помощь ИИ использовал, все равно толком не понял как формулы работают)))
Использую так сказать как "черный ящик")))
Может позже понимание придет))
 
Можно не создавать доп столбец Сессий (Дневная/Вечерняя) на исходном листе. Лишнее прописал, в файле убрал.
Цитата
Два дня разбирался, в помощь ИИ
В Excel есть возможность просмотреть пошаговую работу формул, на вкладке Формулы -- Вычислить формулу. Активируете ячейку с формулой и жмёте Вычислить формулу, и видите поэтапно как формула считает. Только чтобы понять, не нужны такие большие диапазоны как у вас ($B$1:$B$1943), достаточно уменьшить до 10-15 строк, и можно в каждой сессии оставить по 3-4 строки с данными, остальные строки в исходнике  удалить. Тогда просмотр работы будет более удобным.
Изменено: gling - 12.12.2025 22:21:30
 
Цитата
написал:
Лишнее прописал, в файле убрал.
Спасибо, понял.
Исходные данные могут быть намного больше до 50 000 строк
В файле примера данные заканчиваются на строке 1943 и поэтому у вас в формулах просматриваемый диапазон до 1943.
Что можете посоветовать при увеличении данных?
Просто в формулах поменять диапазон строк с 1943 на 50000 ?
Изменено: Mark17 - 12.12.2025 22:29:20
 
Цитата
написал:
жмёте Вычислить формулу
да, так и делал, пошагово смотрел, все равно не понял,

а вот: уменьшить до 10-15 строк, и можно в каждой сессии оставить по 3-4 строки с данными, остальные строки в исходнике  удалить.

как-то не догадался, надо попробовать))), спасибо
Изменено: Mark17 - 12.12.2025 22:34:00
 
Цитата
написал:
Просто в формулах поменять диапазон
Да. Можно даже через Найти/Заменить. Но не знаю как будут формулы считать на таких объёмах. Если будет долго считать, тогда лучше этот файл открывать отдельно, при закрытых других файлах Excel.
 
Цитата
написал:
Если будет долго считат', тогда лучше етот файл открыват' отдел'но, при закрытых других файлах Еxцел.
Хорошо, буду учитывать.
Жму руку!
 
Цитата
Mark17:  вставил побольше данных, и в некоторых ячейках возникли локальные проблемы
Можете прокомментировать?
Mark17,   Могу: похорошему дать вам ешё времени чтоб самому разобраться))
перетащите ячейку I1 в J2 например
...есть там ещё незначительные некорректности, надеюс сами догадаетесь как подкорректировать?
Если версия эксель позваляет, то результат можно получить динамическими массивами ...или одним)
например даты можно получить отсюда:
=УНИК(A2:A1943)
 
Цитата
написал:
надеюс сами догадаетесь как подкорректировать?
Павел, большое спасибо за помощь и за вариант решения.
Конечно буду сам разбираться.
Еще надо подумать как например вычленять значения первой и последней 5-минутке в каждой сессии.
 
Mark17, пожалуйста
Цитата
как например вычленять значения первой и последней 5-минутке в каждой сессии
ну, номер позиции открытия/закрытия у вас уже есть
+/-  к ней сикока надо  ;-)  
 
Цитата
Mark17 написал:
Исходные данные могут быть намного больше до 50 000 строк
Что можете посоветовать при увеличении данных?
Я бы советовал все таки макросы на таких объемах
Скрытый текст

или те, что предлагали ранее
В файле по ссылке собрал свои решения на полных данных (вкл.Сводную, но без данных Открытия и Закрытия). Формулы уже заметно тормозят и на этом объеме
Согласие есть продукт при полном непротивлении сторон
 
Цитата
написал:
перетащите ячейку I1 в J2 например
Сделал.
Наконец разобрался как все устроено, некорректности исправил.
Выборки делает шустро.
Спасибо.
Страницы: 1 2 След.
Читают тему
Наверх