Đường xu hướng chứng khoán Python

Phân tích đường xu hướng để xác định các mức hỗ trợ và kháng cự thường được các nhà kinh tế thực hiện bằng cách vẽ tay các đường trên biểu đồ, chẳng hạn như biểu đồ giá đóng cửa cho một chứng khoán cụ thể. Việc tự động hóa trên máy vi tính đối với một nhiệm vụ như vậy đã không được triển khai rộng rãi trong rất nhiều thư viện ngoài kia. Bắt đầu một nhiệm vụ như vậy đòi hỏi phải có được một định nghĩa khách quan về các đường xu hướng

“Trong tài chính, đường xu hướng là đường giới hạn cho sự biến động giá của chứng khoán. Nó được hình thành khi một đường chéo có thể được vẽ giữa tối thiểu ba điểm trục giá trở lên. Một đường có thể được vẽ giữa hai điểm bất kỳ, nhưng nó không được coi là đường xu hướng cho đến khi được kiểm tra. Do đó cần có điểm thứ ba, bài kiểm tra. ”

Yêu cầu ba điểm trở lên là nơi mà hầu hết các nỗ lực tầm thường đều thất bại. Vì vậy, chúng tôi sẽ thảo luận về các chi tiết kỹ thuật đằng sau từng khía cạnh của việc thực hiện điều này. Điều này có thể được sử dụng thêm để xác định các mẫu biểu đồ khác nhau, chẳng hạn như hình tam giác bao gồm hình tam giác, hình nêm, cờ đuôi nheo và các hình song song như cờ, đỉnh/đáy đôi/ba, đầu và vai, hình chữ nhật mặc dù tất cả những hình này thường chỉ yêu cầu 2 điểm, . Chủ đề thú vị này sẽ được lưu lại để thảo luận trong tương lai

Cài đặt

Chúng tôi sẽ sử dụng Python 3 (mặc dù bất kỳ phiên bản nào từ 2. 7 trở lên là đủ) cho tác vụ này vì nó có các thư viện tốt được thiết kế để xử lý các tập dữ liệu và khá dễ sử dụng. Đầu tiên, dữ liệu chứng khoán phải được tìm nạp. Đối với loạt ví dụ này, chỉ số phổ biến của S&P500 (Mã. ^GSPC) sẽ được sử dụng để có liên quan thực tế

Thư viện Python yfinance có thể dễ dàng tìm nạp toàn bộ dữ liệu lịch sử. Ví dụ, thuận tiện để lấy ít hơn 4 năm dữ liệu hoặc 1000 điểm cuối cùng. Nó sẽ trả về dữ liệu dưới dạng DataFrame của gấu trúc để lập chỉ mục thuận tiện và các hoạt động khác

import numpy as np
import pandas as pd
import yfinance as yf #pip install yfinance
tick = yf.Ticker('^GSPC')
hist = tick.history(period="max", rounding=True)
#hist = hist[:'2019-10-07']
hist = hist[-1000:]
h = hist.Close.tolist()

Để có kết quả có thể lặp lại, tập dữ liệu được lấy khi kết thúc vào ngày 7 tháng 10 năm 2019 và bộ lọc nhận xét cho hiệu ứng đó được hiển thị

Điểm xoay

Vấn đề đầu tiên là xác định các điểm xoay. Điểm của chúng tôi sẽ là giá đóng cửa tại một thời điểm nhất định. Chúng ta có thể coi những điểm này trong biểu đồ là các đỉnh và đáy hoặc là cực đại cục bộ và cực tiểu cục bộ

Tất cả các đỉnh và đáy phương pháp ngây thơ

Có một phương pháp ngây thơ để thực hiện điều này vì điểm xoay sẽ yêu cầu điểm trước và điểm tiếp theo phải thấp hơn hoặc cả hai đều cao hơn điểm hiện tại. Tuy nhiên, một phương pháp ngây thơ có những thiếu sót nghiêm trọng, như nếu giá không đổi trong 2 ngày liên tiếp, sẽ không có đỉnh hoặc đáy nào được phát hiện. Tuy nhiên, các chỉ số mà kịch bản này không xảy ra có thể được tính toán tương đối dễ dàng

minimaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] > x[1] and x[2] > x[1])).tolist()
maximaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] < x[1] and x[2] < x[1])).tolist()

Tất cả các đỉnh và đáy xử lý phương pháp trùng lặp liên tiếp

Chắc chắn, việc thu gọn những nơi mà giá không đổi và mã trước đó với truy xuất chỉ mục khác sẽ khắc phục thiếu sót này và mang lại tất cả chúng, với một lần duy nhất trong khoảng thời gian phẳng được xác định. Loại bỏ các bản sao liên tiếp trước khi tính toán ở trên cũng đơn giản như.

hs = hist.Close.loc[hist.Close.shift(-1) != hist.Close]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] > x[1] and x[2] > x[1])
minimaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] < x[1] and x[2] < x[1])
maximaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
4. Tuy nhiên, các chỉ mục cần tính toán lại vì chúng có thể đã thay đổi

hs = hist.Close.loc[hist.Close.shift(-1) != hist.Close]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] > x[1] and x[2] > x[1])
minimaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] < x[1] and x[2] < x[1])
maximaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]

Cả hai phương pháp này đều có thể được thực hiện bằng cách sử dụng danh sách và vòng lặp thay vì sử dụng kỹ thuật cửa sổ cuộn của Pandas và trên thực tế sẽ nhanh hơn đáng kể với thay đổi triển khai đơn giản đó. Mặc dù Pandas cung cấp các đoạn mã ngắn thanh lịch, nhưng không phải lúc nào việc sử dụng chúng cũng hiệu quả nhất, đặc biệt là hàm tổng hợp sử dụng hàm gọi lại

Phương pháp vi phân số

Tuy nhiên, một cách tiếp cận tao nhã hơn nhiều cho vấn đề này là sử dụng đạo hàm số của giá đóng cửa để xác định các điểm. Đạo hàm thứ nhất là tốc độ thay đổi hoặc hiệu quả là động lượng hoặc vận tốc của giá đóng cửa, trong khi đạo hàm thứ hai biểu thị tốc độ thay đổi của đạo hàm thứ nhất hoặc gia tốc của nó. Phân biệt thông thường không áp dụng ở đây vì chuỗi thời gian riêng biệt yêu cầu các công cụ phân tích số riêng biệt. Có một số lợi thế bao gồm đạo hàm số sẽ làm mịn dữ liệu bằng cách xem xét tất cả các điểm trong một phạm vi nhất định từ điểm mà tốc độ thay đổi sẽ được tính toán. Ví dụ: phương pháp stencil 5 điểm xem xét một số gia số trước và sau, cũng như gia số kép trước và sau cùng với chính điểm đó. Thư viện findiff làm cho việc tính toán này trở nên dễ dàng và chính xác ngay cả khi sử dụng các phương pháp xấp xỉ bậc cao hơn

from findiff import FinDiff #pip install findiff
dx = 1 #1 day interval
d_dx = FinDiff(0, dx, 1)
d2_dx2 = FinDiff(0, dx, 2)
clarr = np.asarray(hist.Close)
mom = d_dx(clarr)
momacc = d2_dx2(clarr)

Với đạo hàm thứ nhất và thứ hai được tính toán, một mức độ làm mịn đã xảy ra một cách hiệu quả mang lại cho chúng ta các đỉnh và đáy nổi bật. Chúng là những nơi mà đạo hàm đầu tiên bằng 0 vì không có động lượng nào cho thấy sự thay đổi hướng đã xảy ra. Đạo hàm thứ hai dương hoặc âm biểu thị đáy hoặc đỉnh tương ứng vì gia tốc hướng lên đi xuống biểu thị sự đảo ngược hướng. Tuy nhiên, một đạo hàm đầu tiên chính xác của 0 là rất khó xảy ra. Thay vào đó, một giá trị ở một phía của 0 theo sau bởi một phía khác là thực tế những gì sẽ xảy ra kể từ khi điểm đạo hàm 0 xảy ra trong khoảng thời gian giữa hai ngày. Vì vậy, dựa trên điều này, giá đóng cửa cao hơn hoặc thấp hơn sẽ được chọn giữa hai điểm xảy ra sự giao nhau bằng 0

def get_extrema(isMin):
return [x for x in range(len(mom))
if (momacc[x] > 0 if isMin else momacc[x] < 0) and
(mom[x] == 0 or #slope is 0
(x != len(mom) - 1 and #check next day
(mom[x] > 0 and mom[x+1] < 0 and
h[x] >= h[x+1] or
mom[x] < 0 and mom[x+1] > 0 and
h[x] <= h[x+1]) or
x != 0 and #check prior day
(mom[x-1] > 0 and mom[x] < 0 and
h[x-1] < h[x] or
mom[x-1] < 0 and mom[x] > 0 and
h[x-1] > h[x])))]
minimaIdxs, maximaIdxs = get_extrema(True), get_extrema(False)

Một cuộc thảo luận khá dài và nếu tất cả các điểm cực tiểu và cực đại đều được mong muốn, thì việc kết hợp các chỉ số từ phương pháp ngây thơ có thể được thực hiện vì nó sẽ nắm bắt được các điểm đã được làm mịn trong quá trình tính toán động lượng. Nhưng với mục đích của các đường xu hướng, các điểm mấu chốt nổi bật thường là lý tưởng và các điểm khác hầu như ồn ào hoặc không liên quan. Đây là một biểu đồ nhỏ hiển thị 10 ngày với các giá trị vận tốc và gia tốc cùng với các điểm trục được xác định

Giá đóng cửa với Điểm xoay, Động lượng, Gia tốc

Giờ đây, đối với những người tò mò về toán học, những người không muốn rời bỏ phép tính này chỉ đến một thư viện như findiff, tôi sẽ đề xuất cách tính một điểm duy nhất trong dữ liệu này (2019–09–27 đóng cửa lúc 2961. 79, trước đó là 2977. 62 và tiếp theo là 2976. 74). Nó tính toán các hệ số riêng của nó để cho phép

Hầu hết mọi người hiểu đạo hàm là sự thay đổi (delta — △) của y trên sự thay đổi của x. Đối với một đường liên tục, đây chỉ đơn thuần là độ dốc của đường và với các điểm tiếp theo, việc tính toán bằng cách lấy chênh lệch của các giá trị y là chuyện nhỏ. Nhưng đạo hàm thực sự là giới hạn của △x trên △y khi △x tiến dần đến 0. Lấy giới hạn như vậy đối với các điểm dữ liệu rời rạc đòi hỏi phải thực sự mở rộng số lượng điểm được xem xét

Điều này có nghĩa là, về mặt kỹ thuật, có một sự rò rỉ dữ liệu ở đây mặc dù đó là một sự cố nhỏ và không liên quan, vì các giá trị trong tương lai được xem xét cho dữ liệu trong quá khứ. Nó tinh tế và không đặc biệt quan trọng, mặc dù nếu tìm các đường xu hướng bằng cách sử dụng dữ liệu rất gần đây trong cửa sổ khoảng thời gian của đạo hàm số, có lẽ một kỹ thuật khác được đề cập sẽ tốt hơn. Chúng ta đang nói về bao nhiêu ngày?

Vì vậy, tôi sẽ cung cấp mã hiển thị các phép tính tay của một điểm trung tâm

import findiff
coeff = findiff.coefficients(deriv=1, acc=1)
print(coeff)

Điều này sẽ mang lại

{‘center’: {‘coefficients’: array([-0.5, 0. , 0.5]),
‘offsets’: array([-1, 0, 1])},
‘forward’: {‘coefficients’: array([-1.5, 2. , -0.5]),
‘offsets’: array([0, 1, 2])},
‘backward’: {‘coefficients’: array([ 0.5, -2. , 1.5]),
‘offsets’: array([-2, -1, 0])}}

Vì vậy, findiff sử dụng các hệ số -0. 5, 0, 0. 5 và chênh lệch thời gian -1, 0 và 1 cho tất cả các điểm trung tâm. Tất nhiên ở ngoài cùng bên phải và ngoài cùng bên trái, nó sử dụng các giá trị tiến và lùi. Tính toán tất cả các dẫn xuất là thẳng về phía trước sau đó. Các chi tiết tính toán cái được gọi là hệ số sai phân hữu hạn và kích thước cửa sổ nằm ngoài phạm vi ở đây nhưng có các bảng và phương pháp để dễ dàng tính toán chúng.

________số 8_______

Điều này mang lại như hình ảnh cho thấy

  • -0. 44000000000005457=-2977. 62/2+2976. 74/2

để tăng tốc

coeff=findiff.coefficients(deriv=2, acc=1)
print(coeff)

năng suất

{‘center’: {‘coefficients’: array([ 1., -2., 1.]),
‘offsets’: array([-1, 0, 1])},
‘forward’: {‘coefficients’: array([ 2., -5., 4., -1.]),
‘offsets’: array([0, 1, 2, 3])},
‘backward’: {‘coefficients’: array([-1., 4., -5., 2.]),
‘offsets’: array([-3, -2, -1, 0])}}

Và một lần nữa

minimaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] > x[1] and x[2] > x[1])).tolist()
maximaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] < x[1] and x[2] < x[1])).tolist()
0

Và chúng ta cũng thấy giá trị kỳ vọng

  • 30. 779999999999745=2977. 62–2961. 79*2+2976. 74

Độ chính xác có thể được tăng lên mặc dù có vẻ như mặc định là 1 được sử dụng nên nó không phải là khuôn tô 5 điểm mà tôi đã chỉ cho bạn nhưng có kỹ thuật riêng để tạo ra các hiệu số và hệ số mà Wikipedia cũng đi sâu vào một số chi tiết về. Có thể tìm thấy các hệ số 5 điểm stencil đã được chia ở đó với.

hs = hist.Close.loc[hist.Close.shift(-1) != hist.Close]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] > x[1] and x[2] > x[1])
minimaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] < x[1] and x[2] < x[1])
maximaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
5. Sau đó, nó trông giống 2 ngày trước và sau thay vì chỉ 1 với
hs = hist.Close.loc[hist.Close.shift(-1) != hist.Close]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] > x[1] and x[2] > x[1])
minimaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] < x[1] and x[2] < x[1])
maximaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
6 giống hệt nhau và chỉ theo thứ tự đảo ngược như đã trình bày. Lưu ý rằng có thể chuyển
hs = hist.Close.loc[hist.Close.shift(-1) != hist.Close]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] > x[1] and x[2] > x[1])
minimaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] < x[1] and x[2] < x[1])
maximaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
7 dưới dạng tham số bổ sung cho hàm tạo FinDiff để có độ chính xác cao hơn

Phương pháp Đường xu hướng

Cuối cùng đã có được các điểm xoay, việc chọn 2 trong số chúng sẽ rất dễ dàng vì bất kỳ cặp điểm cực tiểu hoặc cực đại nào cũng sẽ tạo thành một đường cho tổng số _______2_______8 đường hoàn toàn phù hợp với hình học cơ bản chỉ ra rằng 2 điểm duy nhất là . Tuy nhiên, 3 điểm có thể được chọn theo

hs = hist.Close.loc[hist.Close.shift(-1) != hist.Close]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] > x[1] and x[2] > x[1])
minimaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] < x[1] and x[2] < x[1])
maximaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
9 cách và cách liệt kê như vậy có độ phức tạp về thuật toán O(n³). Các điểm này không phải lúc nào cũng thẳng hàng nên cũng sẽ có sai số ở một mức độ nào đó. Mức độ lỗi sẽ rất quan trọng vì chúng ta cần lọc ra các tập hợp điểm không chính xác và bao gồm những điểm đúng

Giờ đây, hình học cơ bản sẽ phát huy tác dụng khi một đường thẳng được biểu diễn thuận tiện hơn dưới dạng độ dốc và giao điểm để có thể dễ dàng tính toán các điểm tại bất kỳ vị trí nào trên đường thẳng. nhớ lại rằng đối với 2 điểm, hệ số góc m của một đường thẳng trong mặt phẳng 2 chiều với các trục x và y được định nghĩa là sự thay đổi của y so với sự thay đổi của x. Chặn b được tính bằng cách sử dụng một trong các điểm để phù hợp với phương trình đường chuẩn. May mắn thay, chúng ta có thể sử dụng ký hiệu tung độ dốc vì không có độ dốc vô hạn trong dữ liệu chuỗi thời gian trong đó có một điểm duy nhất mỗi lần. Mặt khác, có thể sử dụng ký hiệu cực với khoảng cách góc. Khoảng cách giữa hai điểm là đường thẳng kẻ từ đường chéo của hình chữ nhật tạo bởi các điểm như định lý Pitago cho tam giác vuông

Đối với 3 điểm, nếu chúng ta khớp đường thẳng với 2 điểm, chúng ta có thể tính độ lớn của khoảng cách từ đường thẳng đó đến điểm thứ 3 dọc theo trục y. Tuy nhiên, khoảng cách này là thước đo sai số khá tùy ý vì nó sẽ khác nhau tùy thuộc vào 2 điểm chúng tôi chọn trong số 3 lựa chọn có thể, 2 điểm bổ sung là. đầu tiên và cuối cùng hoặc thứ hai và thứ ba. Tất cả các công thức này và các ví dụ của chúng được đưa ra một cách trực quan

Điểm giá đóng thể hiện tính toán đường

Cho 3 điểm, có thể tìm thấy một đường thẳng phù hợp nhất, đó chính xác là những gì tính toán. Nó tìm thấy một dòng phù hợp nhất với 3 điểm trở lên dựa trên việc giảm thiểu lỗi. Lỗi thường là tổng bình phương phần dư trong đó phần dư tương đương với thước đo khoảng cách như đã cho ở trên. Phương trình chính cần thiết là độ dốc của đường thẳng, từ đó hệ số chặn được tính như trên bằng cách sử dụng các giá trị trung bình của y và x

Có hai lỗi tiêu chuẩn được đưa ra là một lỗi của độ dốc, lỗi còn lại của giao điểm. Đối với độ dốc, lỗi dựa trên tổng bình phương phần dư (SSR) được tính một phần bằng cách chia cho số điểm trừ 2 trong đó số điểm trong trường hợp này là 3 làm cho thuật ngữ biến mất nên nó chỉ là căn bậc hai của . Lỗi chặn là lỗi độ dốc được điều chỉnh bởi các giá trị x. Lỗi độ dốc là đủ chỉ báo lỗi nên điều này sẽ được áp dụng. Cần lưu ý rằng SSR, độ dốc và lỗi chặn đang giả định rằng phương sai của các điểm là không đổi, điều này có thể không đúng. Giả sử độ dốc tiêu chuẩn và các lỗi chặn được phân phối bình thường, điều này cũng có thể không đúng, những điều này sẽ chỉ ra rằng 68% phần trăm số điểm nằm trong khoảng cộng hoặc trừ giá trị lỗi đó, trong đó lỗi gấp đôi là 95% và gấp ba lỗi là 99. 7% theo. Vì vậy, vì phương sai không được đảm bảo cũng như không phải là phân phối bình thường, tại sao lại sử dụng bất kỳ thứ gì có nguồn gốc từ SSR? . SSR vẫn có thể được giữ vì nó cũng có thể được điều chỉnh cho mục đích tương tự mặc dù có kết quả rất giống nhau. Tuy nhiên, tính trung bình thẳng đơn giản của các giá trị dự kiến ​​so với các giá trị thực tế là cách đơn giản nhất và vẫn có thể chấp nhận được

Điểm giá đóng thể hiện hồi quy tuyến tính

Trong Python, biến thể 3 điểm có thể được mã hóa một cách hiệu quả là

minimaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] > x[1] and x[2] > x[1])).tolist()
maximaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] < x[1] and x[2] < x[1])).tolist()
1

Tuy nhiên, đối với tính tổng quát nhưng với chi phí tốc độ, chúng tôi sẽ thực hiện điều này cho bất kỳ số điểm nào vì đường xu hướng tốt hơn sẽ là đường có thể có nhiều hơn 3 điểm với điều kiện 3 chỉ là mức tối thiểu

minimaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] > x[1] and x[2] > x[1])).tolist()
maximaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] < x[1] and x[2] < x[1])).tolist()
2

Nói chung hơn nữa, thư viện numpy có các hàm polyfit và poly1d có thể thực hiện chính xác điều này cho bất kỳ đa thức nào, trong trường hợp này là một dòng hoặc bậc 1. Chúng tôi sẽ sử dụng nó để tính toán đường hỗ trợ trung bình và đường kháng cự trung bình dựa trên tất cả các điểm cực tiểu và cực đại cục bộ tương ứng. Độ dốc và phần chặn được trả về bởi polyfit và poly1d mặc dù poly1d cung cấp khả năng thao tác và sử dụng dễ dàng hơn và do đó được chứng minh khi lỗi được trả về chỉ là tổng bình phương lỗi còn lại nhưng với mục đích so sánh là nhất quán. Mặc dù thích hợp cho một lần sử dụng, chẳng hạn như trung bình tổng thể, nhưng một hàm chung như vậy có thể không nhanh bằng các hàm được tối ưu hóa được viết ở trên, do đó, bạn cần thực hành viết chúng. Tất nhiên ít nhất 2 điểm phải được xác định để phù hợp với dòng này

minimaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] > x[1] and x[2] > x[1])).tolist()
maximaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] < x[1] and x[2] < x[1])).tolist()
3

Nếu thích sử dụng mã số ổn định hơn theo tài liệu thì có Đa thức. phiên bản phù hợp là tốt

minimaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] > x[1] and x[2] > x[1])).tolist()
maximaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] < x[1] and x[2] < x[1])).tolist()
4

Tuy nhiên, lỗi không thể được áp dụng nhất quán cho tất cả các chứng khoán vì giá trị tuyệt đối của lỗi có liên quan đến khoảng thời gian và phạm vi giá trong khoảng thời gian đó. Vì vậy, trước tiên một quy mô thích hợp nên được tính toán.

from findiff import FinDiff #pip install findiff
dx = 1 #1 day interval
d_dx = FinDiff(0, dx, 1)
d2_dx2 = FinDiff(0, dx, 2)
clarr = np.asarray(hist.Close)
mom = d_dx(clarr)
momacc = d2_dx2(clarr)
0. (Nếu chỉ lấy căn bậc hai của sai số dư và chia cho (n-2) thì chia cho
from findiff import FinDiff #pip install findiff
dx = 1 #1 day interval
d_dx = FinDiff(0, dx, 1)
d2_dx2 = FinDiff(0, dx, 2)
clarr = np.asarray(hist.Close)
mom = d_dx(clarr)
momacc = d2_dx2(clarr)
1 ở đây là không cần thiết. ) Sau đó, một tham số
from findiff import FinDiff #pip install findiff
dx = 1 #1 day interval
d_dx = FinDiff(0, dx, 1)
d2_dx2 = FinDiff(0, dx, 2)
clarr = np.asarray(hist.Close)
mom = d_dx(clarr)
momacc = d2_dx2(clarr)
2cho hàm đường xu hướng sẽ là một lỗi phần trăm đơn giản, chẳng hạn như 0. 5%=0. 005 nơi
from findiff import FinDiff #pip install findiff
dx = 1 #1 day interval
d_dx = FinDiff(0, dx, 1)
d2_dx2 = FinDiff(0, dx, 2)
clarr = np.asarray(hist.Close)
mom = d_dx(clarr)
momacc = d2_dx2(clarr)
3. Các sắc thái khác nên được xử lý, chẳng hạn như độ dốc 0 không được trả về dưới dạng hệ số và phải được điền thủ công

phương pháp ngây thơ

Phương pháp này chỉ đơn giản là liệt kê qua tất cả các kết hợp của 3 điểm để tìm ra lỗi liên quan và lọc ra những điểm có giá trị lỗi quá lớn. Tất nhiên, O(n³) không phải là lý tưởng và nếu tập dữ liệu đủ lớn thậm chí sẽ không khả thi trên thực tế. Nhưng tổng điểm cực tiểu và tổng điểm cực đại trong thực tế sẽ không lớn đến mức không thể. Ví dụ: 100 điểm trục sẽ là 100*100*100=1.000.000 hoặc một triệu phép tính. Rõ ràng là để củng cố điều này với 4 hoặc 5 điểm sẽ bắt đầu trở nên không thực tế vì thứ tự phức tạp đã chuyển sang O(n⁴) hoặc O(n⁵). Vì vậy, một chiến lược khác là cần thiết

minimaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] > x[1] and x[2] > x[1])).tolist()
maximaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] < x[1] and x[2] < x[1])).tolist()
5

Sắp xếp phương pháp Slope

May mắn thay, có một số tính chất nhất định của các điểm có thể tương quan với nhau, chẳng hạn như độ dốc của đường thẳng (hoặc góc so với gốc tọa độ). Bằng cách thực hiện duyệt O(n²) tất cả các kết hợp của 2 điểm và tính toán độ dốc của đường mà chúng tạo thành, có thể tạo danh sách các độ dốc cho từng điểm. Bây giờ, việc sắp xếp một danh sách là trường hợp xấu nhất có độ phức tạp lý tưởng là O(n log n) để thuật toán sắp xếp hiệu quả như sắp xếp hợp nhất và chúng ta cần thực hiện điều này trên tất cả n danh sách cho O(n² log n) đây sẽ là độ phức tạp của thuật toán. Các điểm lân cận trong danh sách độ dốc được sắp xếp có thể được xem xét liên tục từ 3 đến tuy nhiên nhiều điểm tiếp tục đáp ứng tiêu chí lọc. Khi chúng được khớp, nhóm sẽ bị xóa và quá trình tìm kiếm tiếp tục. Phần này của thuật toán cũng là O(n²). (Hệ số phức tạp lớn nhất thường là hệ số duy nhất cần xem xét để giữ cho công thức được đơn giản hóa nên 2 O(n²) còn lại không được thêm vào. )

Đây là một thuật toán gần đúng và không đầy đủ vì sắp xếp theo độ dốc không đảm bảo rằng các giá trị độ dốc lân cận sẽ phù hợp nhất khi có thể có khoảng cách lớn giữa các điểm. Tuy nhiên, trên thực tế, tương đối hiếm khi xảy ra kịch bản mà điều này sẽ xảy ra.

minimaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] > x[1] and x[2] > x[1])).tolist()
maximaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] < x[1] and x[2] < x[1])).tolist()
6

Trên thực tế, rất nhiều trận đấu có 3 điểm ngay lập tức được thay thế bằng 4 điểm hoặc thậm chí nhiều hơn vì xu hướng không có gì đáng ngạc nhiên xảy ra trong dữ liệu chỉ mục hoặc bảo mật thực

Phương pháp biến đổi dòng Hough

Có nhiều cách khác để cố gắng giải thuật toán tìm đường và một cách đến từ xử lý hình ảnh trong đó tìm đường trong ảnh là một nhiệm vụ phổ biến và quan trọng trong thị giác máy tính. Một phương pháp như vậy để làm như vậy là biến đổi đường Hough tìm kiếm các điểm trên các đường ở một số góc nhất định trong khi ghi điểm cho chúng để tìm thấy bao nhiêu điểm. Thuật toán này cũng có hạn chế. Thật không may, nó sử dụng rất nhiều bộ nhớ để theo dõi tất cả các biểu đồ và độ chính xác của nó dựa trên số lượng góc được thử. Tuy nhiên, càng nhiều góc cố gắng, nó càng trở nên chậm hơn. Bộ nhớ dựa trên kích thước đường chéo của hình ảnh (với kích thước

from findiff import FinDiff #pip install findiff
dx = 1 #1 day interval
d_dx = FinDiff(0, dx, 1)
d2_dx2 = FinDiff(0, dx, 2)
clarr = np.asarray(hist.Close)
mom = d_dx(clarr)
momacc = d2_dx2(clarr)
4x_______5_______) và số góc (
from findiff import FinDiff #pip install findiff
dx = 1 #1 day interval
d_dx = FinDiff(0, dx, 1)
d2_dx2 = FinDiff(0, dx, 2)
clarr = np.asarray(hist.Close)
mom = d_dx(clarr)
momacc = d2_dx2(clarr)
6) hoặc
from findiff import FinDiff #pip install findiff
dx = 1 #1 day interval
d_dx = FinDiff(0, dx, 1)
d2_dx2 = FinDiff(0, dx, 2)
clarr = np.asarray(hist.Close)
mom = d_dx(clarr)
momacc = d2_dx2(clarr)
7. Thu nhỏ hình ảnh là cần thiết để có kết quả tốt. Trên thực tế, góc nhỏ hơn của
from findiff import FinDiff #pip install findiff
dx = 1 #1 day interval
d_dx = FinDiff(0, dx, 1)
d2_dx2 = FinDiff(0, dx, 2)
clarr = np.asarray(hist.Close)
mom = d_dx(clarr)
momacc = d2_dx2(clarr)
8 và
from findiff import FinDiff #pip install findiff
dx = 1 #1 day interval
d_dx = FinDiff(0, dx, 1)
d2_dx2 = FinDiff(0, dx, 2)
clarr = np.asarray(hist.Close)
mom = d_dx(clarr)
momacc = d2_dx2(clarr)
9 sẽ là góc nhỏ nhất cần tìm kiếm để tìm tất cả các khả năng có 3 điểm vì đây là gia số nhỏ nhất giữa một đường thẳng đứng hoặc nằm ngang. Bằng cách sửa thuật toán với một số chẳng hạn như 360*5 các góc có thể có trong khoảng từ 90 đến -90 độ, chúng ta có thể sử dụng
def get_extrema(isMin):
return [x for x in range(len(mom))
if (momacc[x] > 0 if isMin else momacc[x] < 0) and
(mom[x] == 0 or #slope is 0
(x != len(mom) - 1 and #check next day
(mom[x] > 0 and mom[x+1] < 0 and
h[x] >= h[x+1] or
mom[x] < 0 and mom[x+1] > 0 and
h[x] <= h[x+1]) or
x != 0 and #check prior day
(mom[x-1] > 0 and mom[x] < 0 and
h[x-1] < h[x] or
mom[x-1] < 0 and mom[x] > 0 and
h[x-1] > h[x])))]
minimaIdxs, maximaIdxs = get_extrema(True), get_extrema(False)
0 để tìm kích thước hình ảnh tối đa và chỉ chia tỷ lệ theo số lượng này nếu hình ảnh vượt quá giới hạn

Chúng tôi bắt đầu bằng cách điều chỉnh dữ liệu chuỗi thời gian của mình thành một hình ảnh. Điều này đòi hỏi phải làm cho giá trị giá rời rạc, có thể được thực hiện bằng cách nhân với 100 để loại bỏ phần thập phân của số tiền đô la. Hình ảnh chỉ cần có kích thước theo khoảng thời gian và giá tối thiểu và tối đa trong thời gian đó. Toàn bộ hình ảnh sẽ được khởi tạo thành màu đen và các điểm trắng sẽ được đặt ở những vị trí thích hợp nơi xuất hiện các điểm cực tiểu hoặc cực đại

minimaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] > x[1] and x[2] > x[1])).tolist()
maximaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] < x[1] and x[2] < x[1])).tolist()
7

Biến đổi Hough khá dễ triển khai trong Python được tối ưu hóa dưới dạng thuật toán nhập điểm. Đối với mọi góc và mọi điểm, tính khoảng cách đến đường thẳng vuông góc với góc đi qua điểm đó. Đối với mỗi góc, khoảng cách đến đường vuông góc này là tích một điểm, trong đó các điểm khác nhau có khoảng cách bằng nhau theo hình học phải nằm trên một đường thẳng

Điểm giá đóng thể hiện sự tích lũy biến đổi Hough của rho-theta cho đường 2 điểm có nguồn gốc dựa trên ngày đầu tiên và giá tối thiểu được hiển thị

Điều này dẫn đến thuật toán O(n*m) trong đó m là số góc trong khi mức sử dụng bộ nhớ yêu cầu m lần độ dài đường chéo của không gian điểm 2 chiều

minimaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] > x[1] and x[2] > x[1])).tolist()
maximaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] < x[1] and x[2] < x[1])).tolist()
8

Biến đổi Hough để bảo toàn bộ nhớ không trả về bất kỳ thông tin điểm cụ thể nào, vì mục đích trực quan hóa có thể rất hữu ích. Vì vậy, chúng tôi có thể tính toán khoảng cách cho tất cả các điểm đến đường thẳng, sắp xếp nó và lấy càng nhiều điểm càng tốt phù hợp với dung sai lỗi. Khoảng cách của một điểm đến một dòng được sử dụng để xác định bộ tích lũy chính xác để tăng. Hãy nhớ rằng hệ số góc của hệ số góc vuông góc là nghịch đảo âm của hệ số góc để nhân chúng bằng -1. Một đường vuông góc được tạo cho điểm tương ứng với điểm mới và giao điểm được tính. Phần còn lại của chứng minh được suy ra bằng cách sử dụng khoảng cách giữa điểm và giao điểm. Lưu ý rằng tử số chỉ đơn thuần là sự khác biệt giữa y và y dự kiến, trong khi mẫu số được giữ cố định vì chúng ta chỉ xem xét một hệ số góc duy nhất. Hình hiển thị biến đổi Hough cũng đưa ra công thức rõ ràng

minimaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] > x[1] and x[2] > x[1])).tolist()
maximaIdxs = np.flatnonzero(
hist.Close.rolling(window=3, min_periods=1, center=True).aggregate(
lambda x: len(x) == 3 and x[0] < x[1] and x[2] < x[1])).tolist()
9

Chúng ta cũng có thể sử dụng chức năng biến đổi dòng Hough của thư viện scikit-image có tên. Cần lưu ý rằng thư viện OpenCV (Computer Vision) cũng có sẵn trong Python, cũng có các chức năng tương tự. Điều này cũng có thể được thực hiện thủ công với một lượng mã ngắn vì thuật toán không đặc biệt phức tạp nhưng các thư viện được tối ưu hóa và nhanh hơn. Lưu ý rằng chỉ 2 điểm trong bộ tích lũy là đủ để thuật toán trả về chúng, vì vậy chúng tôi sẽ lọc 3 điểm liên quan trở lên. Chi tiết hữu ích là nó đảo ngược các trục và có tham số ngưỡng lớn hơn nhưng không bằng. Có một số khác biệt chi tiết nhỏ về cách thức hoạt động bên trong, đặc biệt là đối với việc lựa chọn cực đại cục bộ trong bộ tích lũy nên kết quả sẽ không giống hệt nhau. Điều này dẫn đến hai phương pháp khác nhau để thực hiện phép tính (một điểm được tối ưu hóa, điểm còn lại biến đổi thành hình ảnh cho thư viện)

hs = hist.Close.loc[hist.Close.shift(-1) != hist.Close]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] > x[1] and x[2] > x[1])
minimaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] < x[1] and x[2] < x[1])
maximaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
0

Phương pháp biến đổi dòng Hough theo xác suất

Các góc chính xác được sử dụng và các yêu cầu bộ nhớ và xử lý cao cần thiết cho nhận dạng đường Hough thông thường khiến cho nhiệm vụ này có một số điểm nhỏ trở nên không thực tế. Số lượng điểm càng lớn, nó có thể hoạt động tốt hơn. Tuy nhiên, phương pháp trước đây là một bài tập về độ chính xác. Trong thực tế, một biến đổi dòng Hough xác suất được sử dụng khi tìm kiếm được thực hiện một cách ngẫu nhiên và các tham số được sử dụng để lọc kết quả bao gồm ngưỡng cho số điểm. Một chức năng thư viện khác hoạt động cho mục đích này

hs = hist.Close.loc[hist.Close.shift(-1) != hist.Close]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] > x[1] and x[2] > x[1])
minimaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] < x[1] and x[2] < x[1])
maximaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
1

Vẫn chỉ có 2 điểm của đường được trả về ở đây, nhưng ngưỡng đã được tích hợp và thực hiện cho chúng tôi. Thật không may, kết quả sẽ khác nhau mỗi khi nó được chạy do bản chất của thuật toán xác suất có tính ngẫu nhiên. Điều này nói chung làm cho phương pháp này không đặc biệt phù hợp để tìm tất cả các đường xu hướng. Vì nó có thể được chạy nhiều lần, điều này có thể được thực hiện cho đến khi xảy ra một số lần chạy nhất định hoặc một số dòng nhất định được tìm thấy để tăng đáng kể xác suất tìm thấy tất cả các dòng. Như vậy tham số

def get_extrema(isMin):
return [x for x in range(len(mom))
if (momacc[x] > 0 if isMin else momacc[x] < 0) and
(mom[x] == 0 or #slope is 0
(x != len(mom) - 1 and #check next day
(mom[x] > 0 and mom[x+1] < 0 and
h[x] >= h[x+1] or
mom[x] < 0 and mom[x+1] > 0 and
h[x] <= h[x+1]) or
x != 0 and #check prior day
(mom[x-1] > 0 and mom[x] < 0 and
h[x-1] < h[x] or
mom[x-1] < 0 and mom[x] > 0 and
h[x-1] > h[x])))]
minimaIdxs, maximaIdxs = get_extrema(True), get_extrema(False)
1 quy định số lần lặp để chạy nó chẳng hạn 10 lần lặp để tăng khả năng đủ số dòng

Lưu ý rằng tốt hơn mã hóa cứng 100 cho tỷ lệ đồng xu hoặc 1/0. 01 vì đô la đang được sử dụng, sẽ tốt hơn nếu có tham số

def get_extrema(isMin):
return [x for x in range(len(mom))
if (momacc[x] > 0 if isMin else momacc[x] < 0) and
(mom[x] == 0 or #slope is 0
(x != len(mom) - 1 and #check next day
(mom[x] > 0 and mom[x+1] < 0 and
h[x] >= h[x+1] or
mom[x] < 0 and mom[x+1] > 0 and
h[x] <= h[x+1]) or
x != 0 and #check prior day
(mom[x-1] > 0 and mom[x] < 0 and
h[x-1] < h[x] or
mom[x-1] < 0 and mom[x] > 0 and
h[x-1] > h[x])))]
minimaIdxs, maximaIdxs = get_extrema(True), get_extrema(False)
2

Bây giờ chúng ta có 5 phương pháp khác nhau để cố gắng tìm các đường xu hướng

Tìm các đường xu hướng tốt nhất

Thật không may, chỉ vì các điểm cực tiểu hoặc cực đại cục bộ nằm trên một đường, chúng có thể không phải lúc nào cũng mang lại đường xu hướng tốt nhất. Điều này là do những gì được coi là tốt nhất thường mang tính chủ quan. Tuy nhiên, có nhiều cách điều này có thể được biến thành một định nghĩa khách quan. Một cách như vậy là xem tần suất giá vượt qua đường xu hướng hoặc khu vực được tạo bởi đường xu hướng và dữ liệu giá qua điểm sớm nhất và mới nhất của nó. Tỷ lệ phần trăm lỗi chỉ được sử dụng để xác định những gì có thể hoặc không thể là đường xu hướng, nhưng không hữu ích như thế nào đường xu hướng có thể hoặc không. Với đủ dữ liệu, có thể tìm thấy các dòng cách nhau nhiều năm mà dường như không hữu ích cho dù chúng có trùng hợp hay không. Thông thường, các đường xu hướng được vẽ có chứa tín hiệu ở bên này hay bên kia, do đó, cách tiếp cận dựa trên khu vực ít nhất có vẻ hợp lý. Tổng Riemann cung cấp một kỹ thuật tích hợp có thể được sử dụng để tính diện tích này. Trên thực tế, ứng dụng này rất tầm thường vì nó chỉ trừ hai giá trị và tính tổng tất cả các giá trị nhỏ hơn hoặc lớn hơn 0. Cụ thể, đây sẽ là một tổng Riemann đúng, sử dụng giá trị hàm tại mỗi thời điểm trái ngược với điểm giữa hoặc điểm trước đó, cực đại hoặc cực tiểu. Cuối cùng, chia nó cho số ngày sẽ cho phép đo mặt sai của xu hướng mỗi ngày và có thể chọn các đường xu hướng tốt nhất

Giá đóng cửa với mức kháng cự và diện tích_______2_______2

Một vấn đề khác là các thuật toán này có thể bị chậm ngay cả khi chúng được triển khai hiệu quả vì nhiều lý do. Thường có thể tối ưu hóa hơn nữa, đặc biệt là bằng cách loại bỏ gấu trúc và chuyển sang danh sách và mảng gọn gàng có triển khai C nhanh

Tuy nhiên, câu hỏi thực sự ở đây là các đường xu hướng được sử dụng chính xác như thế nào? . Làm thế nào chính xác một cửa sổ có thể được thực hiện ở đây?

Ý tưởng đầu tiên là lấy một khoảng thời gian chẳng hạn như một quý hoặc một năm vì khoảng thời gian quá ngắn sẽ không mang lại đủ điểm mấu chốt hữu ích. Sau đó, cửa sổ phải được cuộn qua tất cả dữ liệu, tuy nhiên, không phải theo cách không hiệu quả hoặc trùng lặp công việc, cũng như không bỏ sót các đường xu hướng có thể có. Khi kích thước cửa sổ được quyết định, công việc có thể bắt đầu bằng cách tìm kiếm với kích thước cửa sổ gấp đôi. Nhân đôi kích thước cửa sổ đảm bảo rằng các đường xu hướng trên đường viền của cửa sổ sẽ được tìm thấy. Sau đó, kích thước cửa sổ kép được tìm kiếm trên tất cả dữ liệu theo gia số kích thước cửa sổ. Vì vậy, nếu khoảng thời gian của bạn là một năm, bạn tìm kiếm trong hai năm qua, sau đó tìm kiếm từ 3 năm trước năm trước, sau đó từ 4 năm trước đến 2 năm trước, v.v. Một phần của cửa sổ sẽ được tìm kiếm hai lần và nhiều phần giống hệt hoặc phần mở rộng của các xu hướng giống hệt nhau sẽ xuất hiện. Điều này cũng sẽ dễ nhìn hơn nhiều, vì sẽ gây rối cho cốt truyện nếu các đường xu hướng được vẽ quá xa

Vì vậy, cuối cùng, các đường xu hướng được tìm thấy phải được hợp nhất lại với nhau một cách thông minh để có được tập hợp cuối cùng. Nó có thể được thực hiện bằng cách đi qua tất cả các đường xu hướng chứa từng điểm đã cho và áp dụng phương pháp sắp xếp độ dốc đã thảo luận trước đó. Dù sao thì điều này cũng cần thiết cho các phương thức biến đổi Hough vì chúng có thể tạo ra các tập hợp điểm dư thừa

hs = hist.Close.loc[hist.Close.shift(-1) != hist.Close]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] > x[1] and x[2] > x[1])
minimaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
x = hs.rolling(window=3, center=True)
.aggregate(lambda x: x[0] < x[1] and x[2] < x[1])
maximaIdxs = [hist.index.get_loc(y) for y in x[x == 1].index]
3

Điểm chính rút ra từ cuộc thảo luận này là khách quan hóa ý tưởng của bạn một cách tốt nhất, biết rằng không phải tất cả mọi người sẽ nhất thiết đồng ý với bất kỳ một định nghĩa khách quan nào. Nó giúp không sử dụng bất kỳ phím tắt nào trong giai đoạn động não để tạo ra một phương pháp toàn diện và đúng đắn

Trực quan hóa kết quả

Trên thực tế, quá trình hợp nhất được thực hiện ở trên có thể tìm thấy các đường xu hướng có các điểm trong các cửa sổ cách nhau rất xa, điều này sẽ kéo dài chúng một cách đáng kể, điều gì đó có thể được mong muốn hoặc không. Tuy nhiên, đối với mục đích hiển thị, việc hiển thị lại các đường xu hướng được tìm thấy có thể là lý tưởng. Bất kể chúng được hợp nhất như thế nào, chúng có thể được tách ra bằng cửa sổ của chúng. Nói chung, chúng tôi chỉ muốn vẽ các đường xu hướng trong tương lai trong một phạm vi giới hạn để tránh làm lộn xộn cốt truyện

Giá đóng cửa với 2 Đường xu hướng Hỗ trợ/Kháng cự tốt nhất do lỗi

Lưu ý trong hình rằng đường hỗ trợ dưới nhìn từ góc độ tài chính là chính xác và hữu ích vì không có trường hợp nào giá giảm xuống dưới nó. Các đường hỗ trợ và kháng cự khác chỉ chọn các đỉnh bán nổi bật và hợp lệ theo định nghĩa của đường xu hướng, nhưng hầu như không được coi là hữu ích. Vì vậy, các đường xu hướng tốt nhất với sai số thấp nhất không nhất thiết phải là các đường hỗ trợ và kháng cự tốt nhất. Một lần nữa, ý tưởng đo diện tích được hình thành bởi đường phía trên đường giá cổ phiếu để tìm mức kháng cự và đường phía dưới đường giá cổ phiếu để hỗ trợ dường như là chìa khóa

Giá đóng cửa với 2 Đường xu hướng Hỗ trợ/Kháng cự tốt nhất theo diện tích sai nhỏ nhất mỗi ngày

Những đường xu hướng này khá tốt đối với phạm vi điểm mà chúng chứa. Các cực trị cục bộ không nổi bật đôi khi vẫn tạo ra các đường xu hướng được sử dụng hạn chế như đường kháng cự phẳng. Ngoài ra, các xu hướng rất ngắn hạn như đường hỗ trợ rất dốc có thể không liên quan đến tương lai xa và các phương pháp phỏng đoán tiếp theo có thể được sử dụng để cố gắng loại bỏ chúng mặc dù nó có thể được coi là hữu ích như trước đây trong thời gian ngắn đó. Tuy nhiên, sau điểm thứ ba, vì đó là giai đoạn phục hồi, thị trường đã đảo ngược hướng đi và vào thời điểm nó được xác định, tính hữu dụng của nó đã lỗi thời. Các đường hỗ trợ và kháng cự tốt nhất khác hoàn toàn là những gì mà một nhà phân tích hy vọng sẽ thấy. Chỉ đơn giản là không vẽ ra tương lai cũng có thể hữu ích nhưng đối với cửa sổ gần đây nhất, toàn bộ mục đích là hướng tới tương lai

Cuối cùng, thay vì hiển thị 2 đường hỗ trợ/kháng cự tốt nhất trong cả khoảng thời gian, kết quả cuối cùng có thể được tạo cửa sổ lại cho mục đích hiển thị và ngoại suy và có thể sử dụng 2 đường tốt nhất từ ​​mỗi cửa sổ

Sử dụng làm tính năng cho Machine Learning

Các đường xu hướng có thể được sử dụng để ngoại suy dữ liệu tính năng cho máy học, chẳng hạn như sử dụng mạng thần kinh LSTM (Bộ nhớ dài hạn) hoặc GRU (Đơn vị tái phát có cổng) ngay cả khi là một phần của GAN (Mạng đối thủ tạo) để dự đoán chuỗi thời gian . Có lẽ trước tiên chúng sẽ được giảm bớt cùng với các tính năng khác bằng cách sử dụng PCA (Phân tích thành phần chính) hoặc bộ mã hóa tự động

Tuy nhiên, để tránh rò rỉ dữ liệu, bất kỳ đường xu hướng nào được tìm thấy chỉ có thể được sử dụng để dự đoán các điểm trong tương lai sau điểm cuối cùng trên đường xu hướng. Bất kỳ lúc nào tại hoặc trước điểm cuối cùng, sẽ là một ví dụ điển hình về rò rỉ dữ liệu trong đó các giá trị trong tương lai được sử dụng để rò rỉ các giá trị vào quá khứ. Ngay cả việc chọn các đường xu hướng tốt nhất cũng phải được thực hiện cẩn thận, chỉ sử dụng dữ liệu trước điểm cuối cùng, mặc dù việc trực quan hóa không có giới hạn như vậy. Cần phải luôn thận trọng ở đây vì ngay cả những lỗi lập trình điển hình như sai số 1 trong tính toán cũng là những sai lầm chết người khi xử lý một nhiệm vụ chính xác như dự đoán chuỗi thời gian. Hãy nhớ chi tiết về sự khác biệt bằng số cũng nhìn về phía trước khi xử lý một hoặc hai ngày đầu tiên tùy thuộc vào độ chính xác, sau khi một xu hướng đã xảy ra. Có thể tốt hơn nếu giả sử xu hướng bắt đầu một hoặc hai ngày sau điểm cực tiểu hoặc cực đại cuối cùng để tránh loại rò rỉ này tùy thuộc vào cách sử dụng xu hướng

Để tất cả chúng cùng nhau

Có một kho lưu trữ GitHub dành cho trendln chứa tất cả mã dành cho sự nhìn chăm chú. Điều này cũng có sẵn dưới dạng gói PyPI trendln có thể được cài đặt và sử dụng dễ dàng

Phụ thuộc bao gồm numpy. Để vẽ đồ thị matplotlib và pandas là bắt buộc. Đối với các đường xu hướng Hough dựa trên hình ảnh và các đường xu hướng Hough xác suất, cần có hình ảnh scikit. Để phân biệt số, cần có findiff. Mã tạo ra tất cả các hình ảnh trong bài viết này cũng chỉ được đưa vào làm tài liệu tham khảo

Phần kết luận

Chúng tôi đã phân tích và trình bày cách sử dụng các phương pháp khác nhau bao gồm phân biệt số để tìm các điểm trục. Ngoài ra, chúng tôi đã chỉ ra cách đo lỗi trong các đường cũng như sử dụng các phương pháp xác định đường xu hướng khác nhau bao gồm sử dụng độ dốc được sắp xếp, biến đổi đường Hough và biến đổi đường Hough xác suất. Bây giờ các đường xu hướng chính xác cho hỗ trợ và kháng cự có thể được thu thập và nghiên cứu. Chúng có thể được áp dụng thêm để phân tích phức tạp hơn hoặc được sử dụng để dự báo chuyển động trong định giá chứng khoán

Hơn nữa, có một động lực để chia sẻ điều này vì nó kết hợp nhiều thông tin vào một tài nguyên với phân tích kỹ lưỡng từng khía cạnh của nhiệm vụ trong khi hầu hết các giải pháp được tuyên bố thậm chí còn chưa đáp ứng định nghĩa cơ bản của đường xu hướng

Nếu bạn thích bài viết này, vui lòng cho tôi biết và thoải mái đặt câu hỏi. Hãy theo dõi các kỹ thuật nhận dạng hình dạng như đã được ám chỉ