сортировка двумерного массива по второму измерению

 

У меня есть 2 части данных, которые мне нужно поместить в массив, а затем отсортировать его.

Сначала я разделяю ордера на два массива: первый массив - для покупок, второй - для продаж. Когда я это делаю, я собираю OrderTicket, чтобы позже я мог выполнить исполнение ордера. Второе, что я собираю, это значение OrderClosePrice ордера, чтобы я мог сравнить его с другим точно таким же списком.

Итак, первый массив, который я создал:

double AryBuys[][2];
double ArySells[][2];

AryBuy[1][0] содержит билет, AryBuy[1][1] содержит цену.

Как отсортировать второе измерение, чтобы массив был отсортирован по цене по убыванию?

Примечание: с помощью ArraySort можно отсортировать только первое измерение. Вот возможная идея, я могу создать временный массив и сделать цену первым измерением во временном массиве, отсортировать его, затем передать его обратно в массив и сделать то же самое в обратном порядке, когда мне позже понадобится отсортировать его по билетам. Это сработает?

 

к сожалению, нельзя, но вы можете создать второй массив, в котором данные из двух измерений поменяются местами, и отсортировать этот новый массив по цене (первое измерение). Затем (если вы все еще хотите) вы можете скопировать данные обратно в исходный массив, снова поменяв местами данные в каждом измерении. Теперь ваш исходный массив содержит исходные данные, но отсортированные по значениям второго измерения.

Это сложно, но это единственный практический способ (который я смог понять) получить данные, отсортированные по размерности >1.

 

Это то, о чем я думал в своих заметках. Меня беспокоило то, что первое измерение будет отсортировано, будет ли оно также переставлять второе измерение данных, когда произойдет сортировка? Думаю, я могу создать тест, чтобы проверить это.

 
LEHayes wrote >>

Это то, о чем я думал в своих заметках. Меня беспокоило то, что первое измерение будет отсортировано, будет ли оно также переставлять второе измерение данных, когда произойдет сортировка? Думаю, я могу создать тест, чтобы проверить это.


Да, все элементы с одинаковым базовым индексом перемещаются при сортировке по первому измерению. Подобно сортировке электронной таблицы, содержащей несколько столбцов данных, только в MQL вы можете сортировать только по первому столбцу.
 

Пока что я настроил все так, как мы обсуждали. Я уверен, что к моменту завершения разговора я разберусь с этим, но в настоящее время получаю:
2010.04.15 23:51:01,M1: неверная стартовая позиция 1 для функции ArraySort
Сначала я попробовал так:
ArraySort(AryBuy,WHOLE_ARRAY,0,MODE_DESCEND);
и получил то же сообщение, только значение позиции было 0, затем я изменил начало (значение позиции) на 1, чтобы посмотреть, что может произойти, и получил то, что описано выше.

На данный момент в массивах должны быть данные. Я собираюсь перезапустить тест и посмотреть, сохранится ли проблема.

 
LEHayes:

.....
double AryBuys[][2];
double ArySells[][2];

AryBuy[1][0] содержит билет, AryBuy[1][1] содержит цену. ....

Поправьте меня, если я ошибаюсь, но, похоже, вы неправильно определяете и адресуете массив. Цитирую из ссылки на переменную:

int    a[50];       // A one-dimensional array of 50 integers.
double m[7][50];    // Two-dimensional array of seven arrays,
                    //each of them consisting of 50 integers

последняя пара скобок - это первое измерение массива... предполагая, что неопределенный размер массива - это первое измерение. IMO это правильное определение:

double AryBuys[2][];
double ArySells[2][];

AryBuy[0][1] contains the ticket, AryBuy[1][1] contains the price. 
 
cameofx:
последняя пара скобок является первым измерением массива... предполагая, что неопределенный размер массива является первым измерением. IMO это правильный вариант:

См. также книгу...
К вашему сведению, мне удобнее называть последнюю пару скобок "первым измерением", потому что следующее измерение добавляется (хотя и расположено левее) "позже".
ИМХО Переименование ее в "размер столбцов" также лучше "вписывается" в концепцию.

 
cameofx:

К вашему сведению, мне удобнее называть последнюю пару скобок "первым измерением", потому что следующее измерение добавляется (хотя и расположено левее) "позже".

Независимо от того, как вы хотите это назвать, первым измерением в двумерном массиве является вектор arr_name[0,1,...,n][0], поэтому технически первая скобка содержит первое измерение; это также вектор, который будет отсортирован с помощью ArraySort(). Из книги:

Раз уж мы затронули тему ArraySort(), я упомяну две недокументированные особенности, которые я обнаружил со временем (и буду рад, если кто-нибудь подтвердит или поправит меня...?):

  1. Если некоторые элементы в первом измерении идентичны, они не обязательно сохранят свой порядок. Очевидно, это должно быть задокументировано, если это "по проекту", иначе я бы считал это "ошибкой".
  2. OrderSort() не работает с 4D массивами (возвращает ошибку 4053). Опять же, это должно быть задокументировано, но этого нет.
 
cameofx wrote >>

Поправьте меня, если я ошибаюсь, но, похоже, вы неправильно определяете и адресуете массив. Цитирую из справочника переменных:

последняя пара скобок - это первое измерение массива... предполагая, что неопределенный размер массива - это первое измерение. IMO это правильно:



Я смотрю на индексацию и размерность массива в стандартной манере электронных таблиц... Строка-столбец (мнемоника "римско-католическая").

Одномерный массив: MyArray[RowNumber-1].

2D массив: MyArray[RowNumber-1][ColumnNumber-1]

3D массив: MyArray[RowNumber-1][ColumnNumber-1][Worksheet-1].

Самый левый набор скобок - это первое измерение, все, что вы делаете с массивом первого измерения, будет делаться с индексом самого левого набора скобок. Например, изменение размера массива (то, что можно сделать только с 1-м измерением) изменяет только значение крайнего левого набора скобок, оно не может изменить диапазон индексов второго, третьего или четвертого измерений (второй, третий или четвертый крайний правый набор скобок).

Все мои строки данных в массиве индексируются первым набором скобок, самым левым набором, и это "первое измерение" массива.

MyArray[0][ColumnNumber-1] -> первый ряд данных

MyArray[1][ColumnNumber-1] -> вторая строка данных

MyArray[2][ColumnNumber-1] -> третий ряд данных

В MQL я могу сортировать только по данным, содержащимся в первом столбце данных... то есть по значениям, найденным в MyArray[i][0]. Значения, находящиеся в одной и той же строке (в данном случае в одной и той же "i"), но в разных столбцах (значения во втором наборе скобок), не могут быть использованы для сортировки/ранжирования.

Вот пример двумерного массива:

3 5
1 9
7 6

Итак, MyArray[0][0] = 3, а MyArray[0][1] = 5, а MyArray[2][1] = 6 и т.д.

Я могу отсортировать этот массив:

ArraySort(MyArray,WHOLE_ARRAY,0,MODE_ASCEND) и результат будет следующим:

1 9
3 5
7 6

Первый столбец отсортирован, второй столбец данных (т.е. все данные с одинаковым индексом первого измерения) перемещается вместе с сортировкой/сдвигом, выполненным при ранжировании первого столбца.

Я не могу отсортировать/ранжировать второй столбец данных в MQL... то есть я НЕ МОГУ получить следующее (не напрямую, во всяком случае):

3 5
7 6
1 9

(обратите внимание, что второй столбец теперь отсортирован от наименьшего к наибольшему).

Чтобы получить массив, в котором второй столбец (или любой другой столбец, кроме первого) отсортирован, я должен вручную поменять данные между столбцами (сохраняя индекс первого измерения прежним, но меняя местами значение индекса второго измерения), затем отсортировать и снова поменять данные местами.

MyNewArray:
5 3
9 1
6 7

Теперь отсортируйте по первому столбцу, ArraySort(MyNewArray,WHOLE_ARRAY,0,MODE_ASCEND) и результат будет следующим:

5 3
6 7
9 1

Затем скопируйте значения обратно в мой исходный массив, снова транспонируя индекс второго измерения, сохраняя значение первого измерения прежним:

3 5
7 6
1 9

Теперь у меня есть исходный массив, но данные отсортированы по второму столбцу.

 

Эта затея превратилась в кошмар, я даже не помню, пытался ли я продолжить ее. Идея заключалась в том, чтобы взять список открытых сделок, разделить покупки и продажи на 2 массива, каждый массив содержал ticket# в первом столбце, второй содержал значение цены сделки. В общем, идея заключалась в том, чтобы сопоставить все большие значения цены покупки со всеми большими значениями цены продажи, и если наибольшее значение покупки превышало наибольшее значение продажи, то закрыть обе эти сделки и повторить процесс.

Последний крючок, который заставил меня отказаться от этой идеи, заключался в том, что после прохождения этого процесса я хотел оставить на столе как минимум 1 положительную сделку на покупку и 1 положительную сделку на продажу, чтобы сохранить хеджированную торговую систему. По сути, это инструмент управления просадкой для стратегии хеджирования. Таким образом, я хочу сохранить хеджирование, но убрать доходы со стола. Мне пришло в голову, что использование алгорифма массивов может дать решение для этого.

Я очень устал и измотан попытками выпустить около 5 стратегий, так что это стало не столько необходимостью, сколько приятной мелочью.

Я готов заключить сделку с любым, кто сможет написать эту функцию для меня. Я дам вам на выбор продукты с многолетней лицензией, бесплатно за помощь мне в этом и, кроме того, я дам вам личную копию этой стратегии хеджирования для бесплатного неограниченного пожизненного использования. Я просто слишком занят, чтобы сделать все это, а моя команда разработчиков сильно загружена выпуском того, что уже находится на наших плечах. Я думаю, что средняя продолжительность сна в команде составляет от 4 до 6 часов в сутки.

Так что если вы заинтересованы в небольшом бартере и обмене, то это мое предложение.

Задачи:
1. Отделить покупки от продаж.
2. отсортировать их по принципу от самой высокой цены к самой низкой
3. Если у buy самые высокие положительные цены, а у sell самые низкие положительные цены, то мы хотим закрыть самую низкую сделку sell самой высокой сделкой buy, сделка buy должна превышать расход сделки sell. Если у sell более высокие положительные цены, то мы делаем обратное действие, чтобы закрыть самую низкую цену buy самой высокой ценой sell. Идея заключается в том, что на каждый проигрыш мы закрываем его выигрышем по более высокой цене, чтобы выигрыши превышали проигрыши со средним положительным заработком.

пример:
покупка-продажа
$15 $- 12
$5 $ - 6
$ 1.5 $ -1
$ 1 $ - .5

Это показывает сбалансированное количество открытых сделок с обеих сторон. Обратите внимание на покупку $15 и продажу $-12, их можно закрыть, потому что положительная покупка превышает отрицательную продажу. Мы также можем закрыть 5 и -6, потому что есть достаточно прибыли от первых двух закрытий, чтобы баланс между закрытием 4 из них был положительным. Мы можем сделать то же самое для 1,5 и -1, но мы не хотим закрывать 1 и -,5, потому что мы хотим сохранить ситуацию хеджирования.

В большинстве случаев сделки не будут сбалансированы как равные с обеих сторон. Это было основой дизайна, чтобы компенсировать самую тяжелую сторону более высоким размером лота и дополнительными сделками в пользу выигрывающей стороны, поэтому возможно, что у вас будет только 1 продажа, и в этом случае вы ничего не будете делать. В случае, если они не сбалансированы, но есть по крайней мере 2 сделки на каждой стороне, вам нужно убедиться, что вы оставили открытыми по одной сделке на каждой стороне. В случае, если 1 положительная сделка перевешивает более 1 отрицательной, вы можете закрыть их все, кроме одной сделки на каждой стороне, которые меньше всего друг друга.

Это должно быть разработано для вызова функции закрытия, которая закроет определенный тикет, так что вам не нужно беспокоиться о закрытии, просто сделайте вызов, чтобы сделки закрылись, передав тикет. Возможно, вам придется перестроить свой список так, чтобы он сравнивал не закрытые сделки, а все новые сделки, которые могли возникнуть во время обработки.

Ах да, еще одна вещь...
Она не должна быть слишком жадной, вы должны предоставить пользовательский экстерн, который диктует, как часто должна срабатывать эта функция, она может быть основана на количестве свечей или на основе часа или минуты, но не должна срабатывать каждый тик или даже каждую новую свечу. Как и сейчас, есть дополнительный инструмент, в который она будет встроена, и который сначала потребует, чтобы сработал другой инструмент, чтобы вызвать этот. Таким образом, сработает другой инструмент, и начнется обратный отсчет времени для срабатывания вашего инструмента.

 
Ларри, я уверен, что код для CloseBy() здесь -> https://book.mql4.com/trading/orderclose (это примерно 2/3 вниз по странице...) может быть расширен, чтобы сделать то, что вы хотите (без использования каких-либо массивов)... Это просто мысль для вашего ума.
Причина обращения: