파이썬으로 목표값(또는 최적해) 찾기(Goal Seek)
금리옵션모형을 만들 때에는 목표값 찾기 기능이 필요합니다. 단순 추정한 선도이자율을 보정(Calibration)하기 위해서 목표값 찾기 기능이 필요한데, 엑셀에는 목표값 찾기 기능이 내장되어 있지만 파이썬에는 이러한 목표값 찾기 기능이 미리 만들어져 있지 않습니다. IRR 정도 구하는 함수는 있었지만 다른 형태로 목표값을 찾는 코드는 구글에 검색해도 잘 안나오는 것 같습니다. 그래서 목표값을 찾는 코드를 직접 만들어 보았습니다. 엑셀 처럼 아무 식이나 넣고 돌리면 값이 나오는 수준으로까지는 구현을 못하였고, 1보다 작은 소수점에서 출발하여 소수점 16째자리까 숫자를 대입해서 목표값에 가장 근접한 결과값을 보이는 숫자를 찾는 방식으로 구현하였습니다. 따라서 최초에 반복문을 시작하는 범위를 지정해 주어야 합니다.

[1]은 소수점 16째 자리까지 보이게 하는 명령어입니다.
[2]는 x를 할인율로 하는 현재가치를 구하는 함수입니다. 꼭 현재가치로 해야하는 것은 아니고 다른 식을 넣어도 됩니다. 저는 목적상 목표 현재가치에 가장 근접한 x를 구하는 기능이 필요하기 때문에 현재가치를 가지고 만들었습니다.
[3]은 현재가치와 1과의 차이를 절대값으로 구하는 함수입니다. 1 이외에 다른 숫자가 들어가도 됩니다. 다만 3.5보다 크게 되면 범위를 다르게 지정해 주어야 합니다. 왜냐하면 pv(x)가 3.5가 되면 x가 0이되고 여기를 벗어나면 (-)값이 되어야 하기 때문입니다.

[4]는 x 값에 0.01부터 1.00까지 입력하였을 때의 결과값으로 만든 리스트입니다. range()함수는 정수에 적용되기 때문에 0에서 100까지로 범위를 지정하고 100으로 나누었습니다.

[5]는 리스트에 있는 결과값들 중에서 가장 작은 차이의 값과 그 값의 인덱스를 출력한 것입니다. 66번 인덱스에서 가장 작은 차이로 계산되었습니다.
[6] 66번 인덱스라 함은 0.66을 입력하였을 때 결과값입니다. 이를 num1이라는 변수에 저장해 둡니다.

[7]에서 step2라는 리스트를 생성하고 0.66 - 0.005부터 0.66 + 0.005까지를 x값에 입력하여 결과값을 집계하였습니다. -0.009부터 +0.009까지 하는 것이 더 안전할 것 같기도 합니다. 일단 이 경우는 이렇게 해서 결과가 나왔습니다 ㅎ

[8]은 차이가 가장 작은 결과값과 그 인덱스를 출력한 것입니다.
[9]는 소수점 세째자리 숫자를 num2에 저장한 것닙니다. 여기서 최소값의 인덱스에서 5를 빼준 이유는 인덱스 0이 -0.005이기 때문입니다. 인덱스 1은 -0.004가 될 것이고, 인덱스 10은 +0.005가 될 것입니다. 따라서 인덱스 9는 0.004입니다.
[10]은 위에서 구한 num1과 num2를 합산하여 diff(x) 함수에 집어넣었을 때 결과값이 더 감소한 것을 확인한 것입니다. num1을 입력하였을 때 0.005*** 어쩌고로 값이 나왔는데 num2까지 입력하였더니 0.0003*** 어쩌고로 차이가 크게 감소하였습니다. 이렇게 소수점 16번째까지 내려가면서 하면 결과가 나오기는 하지만 노가다가 될 것이며 시간도 오래 걸릴 것이므로 우아하게 아래와 같은 반복문을 작성하였습니다.

[11]은 number와 decimal을 인수로 입력하면 직전까지 구해진 숫자에 decimal 에 입력한 자리수에서 -5에서 +5까지 값을 입력해서 최소값을 만들어내는 숫자를 산출하는 함수입니다. num1과 3을 변수로 입력하였더니 소수점 셋째자리 숫자로 0.004가 나왔습니다. [10]에서 계산한 결과와 동일합니다.
[12]는 number에 num1=0.66을 입력하고 소수점 3째 자리부터 16째 자리까지 계속 결과값을 최소화시키면서 최적해를 구하는 반복문입니다.
[13]은 [12]에서 도출한 최적해를 diff(x) 함수에 x값으로 입력하였을 때 결과값이 소수점 16째 자리에서 0이 도출되는 것을 확인한 것입니다.
사실은 위의 과정을 무시하고 0부터 10의 (-16)제곱 단위로 하나씩 입력해서 결과값을 구해도 됩니다. 그렇게 할 경우 무려 10의 16제곱회의 시도가 발생하는 것이기 때문에 비효율적인 것 같습니다. 위의 코드는 num1을 구할때 100번의 시도가 있고 소수점 3째부터 16째자리까지는 각 자리수마다 11번의 시도가 있기 때문에 총 132번의 시도가 있는 것이고 다 합쳐서 232번의 시행착오로 결과값을 구한 것입니다. 이것도 사람이 하면 너무 힘들겠지만 컴터한테는 시키는 거니까 괜찮을 것 같습니다.
다른 형태의 방정식도 식을 정의하고 대략적인 범위를 지정해 준다면 위와 같은 방식으로 풀 수 있지 않을까 생각합니다. 예를 들어 결과값이 0에서 1,000조 사이에 있다고 하면 일단 최초에 1,000회 시도를 통해서 조단위 숫자를 먼저 추정하고 거기서부터 1단위까지 내려오면 추가로 백몇회만 시도하면 결과값을 구할 수 있을 것 같습니다.
저는 최적해나 목표값 찾기를 검색할 때 파이썬으로 검색이 안되었는데, 누군가 비슷한 고민을 하신다면 도움이 되면 좋겠습니다. 이공계 분들은 당연히 스스로 잘 하실 것 같고, 저 같은 문과 출신 분들에게는 도움이 될 수도 있을 것 같습니다.
긴 글 읽어주셔서 감사합니다.