What is the explanation for the inverse FFT of a cross-correlated signal being shifted by some amount in the time domain? I created two signals in the time domain: signal A which is a square wave, and signal B which is a right-angled triangle wave, as shown in the picture below.





I took the FFT of these signals, multiplied channel 1 FFT with the conjugate of channel 2 FFT. Then I inverse-FFT'd to observe it back in the time domain, and I observed this: 



Now, instead if I did the correlation directly in the time domain using signal in Python like this:



txcorr = signal.correlate(wave1, wave2, mode = 'same', method='direct')


I see this output: 



So, my assumption is taking the conjugate of a signal in the frequency domain reverses the time axis? Could someone give me a more mathematical background or where I could read to understand what is happening exactly in the frequency domain? Of course, when I simply do the multiplication in the frequency domain without taking the conjugate of a signal, it produces the shape expected

Additionally, this is probably the biggest confusion: Why is the "maximum point" of the cross-correlated signal in the time domain not at 0.3s? This is what I expected from what cross-correlation page in wikipedia showed:
The issue is that the FFT version always assumes that the indices start numbering from $n=0$.  The result of the FFT version will be periodic, with period the same as the FFT length.

To show the same result as the correlation version, you need to use numpy.fft.fftshift.

Here is my attempt to generate your original signals:



Then the two versions of correlation:



which seems to do what you're seeing.

Whnn I apply fftshift to the FFT version, I get:





Code Only Below

import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
t = np.linspace(-0.2, 0.5, 500, endpoint=False)
t2 = np.linspace(-0.2, 0.5, 250, endpoint=False)
t3 = np.linspace(-0.4, 1.0, 999)
square = (signal.square(2 * np.pi * t - np.pi/2 , duty=0.2) + 1)/3
triangle = np.zeros(500)
triangle[250:500] = (signal.sawtooth(2 * np.pi * t2 - np.pi, 0 ) + 1)/2

txcorr = signal.correlate(square, triangle, mode = 'full', method='direct')
txcorr2 = np.fft.ifft(np.fft.fft(square, 999)*np.conj(np.fft.fft(triangle, 999)))

plt.figure(0)
plt.plot(t, square)
plt.plot(t, triangle)
plt.figure(1)
plt.plot(t3, txcorr)
plt.plot(t3, txcorr2)
plt.figure(2)
plt.plot(t3, np.fft.fftshift(txcorr2), '.')
plt.plot(t3, txcorr)